├── .gitignore ├── go.mod ├── reply.go ├── server_test.go ├── port_test.go ├── LICENSE ├── common.go ├── request_test.go ├── address_test.go ├── request.go ├── port.go ├── conn.go ├── transport.go ├── protocol.go ├── auth.go ├── client_test.go ├── README.md ├── address.go ├── client.go └── server.go /.gitignore: -------------------------------------------------------------------------------- 1 | main/ 2 | .vscode/ 3 | .idea/ -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/haochen233/socks5 2 | 3 | go 1.16 4 | -------------------------------------------------------------------------------- /reply.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | // Reply a reply formed as follows: 4 | // +----+-----+-------+------+----------+----------+ 5 | // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 6 | // +----+-----+-------+------+----------+----------+ 7 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 8 | // +----+-----+-------+------+----------+----------+ 9 | type Reply struct { 10 | VER 11 | REP 12 | RSV uint8 13 | *Address 14 | } 15 | -------------------------------------------------------------------------------- /server_test.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "testing" 7 | ) 8 | 9 | func TestOpError(t *testing.T) { 10 | ip := net.IPv4(127, 0, 0, 1) 11 | clientIP := &net.IPAddr{IP: ip} 12 | err := &OpError{ 13 | Op: "write", 14 | VER: Version5, 15 | Addr: clientIP, 16 | Step: "authentication", 17 | Err: errors.New("user admin has no password."), 18 | } 19 | 20 | expected := "socks5 write 127.0.0.1 authentication:user admin has no password." 21 | if err.Error() != expected { 22 | t.Errorf("expected: %s\ngot: %s", expected, err.Error()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /port_test.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "log" 5 | "testing" 6 | ) 7 | 8 | func TestGetRandomPort(t *testing.T) { 9 | // right tcp network 10 | for i := 0; i < 50; i++ { 11 | err, port := GetRandomPort("tcp") 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | log.Printf("get tcp port: %d", port) 16 | } 17 | 18 | // right udp network 19 | for i := 0; i < 50; i++ { 20 | err, port := GetRandomPort("udp") 21 | if err != nil { 22 | t.Error(err) 23 | } 24 | log.Printf("get udp port: %d", port) 25 | } 26 | } 27 | 28 | func TestGetRandomPort_Err(t *testing.T) { 29 | err, _ := GetRandomPort("kcp") 30 | if err.Error() != "unknown network type kcp" { 31 | t.Error(err) 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 haochen233 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /common.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io" 7 | ) 8 | 9 | var errUnexpectMinusLength = errors.New("arg number should not be minus") 10 | 11 | // ReadNBytes wrap io.ReadFull. read n bytes. 12 | // The error is EOF only if no bytes were read. 13 | // If an EOF happens after reading some but not all the bytes, 14 | // ReadFull returns ErrUnexpectedEOF. 15 | func ReadNBytes(reader io.Reader, n int) ([]byte, error) { 16 | if n < 0 { 17 | return nil, errUnexpectMinusLength 18 | } 19 | data := make([]byte, n) 20 | _, err := io.ReadFull(reader, data) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | return data, nil 26 | } 27 | 28 | // ReadUntilNULL Read all not Null byte. 29 | // Until read first Null byte(all zero bits) 30 | func ReadUntilNULL(reader io.Reader) ([]byte, error) { 31 | data := &bytes.Buffer{} 32 | b := make([]byte, 1) 33 | for { 34 | _, err := reader.Read(b) 35 | if err != nil { 36 | if err == io.EOF { 37 | return nil, nil 38 | } 39 | return nil, err 40 | } 41 | 42 | if b[0] == NULL { 43 | return data.Bytes(), nil 44 | } 45 | data.WriteByte(b[0]) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /request_test.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "bytes" 5 | "net" 6 | "testing" 7 | ) 8 | 9 | func TestPackUDPData(t *testing.T) { 10 | data := []byte("udp") 11 | addr := &Address{ 12 | Addr: net.IPv4(1, 1, 1, 1).To4(), 13 | ATYPE: IPV4_ADDRESS, 14 | Port: 1080, 15 | } 16 | udpData, err := PackUDPData(addr, data) 17 | if err != nil { 18 | t.Error(err) 19 | } 20 | 21 | if len(udpData) != 13 { 22 | t.Errorf("get length: %d, want length: %d", len(udpData), 13) 23 | } 24 | 25 | bytes.Equal(udpData, []byte{0x00, 0x00, 0x00, 1, 1, 1, 1, 1, 0x04, 0x38}) 26 | } 27 | 28 | func TestUnpackUDPData(t *testing.T) { 29 | data := []byte{0x00, 0x00, 0x00, 1, 1, 1, 1, 1, 0x04, 0x38, 'a', 'b', 'c'} 30 | wantAddr := net.IPv4(1, 1, 1, 1) 31 | wantPayload := []byte{'a', 'b', 'c'} 32 | wantATYPE := IPV4_ADDRESS 33 | var wantPort uint16 = 1080 34 | addr, payload, err := UnpackUDPData(data) 35 | if err != nil { 36 | t.Error(err) 37 | } 38 | if !bytes.Equal(payload, wantPayload) { 39 | t.Errorf("want: %v get %v", wantPayload, payload) 40 | } 41 | 42 | if !addr.Addr.Equal(wantAddr) { 43 | t.Errorf("want: %s get %s", wantAddr.String(), addr.Addr.String()) 44 | } 45 | 46 | if wantATYPE != addr.ATYPE { 47 | t.Errorf("want: %#x get %#x", wantATYPE, addr.ATYPE) 48 | } 49 | 50 | if addr.Port != wantPort { 51 | t.Errorf("want: %d get %d", wantATYPE, addr.Port) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /address_test.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "net" 5 | "testing" 6 | ) 7 | 8 | var addressTests = []struct { 9 | *Address 10 | String string 11 | Bytes []byte 12 | }{ 13 | // ipv4 14 | { 15 | &Address{net.IPv4(127, 0, 0, 1).To4(), IPV4_ADDRESS, 1080}, 16 | "127.0.0.1:1080", 17 | []byte{0x01, 127, 0, 0, 1, 0x04, 0x38}, 18 | }, 19 | { 20 | &Address{net.IPv4(172, 16, 1, 1).To4(), IPV4_ADDRESS, 1080}, 21 | "172.16.1.1:1080", 22 | []byte{0x01, 172, 16, 1, 1, 0x04, 0x38}, 23 | }, 24 | { 25 | &Address{net.IPv4(192, 168, 1, 1).To4(), IPV4_ADDRESS, 1080}, 26 | "192.168.1.1:1080", 27 | []byte{0x01, 192, 168, 1, 1, 0x04, 0x38}, 28 | }, 29 | { 30 | &Address{net.IPv4(0, 0, 0, 0).To4(), IPV4_ADDRESS, 1080}, 31 | "0.0.0.0:1080", 32 | []byte{0x01, 0, 0, 0, 0, 0x04, 0x38}, 33 | }, 34 | // ipv6 35 | { 36 | &Address{net.IPv6zero, IPV6_ADDRESS, 1080}, 37 | "[::]:1080", 38 | []byte{0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x04, 0x38}, 39 | }, 40 | {&Address{net.IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}, IPV6_ADDRESS, 1080}, 41 | "[2001:4860:0:2001::68]:1080", 42 | []byte{0x01, 0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68, 0x04, 0x38}, 43 | }, 44 | // domain name 45 | { 46 | &Address{[]byte("localhost"), DOMAINNAME, 1080}, 47 | "localhost:1080", 48 | []byte{}, 49 | }, 50 | } 51 | 52 | func TestAddress_String(t *testing.T) { 53 | for _, a := range addressTests { 54 | if a.Address.String() != a.String { 55 | t.Errorf("get: %s, want: %s", a.Address.String(), a.String) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /request.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | ) 7 | 8 | // Request The SOCKS request is formed as follows: 9 | // +----+-----+-------+------+----------+----------+ 10 | // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 11 | // +----+-----+-------+------+----------+----------+ 12 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 13 | // +----+-----+-------+------+----------+----------+ 14 | type Request struct { 15 | VER 16 | CMD 17 | RSV uint8 18 | *Address 19 | } 20 | 21 | // UDPHeader Each UDP datagram carries a UDP request 22 | // header with it: 23 | // +----+------+------+----------+----------+----------+ 24 | // |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | 25 | // +----+------+------+----------+----------+----------+ 26 | // | 2 | 1 | 1 | Variable | 2 | Variable | 27 | // +----+------+------+----------+----------+----------+ 28 | type UDPHeader struct { 29 | RSV uint16 30 | FRAG uint8 31 | *Address 32 | Data []byte 33 | } 34 | 35 | var errEmptyPayload = errors.New("empty payload") 36 | 37 | // PackUDPData add UDP request header before payload. 38 | func PackUDPData(addr *Address, payload []byte) ([]byte, error) { 39 | if len(payload) == 0 { 40 | return nil, errEmptyPayload 41 | } 42 | if addr == nil { 43 | return nil, errors.New("addr is nil") 44 | } 45 | // RSV, FRAG 46 | data := []byte{0x00, 0x00, 0x00} 47 | dest, err := addr.Bytes(Version5) 48 | if err != nil { 49 | return nil, err 50 | } 51 | // ATYP, DEST.IP, DEST.PORT 52 | data = append(data, dest...) 53 | // DATA 54 | data = append(data, payload...) 55 | return data, nil 56 | } 57 | 58 | // UnpackUDPData split UDP header and payload. 59 | func UnpackUDPData(data []byte) (addr *Address, payload []byte, err error) { 60 | // trim RSV, FRAG 61 | data = data[3:] 62 | buf := bytes.NewBuffer(data) 63 | addr, _, err = readAddress(buf, Version5) 64 | if err != nil { 65 | return nil, nil, err 66 | } 67 | 68 | payload = buf.Bytes() 69 | return 70 | } 71 | -------------------------------------------------------------------------------- /port.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | // GetRandomPort return a random port by specific network. 11 | // The network must be "tcp", "udp". 12 | func GetRandomPort(network string) (err error, port uint16) { 13 | network = strings.ToLower(network) 14 | addr := "0.0.0.0:0" 15 | 16 | switch network { 17 | case "tcp", "tcp4", "tcp6": 18 | tcpAddr, err := net.ResolveTCPAddr(network, addr) 19 | if err != nil { 20 | return err, 0 21 | } 22 | ln, err := net.ListenTCP(network, tcpAddr) 23 | if err != nil { 24 | return err, 0 25 | } 26 | 27 | _, portStr, err := net.SplitHostPort(ln.Addr().String()) 28 | p, err := strconv.Atoi(portStr) 29 | port = uint16(p) 30 | 31 | err = ln.Close() 32 | if err != nil { 33 | return err, 0 34 | } 35 | return err, port 36 | case "udp", "udp4", "udp6": 37 | udpAddr, err := net.ResolveUDPAddr(network, addr) 38 | if err != nil { 39 | return err, 0 40 | } 41 | ln, err := net.ListenUDP(network, udpAddr) 42 | if err != nil { 43 | return err, 0 44 | } 45 | 46 | _, portStr, err := net.SplitHostPort(ln.LocalAddr().String()) 47 | p, err := strconv.Atoi(portStr) 48 | port = uint16(p) 49 | 50 | err = ln.Close() 51 | if err != nil { 52 | return err, 0 53 | } 54 | return err, port 55 | default: 56 | return errors.New("unknown network type " + network), 0 57 | } 58 | } 59 | 60 | // IsFreePort indicates the port is available. 61 | // The network must be "tcp", "udp". 62 | func IsFreePort(network string, port uint16) error { 63 | network = strings.ToLower(network) 64 | portStr := strconv.Itoa(int(port)) 65 | addr := "0.0.0.0:" + portStr 66 | 67 | switch network { 68 | case "tcp": 69 | tcpAddr, err := net.ResolveTCPAddr(network, addr) 70 | if err != nil { 71 | return err 72 | } 73 | ln, err := net.ListenTCP(network, tcpAddr) 74 | if err != nil { 75 | return err 76 | } 77 | 78 | ln.Close() 79 | if err != nil { 80 | return err 81 | } 82 | return nil 83 | case "udp": 84 | udpAddr, err := net.ResolveUDPAddr(network, addr) 85 | if err != nil { 86 | return err 87 | } 88 | ln, err := net.ListenUDP(network, udpAddr) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | ln.Close() 94 | if err != nil { 95 | return err 96 | } 97 | return nil 98 | default: 99 | return errors.New("unknown network type " + network) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /conn.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | // UDPConn be associated with TCP connections. 11 | // The UDP connection will close immediately, When TCP connection closed, 12 | // UDPConn only use in UDP_ASSOCIATE command. 13 | type UDPConn struct { 14 | mu sync.Mutex 15 | udp *net.UDPConn 16 | tcp *net.TCPConn 17 | closeChan chan struct{} 18 | } 19 | 20 | // NewUDPConn get a *UDPConn through provide a tcp and udp connection. 21 | // the tcp connection is used for socks UDP_ASSOCIATE handshake. 22 | // the udp connection is used for socks udp forwarding. 23 | // 24 | // After UDP_ASSOCIATE handshake, the tcp transit nothing. Its only 25 | // function is udp relay connection still running. 26 | // 27 | // If one of them shuts off, it will close them all. 28 | func NewUDPConn(udp *net.UDPConn, tcp *net.TCPConn) *UDPConn { 29 | if udp == nil || tcp == nil { 30 | return nil 31 | } 32 | 33 | u := &UDPConn{ 34 | udp: udp, 35 | tcp: tcp, 36 | closeChan: make(chan struct{}), 37 | } 38 | 39 | go func() { 40 | // guard tcp connection, if it closed should close tcp relay too. 41 | io.Copy(io.Discard, tcp) 42 | u.Close() 43 | }() 44 | 45 | return u 46 | } 47 | 48 | func (u *UDPConn) LocalAddr() net.Addr { 49 | return u.udp.LocalAddr() 50 | } 51 | 52 | func (u *UDPConn) RemoteAddr() net.Addr { 53 | return u.udp.RemoteAddr() 54 | } 55 | 56 | func (u *UDPConn) SetDeadline(t time.Time) error { 57 | return u.udp.SetDeadline(t) 58 | } 59 | 60 | func (u *UDPConn) SetReadDeadline(t time.Time) error { 61 | return u.udp.SetReadDeadline(t) 62 | } 63 | 64 | func (u *UDPConn) SetWriteDeadline(t time.Time) error { 65 | return u.udp.SetWriteDeadline(t) 66 | } 67 | 68 | func (u *UDPConn) Read(b []byte) (n int, err error) { 69 | return u.udp.Read(b) 70 | } 71 | 72 | func (u *UDPConn) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) { 73 | return u.udp.WriteToUDP(b, addr) 74 | } 75 | 76 | func (u *UDPConn) ReadFromUDP(b []byte) (int, *net.UDPAddr, error) { 77 | return u.udp.ReadFromUDP(b) 78 | } 79 | 80 | func (u *UDPConn) Write(b []byte) (n int, err error) { 81 | return u.udp.Write(b) 82 | } 83 | 84 | func (u *UDPConn) Close() error { 85 | var err error 86 | u.mu.Lock() 87 | defer u.mu.Unlock() 88 | 89 | ch := u.getCloseChanLocked() 90 | select { 91 | case <-ch: 92 | return nil 93 | default: 94 | if err2 := u.udp.Close(); err2 != nil { 95 | err = err2 96 | } 97 | if err2 := u.tcp.Close(); err2 != nil { 98 | err = err2 99 | } 100 | close(u.closeChan) 101 | } 102 | return err 103 | } 104 | 105 | func (u *UDPConn) CloseCh() <-chan struct{} { 106 | u.mu.Lock() 107 | defer u.mu.Unlock() 108 | return u.getCloseChanLocked() 109 | } 110 | 111 | func (u *UDPConn) getCloseChanLocked() <-chan struct{} { 112 | if u.closeChan == nil { 113 | u.closeChan = make(chan struct{}) 114 | } 115 | return u.closeChan 116 | } 117 | -------------------------------------------------------------------------------- /transport.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "strings" 7 | "sync" 8 | ) 9 | 10 | // Transporter transmit data between client and dest server. 11 | type Transporter interface { 12 | TransportTCP(client *net.TCPConn, remote *net.TCPConn) <-chan error 13 | TransportUDP(server *UDPConn, request *Request) error 14 | } 15 | 16 | type transport struct { 17 | } 18 | 19 | const maxLenOfDatagram = 65507 20 | 21 | var transportPool = &sync.Pool{ 22 | New: func() interface{} { 23 | return make([]byte, maxLenOfDatagram) 24 | }, 25 | } 26 | 27 | // TransportTCP use io.CopyBuffer transmit data. 28 | func (t *transport) TransportTCP(client *net.TCPConn, remote *net.TCPConn) <-chan error { 29 | errCh := make(chan error) 30 | var wg = sync.WaitGroup{} 31 | 32 | f := func(dst *net.TCPConn, src *net.TCPConn) { 33 | defer wg.Done() 34 | buf := transportPool.Get().([]byte) 35 | defer transportPool.Put(buf) 36 | _, err := io.CopyBuffer(dst, src, buf) 37 | errCh <- err 38 | } 39 | 40 | wg.Add(2) 41 | go func() { 42 | wg.Wait() 43 | defer client.Close() 44 | defer remote.Close() 45 | close(errCh) 46 | }() 47 | 48 | go f(remote, client) 49 | go f(client, remote) 50 | 51 | return errCh 52 | } 53 | 54 | // TransportUDP forwarding UDP packet between client and dest. 55 | func (t *transport) TransportUDP(server *UDPConn, request *Request) error { 56 | // Client udp address, limit access to the association. 57 | clientAddr, err := request.Address.UDPAddr() 58 | if err != nil { 59 | return err 60 | } 61 | 62 | // Record dest address, limit access to the association. 63 | forwardAddr := make(map[string]struct{}) 64 | buf := transportPool.Get().([]byte) 65 | defer transportPool.Put(buf) 66 | 67 | defer server.Close() 68 | for { 69 | select { 70 | default: 71 | // Receive data from remote. 72 | n, addr, err := server.ReadFromUDP(buf) 73 | if err != nil { 74 | return err 75 | } 76 | 77 | // Should unpack data when data from client. 78 | if strings.EqualFold(clientAddr.String(), addr.String()) { 79 | destAddr, payload, err := UnpackUDPData(buf[:n]) 80 | if err != nil { 81 | return err 82 | } 83 | 84 | destUDPAddr, err := destAddr.UDPAddr() 85 | if err != nil { 86 | return err 87 | } 88 | forwardAddr[destUDPAddr.String()] = struct{}{} 89 | 90 | // send payload to dest address 91 | _, err = server.WriteToUDP(payload, destUDPAddr) 92 | if err != nil { 93 | return err 94 | } 95 | } 96 | 97 | // Should pack data when data from dest host 98 | if _, ok := forwardAddr[addr.String()]; ok { 99 | address, err := ParseAddress(addr.String()) 100 | if err != nil { 101 | return err 102 | } 103 | 104 | // packed Data 105 | packedData, err := PackUDPData(address, buf[:n]) 106 | if err != nil { 107 | return err 108 | } 109 | 110 | // send payload to client 111 | _, err = server.WriteToUDP(packedData, clientAddr) 112 | if err != nil { 113 | return err 114 | } 115 | } 116 | case <-server.CloseCh(): 117 | return nil 118 | } 119 | } 120 | } 121 | 122 | var DefaultTransporter Transporter = &transport{} 123 | -------------------------------------------------------------------------------- /protocol.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import "fmt" 4 | 5 | type VersionError struct { 6 | VER 7 | } 8 | 9 | func (v *VersionError) Error() string { 10 | return fmt.Sprintf("error socks protocol version: %d", v.VER) 11 | } 12 | 13 | // VER indicates protocol version 14 | type VER = uint8 15 | 16 | const ( 17 | Version4 = 0x04 18 | Version5 = 0x05 19 | ) 20 | 21 | type MethodError struct { 22 | METHOD 23 | } 24 | 25 | func (m *MethodError) Error() string { 26 | if _, ok := method2Str[m.METHOD]; ok { 27 | return fmt.Sprintf("don't support this method %s", method2Str[m.METHOD]) 28 | } else { 29 | return fmt.Sprintf("unknown mehotd %#x", m.METHOD) 30 | } 31 | } 32 | 33 | // METHOD Defined authentication methods 34 | type METHOD = uint8 35 | 36 | const ( 37 | NO_AUTHENTICATION_REQUIRED METHOD = 0x00 38 | GSSAPI METHOD = 0x01 39 | USERNAME_PASSWORD METHOD = 0x02 40 | IANA_ASSIGNED METHOD = 0x03 41 | NO_ACCEPTABLE_METHODS METHOD = 0xff 42 | ) 43 | 44 | var method2Str = map[METHOD]string{ 45 | NO_AUTHENTICATION_REQUIRED: "NO_AUTHENTICATION_REQUIRED", 46 | GSSAPI: "GSSAPI", 47 | USERNAME_PASSWORD: "USERNAME_PASSWORD", 48 | IANA_ASSIGNED: "IANA_ASSIGNED", 49 | NO_ACCEPTABLE_METHODS: "NO_ACCEPTABLE_METHODS", 50 | } 51 | 52 | // CMDError cmd error type 53 | type CMDError struct { 54 | CMD 55 | } 56 | 57 | func (c *CMDError) Error() string { 58 | if _, ok := cmd2Str[c.CMD]; !ok { 59 | return fmt.Sprintf("unknown command:%#x", c.CMD) 60 | } 61 | return fmt.Sprintf("don't support this command:%s", cmd2Str[c.CMD]) 62 | } 63 | 64 | // CMD is one of a field in Socks5 Request 65 | type CMD = uint8 66 | 67 | const ( 68 | CONNECT CMD = 0x01 69 | BIND CMD = 0x02 70 | UDP_ASSOCIATE CMD = 0x03 71 | ) 72 | 73 | var cmd2Str = map[CMD]string{ 74 | CONNECT: "CONNECT", 75 | BIND: "BIND", 76 | UDP_ASSOCIATE: "UDP_ASSOCIATE", 77 | Rejected: "Rejected", 78 | Granted: "Granted", 79 | } 80 | 81 | type REPError struct { 82 | REP 83 | } 84 | 85 | func (r *REPError) Error() string { 86 | if _, ok := cmd2Str[r.REP]; !ok { 87 | return fmt.Sprintf("unknown rep:%#x", r.REP) 88 | } 89 | return fmt.Sprintf("don't support this rep:%s", rep2Str[r.REP]) 90 | } 91 | 92 | // REP is one of a filed in Socks5 Reply 93 | type REP = uint8 94 | 95 | //socks5 reply 96 | const ( 97 | SUCCESSED REP = 0x00 98 | GENERAL_SOCKS_SERVER_FAILURE REP = 0x01 99 | CONNECTION_NOT_ALLOW_BY_RULESET REP = 0x02 100 | NETWORK_UNREACHABLE REP = 0x03 101 | HOST_UNREACHABLE REP = 0x04 102 | CONNECTION_REFUSED REP = 0x05 103 | TTL_EXPIRED REP = 0x06 104 | COMMAND_NOT_SUPPORTED REP = 0x07 105 | ADDRESS_TYPE_NOT_SUPPORTED REP = 0x08 106 | UNASSIGNED REP = 0x09 107 | ) 108 | 109 | var rep2Str = map[REP]string{ 110 | SUCCESSED: "successes", 111 | GENERAL_SOCKS_SERVER_FAILURE: "general_socks_server_failure", 112 | CONNECTION_NOT_ALLOW_BY_RULESET: "connection_not_allow_by_ruleset", 113 | NETWORK_UNREACHABLE: "network_unreachable", 114 | HOST_UNREACHABLE: "host_unreachable", 115 | CONNECTION_REFUSED: "connection_refused", 116 | TTL_EXPIRED: "ttl_expired", 117 | COMMAND_NOT_SUPPORTED: "command_not_supported", 118 | ADDRESS_TYPE_NOT_SUPPORTED: "address_type_not_supported", 119 | UNASSIGNED: "unassigned", 120 | Granted: "granted", 121 | Rejected: "rejected", 122 | } 123 | 124 | //socks4 reply 125 | const ( 126 | // Granted means server allow client request 127 | Granted = 90 128 | // Rejected means server refuse client request 129 | Rejected = 91 130 | ) 131 | 132 | type AtypeError struct { 133 | ATYPE 134 | } 135 | 136 | func (a *AtypeError) Error() string { 137 | return fmt.Sprintf("unknown address type:%#x", a.ATYPE) 138 | } 139 | 140 | // ATYPE indicates address type in Request and Reply struct 141 | type ATYPE = uint8 142 | 143 | const ( 144 | IPV4_ADDRESS ATYPE = 0x01 145 | DOMAINNAME ATYPE = 0x03 146 | IPV6_ADDRESS ATYPE = 0x04 147 | ) 148 | 149 | var atype2Str = map[ATYPE]string{ 150 | IPV4_ADDRESS: "IPV4_ADDRESS", 151 | DOMAINNAME: "DOMAINNAME", 152 | IPV6_ADDRESS: "IPV6_ADDRESS", 153 | } 154 | 155 | const NULL byte = 0 156 | -------------------------------------------------------------------------------- /auth.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "hash" 7 | "io" 8 | "sync" 9 | ) 10 | 11 | // Authenticator provides socks5's authentication sub negotiation. 12 | type Authenticator interface { 13 | Authenticate(in io.Reader, out io.Writer) error 14 | } 15 | 16 | // NoAuth NO_AUTHENTICATION_REQUIRED implementation. 17 | type NoAuth struct { 18 | } 19 | 20 | // Authenticate NO_AUTHENTICATION_REQUIRED Authentication for socks5 Server and Client. 21 | func (n NoAuth) Authenticate(in io.Reader, out io.Writer) error { 22 | return nil 23 | } 24 | 25 | // UserPwdAuth provides socks5 Server Username/Password Authenticator. 26 | type UserPwdAuth struct { 27 | UserPwdStore 28 | } 29 | 30 | // Authenticate provide socks5 Server Username/Password authentication. 31 | func (u UserPwdAuth) Authenticate(in io.Reader, out io.Writer) error { 32 | uname, passwd, err := u.ReadUserPwd(in) 33 | if err != nil { 34 | return err 35 | } 36 | 37 | err = u.Validate(string(uname), string(passwd)) 38 | if err != nil { 39 | reply := []byte{1, 1} 40 | _, err1 := out.Write(reply) 41 | if err1 != nil { 42 | return err 43 | } 44 | return err 45 | } 46 | 47 | //authentication successful,then send reply to client 48 | reply := []byte{1, 0} 49 | _, err = out.Write(reply) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | return nil 55 | } 56 | 57 | // ReadUserPwd read Username/Password request from client 58 | // return username and password. 59 | // Username/Password request format is as follows: 60 | // +----+------+----------+------+----------+ 61 | // |VER | ULEN | UNAME | PLEN | PASSWD | 62 | // +----+------+----------+------+----------+ 63 | // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | 64 | // +----+------+----------+------+----------+ 65 | // For standard details, please see (https://www.rfc-editor.org/rfc/rfc1929.html) 66 | func (u UserPwdAuth) ReadUserPwd(in io.Reader) ([]byte, []byte, error) { 67 | 68 | ulen, err := ReadNBytes(in, 2) 69 | if err != nil { 70 | return nil, nil, err 71 | } 72 | 73 | uname, err := ReadNBytes(in, int(ulen[1])) 74 | if err != nil { 75 | return nil, nil, err 76 | } 77 | 78 | plen, err := ReadNBytes(in, 1) 79 | if err != nil { 80 | return nil, nil, err 81 | } 82 | 83 | passwd := make([]byte, plen[0]) 84 | passwd, err = ReadNBytes(in, int(plen[0])) 85 | if err != nil { 86 | return nil, nil, err 87 | } 88 | 89 | return uname, passwd, nil 90 | } 91 | 92 | // UserPwdStore provide username and password storage. 93 | type UserPwdStore interface { 94 | Set(username string, password string) error 95 | Del(username string) error 96 | Validate(username string, password string) error 97 | } 98 | 99 | // MemoryStore store username&password in memory. 100 | // the password is encrypt with hash method. 101 | type MemoryStore struct { 102 | Users map[string][]byte 103 | mu sync.Mutex 104 | hash.Hash 105 | algoSecret string 106 | } 107 | 108 | // NewMemeryStore return a new MemoryStore 109 | func NewMemeryStore(algo hash.Hash, secret string) *MemoryStore { 110 | return &MemoryStore{ 111 | Users: make(map[string][]byte), 112 | Hash: algo, 113 | algoSecret: secret, 114 | } 115 | } 116 | 117 | // Set the mapping of username and password. 118 | func (m *MemoryStore) Set(username string, password string) error { 119 | m.mu.Lock() 120 | defer m.mu.Unlock() 121 | build := bytes.NewBuffer(nil) 122 | build.WriteString(password + m.algoSecret) 123 | cryptPasswd := m.Hash.Sum(build.Bytes()) 124 | m.Users[username] = cryptPasswd 125 | return nil 126 | } 127 | 128 | // UserNotExist the error type used in UserPwdStore.Del() method and 129 | // UserPwdStore.Validate method. 130 | type UserNotExist struct { 131 | username string 132 | } 133 | 134 | func (u UserNotExist) Error() string { 135 | return fmt.Sprintf("user %s don't exist", u.username) 136 | } 137 | 138 | // Del delete by username 139 | func (m *MemoryStore) Del(username string) error { 140 | m.mu.Lock() 141 | defer m.mu.Unlock() 142 | if _, ok := m.Users[username]; !ok { 143 | return UserNotExist{username: username} 144 | } 145 | 146 | delete(m.Users, username) 147 | return nil 148 | } 149 | 150 | // Validate validate username and password. 151 | func (m *MemoryStore) Validate(username string, password string) error { 152 | m.mu.Lock() 153 | defer m.mu.Unlock() 154 | if _, ok := m.Users[username]; !ok { 155 | return UserNotExist{username: username} 156 | } 157 | 158 | build := bytes.NewBuffer(nil) 159 | build.WriteString(password + m.algoSecret) 160 | cryptPasswd := m.Hash.Sum(build.Bytes()) 161 | if !bytes.Equal(cryptPasswd, m.Users[username]) { 162 | return fmt.Errorf("user %s has bad password", username) 163 | } 164 | return nil 165 | } 166 | -------------------------------------------------------------------------------- /client_test.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "encoding/binary" 5 | "log" 6 | "net" 7 | "net/http" 8 | "strconv" 9 | "testing" 10 | ) 11 | 12 | func runLocalServer(addr string, bindIP string) { 13 | // create socks server. 14 | srv := &Server{ 15 | // socks server listen address. 16 | Addr: addr, 17 | // UDP assocaite and bind command listen ip. 18 | // Don't need port, the port will automatically chosen. 19 | BindIP: bindIP, 20 | // if nil server will provide no authentication required method. 21 | Authenticators: nil, 22 | } 23 | 24 | // start listen 25 | err := srv.ListenAndServe() 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | } 30 | 31 | func TestClient_UDPForward(t *testing.T) { 32 | go runLocalServer("127.0.0.1:1080", "127.0.0.1") 33 | c := Client{ 34 | ProxyAddr: "127.0.0.1:1080", 35 | Timeout: 0, 36 | Auth: map[METHOD]Authenticator{ 37 | USERNAME_PASSWORD: &UserPasswd{Username: "admin", Password: "123456"}, 38 | NO_AUTHENTICATION_REQUIRED: NoAuth{}, 39 | }, 40 | } 41 | 42 | local := "127.0.0.1:19999" 43 | 44 | _, err := c.UDPForward(local) 45 | if err != nil { 46 | log.Println(err) 47 | return 48 | } 49 | } 50 | 51 | func TestClient_Connect(t *testing.T) { 52 | go runLocalServer("127.0.0.1:1080", "127.0.0.1") 53 | c := Client{ 54 | ProxyAddr: "127.0.0.1:1080", 55 | Auth: map[METHOD]Authenticator{ 56 | USERNAME_PASSWORD: &UserPasswd{ 57 | Username: "admin", 58 | Password: "123456", 59 | }, 60 | NO_AUTHENTICATION_REQUIRED: &NoAuth{}, 61 | }, 62 | } 63 | 64 | // socks4 connect 65 | dest := "www.baidu.com:80" 66 | conn, err := c.Connect(Version4, dest) 67 | if err != nil { 68 | t.Fatal(err) 69 | return 70 | } 71 | 72 | // send http Get request via socks proxy. 73 | req, err := http.NewRequest("GET", "http://www.baidu.com", nil) 74 | if err != nil { 75 | t.Fatal(err) 76 | return 77 | } 78 | 79 | err = req.WriteProxy(conn) 80 | if err != nil { 81 | t.Fatal(err) 82 | } 83 | 84 | // socks5 connect 85 | conn5, err := c.Connect(Version5, dest) 86 | if err != nil { 87 | t.Fatal(err) 88 | } 89 | 90 | err = req.WriteProxy(conn5) 91 | if err != nil { 92 | t.Fatal(err) 93 | } 94 | } 95 | 96 | func TestClient_Bind(t *testing.T) { 97 | socksServerAddr := "127.0.0.1:1080" 98 | socksServerBindIP := "127.0.0.1" 99 | go runLocalServer(socksServerAddr, socksServerBindIP) 100 | 101 | destServerAddr := "127.0.0.1:9000" 102 | destServerLaddr := "127.0.0.1:9001" 103 | go runDestServer(destServerAddr, destServerLaddr) 104 | 105 | c := Client{ 106 | ProxyAddr: socksServerAddr, 107 | Auth: map[METHOD]Authenticator{ 108 | USERNAME_PASSWORD: &UserPasswd{ 109 | Username: "admin", 110 | Password: "123456", 111 | }, 112 | NO_AUTHENTICATION_REQUIRED: &NoAuth{}, 113 | }, 114 | } 115 | 116 | // connect 117 | conn1, err := c.Connect(5, destServerAddr) 118 | if err != nil { 119 | t.Fatal(err) 120 | } 121 | 122 | // bind 123 | bindAddr, errors, conn, err := c.Bind(4, destServerLaddr) 124 | if err != nil { 125 | t.Fatal(err) 126 | } 127 | 128 | port := make([]byte, 2) 129 | binary.BigEndian.PutUint16(port, bindAddr.Port) 130 | conn1.Write(append(bindAddr.Addr, port...)) 131 | 132 | err = <-errors 133 | if err != nil { 134 | t.Fatal(err) 135 | } 136 | 137 | // success 138 | _, err = conn.Write([]byte("hello")) 139 | if err != nil { 140 | t.Fatal(err) 141 | } 142 | 143 | buf := make([]byte, 2) 144 | _, err = conn.Read(buf) 145 | if err != nil { 146 | t.Fatal(err) 147 | } 148 | 149 | if string(buf) != "hi" { 150 | t.Errorf("want hi but get %s", string(buf)) 151 | } 152 | } 153 | 154 | // bindAddr is tcp listen address 155 | // laddr is which address connect to socks bind server. 156 | func runDestServer(bindAddr, laddr string) { 157 | ListenAddr, _ := net.ResolveTCPAddr("tcp", bindAddr) 158 | ln, err := net.ListenTCP("tcp", ListenAddr) 159 | if err != nil { 160 | log.Fatal(err) 161 | } 162 | localAddr, _ := net.ResolveTCPAddr("tcp", laddr) 163 | 164 | conn, err := ln.AcceptTCP() 165 | if err != nil { 166 | log.Fatal(err) 167 | } 168 | 169 | addr := make([]byte, 6) 170 | _, err = conn.Read(addr) 171 | if err != nil { 172 | log.Fatal(err) 173 | } 174 | 175 | ip := addr[:4] 176 | portBytes := addr[4:] 177 | 178 | IP := net.IPv4(ip[0], ip[1], ip[2], ip[3]) 179 | port := binary.BigEndian.Uint16(portBytes) 180 | portStr := strconv.Itoa(int(port)) 181 | 182 | address := net.JoinHostPort(IP.To4().String(), portStr) 183 | raddr, _ := net.ResolveTCPAddr("tcp", address) 184 | 185 | tcpConn, err := net.DialTCP("tcp", localAddr, raddr) 186 | if err != nil { 187 | log.Fatal(err) 188 | } 189 | 190 | buf := make([]byte, 1024) 191 | _, err = tcpConn.Read(buf) 192 | if err != nil { 193 | log.Fatal() 194 | } 195 | 196 | _, err = tcpConn.Write([]byte("hi")) 197 | if err != nil { 198 | log.Fatal(err) 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socks5 2 | 3 | This is a Golang implementation of the Socks5 protocol library. 4 | To see in this [SOCKS Protocol Version 5](https://www.rfc-editor.org/rfc/rfc1928.html). 5 | This library is also compatible with Socks4 and Socks4a. 6 | 7 | # Contents 8 | 9 | - [Features](#Features) 10 | - [Install](#Installation) 11 | - [Examples](#Examples) 12 | - [Server example](#Server-example) 13 | - [simple (no authentication)](#simple-no-authentication) 14 | - [username/password authentication in memory](#username/password-authentication-in-memory) 15 | - [custom transporter to transmit data between client and remote](#custom-transporter-to-transmit-data-between-client-and-remote) 16 | - [Client example](#Client) 17 | - [CONNECT usage](#CONNECT-usage) 18 | - [UDP_ASSOCIATE usage](#UDP_ASSOCIATE-usage) 19 | - [BIND usage](#BIND-usage) 20 | - [FAQ](#FAQ) 21 | 22 | # Features 23 | 24 | - socks5: 25 | - command: **CONNECT**, **UDP ASSOCIATE**, **BIND**. 26 | - auth methods: 27 | - **Username/Password** authentication. 28 | - No Authentication Required. 29 | - socks4: 30 | - command: **CONNECT**, **BIND**. 31 | - auth: (no support). 32 | - sock4a: same as socks4. 33 | - Custom client and server authenticator. 34 | - Easy to read source code. 35 | - Similar to the Golang standard library experience. 36 | 37 | # Installation 38 | 39 | ``` sh 40 | $ go get "github.com/haochen233/socks5"` 41 | ``` 42 | 43 | # Examples 44 | 45 | ## Server example 46 | 47 | ### simple (no authentication): 48 | 49 | ```go 50 | package main 51 | 52 | import ( 53 | "log" 54 | "github.com/haochen233/socks5" 55 | ) 56 | 57 | func main() { 58 | // create socks server. 59 | srv := &socks5.Server{ 60 | // socks server listen address. 61 | Addr: "127.0.0.1:1080", 62 | // UDP assocaite and bind command listen ip. 63 | // Don't need port, the port will automatically chosen. 64 | BindIP: "127.0.0.1", 65 | // if nil server will provide no authentication required method. 66 | Authenticators: nil, 67 | } 68 | 69 | // start listen 70 | err := srv.ListenAndServe() 71 | if err != nil { 72 | log.Fatal(err) 73 | } 74 | } 75 | 76 | 77 | ``` 78 | 79 | ### username/password authentication in memory: 80 | 81 | ```go 82 | package main 83 | 84 | import ( 85 | "crypto/md5" 86 | "log" 87 | 88 | "github.com/haochen233/socks5" 89 | ) 90 | 91 | func main() { 92 | // create a username/password store in memory. 93 | var userStorage socks5.UserPwdStore = socks5.NewMemeryStore(md5.New(), "secret") 94 | // set a pair of username/password. 95 | userStorage.Set("admin", "123456") 96 | 97 | srv := &socks5.Server{ 98 | Addr: "127.0.0.1:1080", 99 | BindIP: "127.0.0.1", 100 | // enable username/password method and authenticator. 101 | Authenticators: map[socks5.METHOD]socks5.Authenticator{ 102 | socks5.USERNAME_PASSWORD: socks5.UserPwdAuth{UserPwdStore: userStorage}, 103 | // There is already an authentication method. 104 | // If want enable no authentication required method. 105 | // you should enable it explicit. 106 | socks5.NO_AUTHENTICATION_REQUIRED: socks5.NoAuth{}, 107 | }, 108 | } 109 | 110 | err := srv.ListenAndServe() 111 | if err != nil { 112 | log.Fatal(err) 113 | } 114 | } 115 | ``` 116 | 117 | ### custom transporter to transmit data between client and remote. 118 | 119 | ```go 120 | package main 121 | 122 | import ( 123 | "log" 124 | "net" 125 | 126 | "github.com/haochen233/socks5" 127 | ) 128 | 129 | // simulate to impl socks5.Transporter interface. 130 | // transport encrypted data. 131 | type cryptTransport struct { 132 | } 133 | 134 | func (c *cryptTransport) TransportTCP(client *net.TCPConn, remote *net.TCPConn) <-chan error { 135 | //encrypt data and send to remote 136 | //decrypt data and send to client 137 | return nil 138 | } 139 | 140 | func (c *cryptTransport) TransportUDP(server *socks5.UDPConn, request *socks5.Request) error { 141 | panic("implement me") 142 | return nil 143 | } 144 | 145 | func main() { 146 | server := &socks5.Server{ 147 | Addr: "127.0.0.1:1080", 148 | BindIP: "127.0.0.1", 149 | // replace default Transporter interface 150 | Transporter: &cryptTransport{}, 151 | } 152 | 153 | err := server.ListenAndServe() 154 | if err != nil { 155 | log.Fatal(err) 156 | } 157 | } 158 | ``` 159 | 160 | ## Client example 161 | 162 | ### CONNECT usage: 163 | 164 | ```go 165 | package main 166 | 167 | import ( 168 | "log" 169 | 170 | "github.com/haochen233/socks5" 171 | ) 172 | 173 | func main() { 174 | // create socks client 175 | clnt := socks5.Client{ 176 | ProxyAddr: "127.0.0.1:1080", 177 | // Authenticator supported by the client. 178 | // It must not be nil. 179 | Auth: map[socks5.METHOD]socks5.Authenticator{ 180 | // If client want send NO_AUTHENTICATION_REQUIRED method to server, must 181 | // add socks5.NoAuth authenticator explicitly 182 | socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{}, 183 | }, 184 | } 185 | 186 | // client send CONNECT command and get a tcp connection. 187 | // and use this connection transit data between you and www.google.com:80. 188 | conn, err := clnt.Connect(socks5.Version5, "www.baidu.com:80") 189 | if err != nil { 190 | log.Fatal(err) 191 | } 192 | 193 | // close connection. 194 | conn.Close() 195 | } 196 | 197 | ``` 198 | 199 | ### UDP_ASSOCIATE usage: 200 | 201 | ```go 202 | package main 203 | 204 | import ( 205 | "fmt" 206 | "log" 207 | 208 | "github.com/haochen233/socks5" 209 | ) 210 | 211 | func main() { 212 | clnt := socks5.Client{ 213 | ProxyAddr: "127.0.0.1:1080", 214 | // client provide USERNAME_PASSWORD method and 215 | // NO_AUTHENTICATION_REQUIRED. 216 | Auth: map[socks5.METHOD]socks5.Authenticator{ 217 | socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{}, 218 | socks5.USERNAME_PASSWORD: &socks5.UserPasswd{Username: "admin", Password: "123456"}, 219 | }, 220 | } 221 | 222 | // client send UDP_ASSOCIATE command and get a udp connection. 223 | // Empty local addr string a local address (127.0.0.1:port) is automatically chosen. 224 | // you can specific a address to tell socks server which client address will 225 | // send udp data. Such as clnt.UDPForward("127.0.0.1:9999"). 226 | conn, err := clnt.UDPForward("") 227 | if err != nil { 228 | log.Fatal(err) 229 | } 230 | defer conn.Close() 231 | 232 | // send every datagram should add UDP request header. 233 | someData := []byte("some data") 234 | // dest addr where are you send to. 235 | destAddr, _ := socks5.ParseAddress("127.0.0.1:9190") 236 | // packing socks5 UDP data with dest addr. 237 | pakcedData, err := socks5.PackUDPData(destAddr, someData) 238 | // final send you data 239 | conn.Write(pakcedData) 240 | 241 | // on the contrary. 242 | // you should unpacked the packet, after received every packedData. 243 | buf := make([]byte, 65507) 244 | conn.Read(buf) 245 | 246 | // unpacking data. 247 | destAddr, unpackedData, err := socks5.UnpackUDPData(buf) 248 | // operate your udp data. 249 | fmt.Println(unpackedData) 250 | } 251 | ``` 252 | 253 | ### BIND usage: 254 | 255 | ```go 256 | package main 257 | 258 | import ( 259 | "encoding/binary" 260 | "github.com/haochen233/socks5" 261 | "log" 262 | ) 263 | 264 | func main() { 265 | c := socks5.Client{ 266 | ProxyAddr: "172.16.1.28:1080", 267 | Auth: map[socks5.METHOD]socks5.Authenticator{ 268 | socks5.USERNAME_PASSWORD: &socks5.UserPasswd{"admin", "123456"}, 269 | socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{}, 270 | }, 271 | } 272 | 273 | // connect 274 | conn1, err := c.Connect(5, "127.0.0.1:9000") 275 | if err != nil { 276 | log.Fatal(err) 277 | } 278 | 279 | dest := "127.0.0.1:9001" 280 | // bind 281 | bindAddr, errors, conn2, err := c.Bind(4, dest) 282 | if err != nil { 283 | log.Fatal(err) 284 | } 285 | 286 | // An example tell dest about socks server bind address 287 | // via CONNECT proxy connection. 288 | port := make([]byte, 2) 289 | binary.BigEndian.PutUint16(port, bindAddr.Port) 290 | conn1.Write(append(bindAddr.Addr, port...)) 291 | 292 | // wait the second reply. if nil the dest already 293 | // established with socks server. 294 | err = <-errors 295 | if err != nil { 296 | log.Fatal(err) 297 | return 298 | } 299 | 300 | // bind success 301 | _, err = conn2.Write([]byte("hello")) 302 | if err != nil { 303 | return 304 | log.Fatal(err) 305 | } 306 | } 307 | ``` 308 | 309 | # FAQ: 310 | - Server default enable socks4. How to disable socks4 support? 311 | when you initialize a socks5 server, you should spefic this flag to disable explicitly. 312 | ```go 313 | server := &socks5.Server{ 314 | DisableSocks4: true, 315 | } 316 | ``` -------------------------------------------------------------------------------- /address.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "errors" 7 | "fmt" 8 | "io" 9 | "net" 10 | "strconv" 11 | "sync" 12 | ) 13 | 14 | // Address represents address in socks protocol. 15 | type Address struct { 16 | Addr net.IP 17 | ATYPE 18 | Port uint16 19 | } 20 | 21 | var bufPool = sync.Pool{New: func() interface{} { 22 | buf := bytes.Buffer{} 23 | return &buf 24 | }} 25 | 26 | // Address return address 27 | // Examples: 28 | // 127.0.0.1:80 29 | // example.com:443 30 | // [fe80::1%lo0]:80 31 | func (a *Address) String() string { 32 | if a.ATYPE == DOMAINNAME { 33 | return net.JoinHostPort(string(a.Addr), strconv.Itoa(int(a.Port))) 34 | } 35 | return net.JoinHostPort(a.Addr.String(), strconv.Itoa(int(a.Port))) 36 | } 37 | 38 | var errDomainMaxLengthLimit = errors.New("domain name out of max length") 39 | 40 | // Bytes return bytes slice of Address by ver param. 41 | // If ver is socks4, the returned socks4 address format as follows: 42 | // +----+----+----+----+----+----+....+----+....+----+ 43 | // | DSTPORT | DSTIP | USERID |NULL| 44 | // +----+----+----+----+----+----+----+----+....+----+ 45 | // If ver is socks4 and address type is domain name, 46 | // the returned socks4 address format as follows: 47 | // +----+----+----+----+----+----+....+----+....+----+....+----+....+----+ 48 | // | DSTPORT | DSTIP | USERID |NULL| HOSTNAME |NULL| 49 | // +----+----+----+----+----+----+----+----+....+----+----+----+....+----+ 50 | // If ver is socks5 51 | // the returned socks5 address format as follows: 52 | // +------+----------+----------+ 53 | // | ATYP | DST.ADDR | DST.PORT | 54 | // +------+----------+----------+ 55 | // | 1 | Variable | 2 | 56 | // +------+----------+----------+ 57 | // Socks4 call this method return bytes end with NULL, socks4 client use normally, 58 | // Socks4 server should trim terminative NULL. 59 | // Socks4 server should not call this method if server address type is DOMAINNAME 60 | func (a *Address) Bytes(ver VER) ([]byte, error) { 61 | buf := bufPool.Get().(*bytes.Buffer) 62 | defer buf.Reset() 63 | defer bufPool.Put(buf) 64 | 65 | // port 66 | port := make([]byte, 2) 67 | binary.BigEndian.PutUint16(port, a.Port) 68 | 69 | switch ver { 70 | case Version4: 71 | // socks4a 72 | buf.Write(port) 73 | if a.ATYPE == DOMAINNAME { 74 | buf.Write(net.IPv4(0, 0, 0, 1).To4()) 75 | // NULL 76 | buf.WriteByte(NULL) 77 | // hostname 78 | buf.Write(a.Addr) 79 | } else if a.ATYPE == IPV4_ADDRESS { 80 | buf.Write(a.Addr) 81 | } else { 82 | return nil, fmt.Errorf("socks4 unsupported address type: %#x", a.ATYPE) 83 | } 84 | buf.WriteByte(NULL) 85 | case Version5: 86 | // address type 87 | buf.WriteByte(a.ATYPE) 88 | // domain name address type 89 | if a.ATYPE == DOMAINNAME { 90 | if len(a.Addr) > 255 { 91 | return nil, errDomainMaxLengthLimit 92 | } 93 | buf.WriteByte(byte(len(a.Addr))) 94 | buf.Write(a.Addr) 95 | } else if a.ATYPE == IPV4_ADDRESS { 96 | buf.Write(a.Addr.To4()) 97 | } else if a.ATYPE == IPV6_ADDRESS { 98 | buf.Write(a.Addr.To16()) 99 | } 100 | buf.Write(port) 101 | } 102 | 103 | return buf.Bytes(), nil 104 | } 105 | 106 | // readAddress read address info from follows: 107 | // socks5 server's reply. 108 | // socks5 client's request. 109 | // socks5 server's udp reply header. 110 | // socks5 client's udp request header. 111 | // 112 | // socks4 client's request. 113 | // socks4a client's request 114 | // exclude: socks4a server's reply, socks4 server's reply. Please use readSocks4ReplyAddress. 115 | func readAddress(r io.Reader, ver VER) (*Address, REP, error) { 116 | addr := &Address{} 117 | 118 | switch ver { 119 | case Version4: 120 | // DST.PORT 121 | port, err := ReadNBytes(r, 2) 122 | if err != nil { 123 | return nil, Rejected, &OpError{Version5, "read", nil, "client dest port", err} 124 | } 125 | addr.Port = binary.BigEndian.Uint16(port) 126 | // DST.IP 127 | ip, err := ReadNBytes(r, 4) 128 | if err != nil { 129 | return nil, Rejected, &OpError{Version4, "read", nil, "\"process request dest ip\"", err} 130 | } 131 | addr.ATYPE = IPV4_ADDRESS 132 | 133 | //Discard later bytes until read EOF 134 | //Please see socks4 request format at(http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol) 135 | _, err = ReadUntilNULL(r) 136 | if err != nil { 137 | return nil, Rejected, &OpError{Version4, "read", nil, "\"process request useless header \"", err} 138 | } 139 | 140 | //Socks4a extension 141 | // +----+----+----+----+----+----+----+----+----+----++----++-----+-----++----+ 142 | // | VN | CD | DSTPORT | DSTIP | USERID |NULL| HOSTNAME |NULL| 143 | // +----+----+----+----+----+----+----+----+----+----++----++-----+-----++----+ 144 | // 1 1 2 4 variable 1 variable 1 145 | //The client sets the first three bytes of DSTIP to NULL and 146 | //the last byte to non-zero. The corresponding IP address is 147 | //0.0.0.x, where x is non-zero 148 | if ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && 149 | ip[3] != 0 { 150 | ip, err = ReadUntilNULL(r) 151 | if err != nil { 152 | return nil, Rejected, &OpError{Version4, "read", nil, "\"process socks4a extension request\"", err} 153 | } 154 | addr.ATYPE = DOMAINNAME 155 | } 156 | addr.Addr = ip 157 | return addr, Granted, nil 158 | case Version5: 159 | // ATYP 160 | aType, err := ReadNBytes(r, 1) 161 | if err != nil { 162 | return nil, GENERAL_SOCKS_SERVER_FAILURE, &OpError{Version5, "read", nil, "dest address type", err} 163 | } 164 | addr.ATYPE = aType[0] 165 | 166 | var addrLen int 167 | switch addr.ATYPE { 168 | case IPV4_ADDRESS: 169 | addrLen = 4 170 | case IPV6_ADDRESS: 171 | addrLen = 16 172 | case DOMAINNAME: 173 | fqdnLength, err := ReadNBytes(r, 1) 174 | if err != nil { 175 | return nil, GENERAL_SOCKS_SERVER_FAILURE, &OpError{Version5, "read", nil, "\"dest domain name length\"", err} 176 | } 177 | addrLen = int(fqdnLength[0]) 178 | default: 179 | return nil, ADDRESS_TYPE_NOT_SUPPORTED, &OpError{Version5, "", nil, "\"dest address\"", &AtypeError{aType[0]}} 180 | } 181 | 182 | // DST.ADDR 183 | ip, err := ReadNBytes(r, addrLen) 184 | if err != nil { 185 | return nil, GENERAL_SOCKS_SERVER_FAILURE, err 186 | } 187 | addr.Addr = ip 188 | 189 | // DST.PORT 190 | port, err := ReadNBytes(r, 2) 191 | if err != nil { 192 | return nil, GENERAL_SOCKS_SERVER_FAILURE, &OpError{Version5, "read", nil, "client dest port", err} 193 | } 194 | addr.Port = binary.BigEndian.Uint16(port) 195 | return addr, SUCCESSED, nil 196 | default: 197 | return nil, UNASSIGNED, &VersionError{ver} 198 | } 199 | } 200 | 201 | // readSocks4ReplyAddress read socks4 reply address. Why don't use readAddress, 202 | // because socks4 reply not end with NULL, they're not compatible 203 | func readSocks4ReplyAddress(r io.Reader, ver VER) (*Address, REP, error) { 204 | addr := &Address{} 205 | 206 | // DST.PORT 207 | port, err := ReadNBytes(r, 2) 208 | if err != nil { 209 | return nil, Rejected, &OpError{Version5, "read", nil, "client dest port", err} 210 | } 211 | addr.Port = binary.BigEndian.Uint16(port) 212 | // DST.IP 213 | ip, err := ReadNBytes(r, 4) 214 | if err != nil { 215 | return nil, Rejected, &OpError{Version4, "read", nil, "\"process request dest ip\"", err} 216 | } 217 | addr.Addr = ip 218 | addr.ATYPE = IPV4_ADDRESS 219 | 220 | return addr, Granted, nil 221 | } 222 | 223 | // UDPAddr return UDP Address. 224 | func (a *Address) UDPAddr() (*net.UDPAddr, error) { 225 | return net.ResolveUDPAddr("udp", a.String()) 226 | } 227 | 228 | // TCPAddr return TCP Address. 229 | func (a *Address) TCPAddr() (*net.TCPAddr, error) { 230 | return net.ResolveTCPAddr("tcp", a.String()) 231 | } 232 | 233 | // ParseAddress parse address to *Address 234 | // Input Examples: 235 | // 127.0.0.1:80 236 | // example.com:443 237 | // [fe80::1%lo0]:80 238 | func ParseAddress(addr string) (*Address, error) { 239 | Address := new(Address) 240 | 241 | host, port, err := net.SplitHostPort(addr) 242 | if err != nil { 243 | return nil, err 244 | } 245 | 246 | ip := net.ParseIP(host) 247 | if ip == nil { 248 | Address.ATYPE = DOMAINNAME 249 | Address.Addr = []byte(host) 250 | } else if ip.To4() != nil { 251 | Address.ATYPE = IPV4_ADDRESS 252 | Address.Addr = ip.To4() 253 | } else if ip.To16() != nil { 254 | Address.ATYPE = IPV6_ADDRESS 255 | Address.Addr = ip.To16() 256 | } 257 | atoi, err := strconv.Atoi(port) 258 | if err != nil { 259 | return nil, err 260 | } 261 | Address.Port = uint16(atoi) 262 | return Address, nil 263 | } 264 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | "strconv" 10 | "time" 11 | ) 12 | 13 | // Client defines parameters for running socks client. 14 | type Client struct { 15 | // ProxyAddr in the form "host:port". It not be empty. 16 | ProxyAddr string 17 | 18 | // Timeout specifies a time limit for requests made by this 19 | // Client. The timeout includes connection time, reading the response body. 20 | // 21 | // A Timeout of zero means no timeout. 22 | // 23 | // The Client cancels requests to the underlying Transport 24 | // as if the Request's Context ended. 25 | Timeout time.Duration 26 | 27 | // method mapping to the authenticator 28 | Auth map[METHOD]Authenticator 29 | 30 | // ErrorLog specifics an options logger for errors accepting 31 | // If nil, logging is done via log package's standard logger. 32 | ErrorLog *log.Logger 33 | 34 | // DisableSocks4A client disable socks4a client, default enable socks4a extension. 35 | DisableSocks4A bool 36 | } 37 | 38 | // UserPasswd provide socks5 Client Username/Password Authenticator. 39 | type UserPasswd struct { 40 | Username string 41 | Password string 42 | } 43 | 44 | // Authenticate socks5 Client Username/Password Authentication. 45 | func (c *UserPasswd) Authenticate(in io.Reader, out io.Writer) error { 46 | //This begins with the client producing a Username/Password request: 47 | // +----+------+----------+------+----------+ 48 | // |VER | ULEN | UNAME | PLEN | PASSWD | 49 | // +----+------+----------+------+----------+ 50 | // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | 51 | // +----+------+----------+------+----------+ 52 | _, err := out.Write(append(append(append([]byte{0x01, byte(len(c.Username))}, []byte(c.Username)...), byte(len(c.Password))), []byte(c.Password)...)) 53 | if err != nil { 54 | return err 55 | } 56 | //Get reply, the following response: 57 | 58 | // +----+--------+ 59 | // |VER | STATUS | 60 | // +----+--------+ 61 | // | 1 | 1 | 62 | // +----+--------+ 63 | tmp, err := ReadNBytes(in, 2) 64 | if err != nil { 65 | return err 66 | } 67 | if tmp[0] != 0x01 { 68 | return errors.New("not support method") 69 | } 70 | if tmp[1] != SUCCESSED { 71 | return errors.New("user authentication failed") 72 | } 73 | return nil 74 | } 75 | 76 | // handshake socks TCP connect,get a tcp connect and reply addr 77 | func (clt *Client) handshake(request *Request) (conn *net.TCPConn, replyAddr *Address, err error) { 78 | // get Socks server Address 79 | proxyTCPAddr, err := net.ResolveTCPAddr("tcp", clt.ProxyAddr) 80 | if err != nil { 81 | return nil, nil, err 82 | } 83 | 84 | // dial to Socks server. 85 | proxyTCPConn, err := net.DialTCP("tcp", nil, proxyTCPAddr) 86 | if err != nil { 87 | return nil, nil, err 88 | } 89 | if clt.Timeout != 0 { 90 | err = proxyTCPConn.SetDeadline(time.Now().Add(clt.Timeout)) 91 | if err != nil { 92 | return nil, nil, err 93 | } 94 | defer proxyTCPConn.SetDeadline(time.Time{}) 95 | } 96 | 97 | // process handshake by version 98 | if request.VER == Version5 { 99 | replyAddr, err = clt.handShake5(request, proxyTCPConn) 100 | } else if request.VER == Version4 { 101 | if request.ATYPE == DOMAINNAME && clt.DisableSocks4A { 102 | return nil, nil, errors.New("socks4a client had been disabled") 103 | } 104 | replyAddr, err = clt.handshake4(request, proxyTCPConn) 105 | } 106 | 107 | // handshake wrong. 108 | if err != nil { 109 | proxyTCPConn.Close() 110 | return nil, nil, err 111 | } 112 | 113 | return proxyTCPConn, replyAddr, nil 114 | } 115 | 116 | // handShake5 Socks 5 version of the connection handshake 117 | func (clt *Client) handShake5(request *Request, proxyTCPConn net.Conn) (*Address, error) { 118 | err := clt.authentication(proxyTCPConn) 119 | if err != nil { 120 | return nil, err 121 | } 122 | destAddrByte, err := request.Address.Bytes(Version5) 123 | if err != nil { 124 | return nil, err 125 | } 126 | // The SOCKS request is formed as follows: 127 | // +----+-----+-------+------+----------+----------+ 128 | // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 129 | // +----+-----+-------+------+----------+----------+ 130 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 131 | // +----+-----+-------+------+----------+----------+ 132 | if _, err := proxyTCPConn.Write(append([]byte{request.VER, request.CMD, request.RSV}, destAddrByte...)); err != nil { 133 | return nil, err 134 | } 135 | // reply formed as follows: 136 | // +----+-----+-------+------+----------+----------+ 137 | // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 138 | // +----+-----+-------+------+----------+----------+ 139 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 140 | // +----+-----+-------+------+----------+----------+ 141 | reply := &Reply{} 142 | tmp, err := ReadNBytes(proxyTCPConn, 3) 143 | if err != nil { 144 | return nil, fmt.Errorf("failed to get reply version and command and reserved, %v", err) 145 | } 146 | reply.VER, reply.REP, reply.RSV = tmp[0], tmp[1], tmp[2] 147 | if reply.VER != Version5 { 148 | return nil, fmt.Errorf("unrecognized SOCKS version[%d]", reply.VER) 149 | } 150 | // read address 151 | serverBoundAddr, _, err := readAddress(proxyTCPConn, request.VER) 152 | if err != nil { 153 | return nil, fmt.Errorf("failed to get reply address, %v", err) 154 | } 155 | reply.Address = serverBoundAddr 156 | if reply.REP != SUCCESSED { 157 | return nil, fmt.Errorf("server refuse client request, %s", rep2Str[reply.REP]) 158 | } 159 | return reply.Address, nil 160 | } 161 | 162 | // authentication 163 | func (clt *Client) authentication(proxyConn net.Conn) error { 164 | var methods []byte 165 | for method := range clt.Auth { 166 | methods = append(methods, method) 167 | } 168 | // The client connects to the server, and sends a version identifier/method selection message: 169 | // +----+----------+----------+ 170 | // |VER | NMETHODS | METHODS | 171 | // +----+----------+----------+ 172 | // | 1 | 1 | 1 to 255 | 173 | // +----+----------+----------+ 174 | _, err := proxyConn.Write(append([]byte{Version5, byte(len(methods))}, methods...)) 175 | if err != nil { 176 | return nil 177 | } 178 | //Get reply, a METHOD selection message: 179 | // +----+--------+ 180 | // |VER | METHOD | 181 | // +----+--------+ 182 | // | 1 | 1 | 183 | // +----+--------+ 184 | reply, err := ReadNBytes(proxyConn, 2) 185 | if err != nil { 186 | return err 187 | } 188 | if reply[0] != Version5 { 189 | return &VersionError{reply[0]} 190 | } 191 | 192 | // Is client has this method? 193 | if _, ok := clt.Auth[reply[1]]; !ok { 194 | return &MethodError{reply[1]} 195 | } 196 | 197 | // process authentication sub negotiation 198 | err = clt.Auth[reply[1]].Authenticate(proxyConn, proxyConn) 199 | if err != nil { 200 | return err 201 | } 202 | 203 | return nil 204 | } 205 | 206 | // handShake4 Socks 4 version of the connection handshake 207 | func (clt *Client) handshake4(request *Request, proxyConn net.Conn) (*Address, error) { 208 | destAddrByte, err := request.Address.Bytes(Version4) 209 | if err != nil { 210 | return nil, err 211 | } 212 | // The client connects to the SOCKS server and sends a CONNECT request when it wants to establish a connection to an application server. 213 | // The client includes in the request packet the IP address and the port number of the destination host, and userid, in the following format. 214 | // +----+----+----+----+----+----+----+----+----+----+....+----+ 215 | // | VN | CD | DSTPORT | DSTIP | USERID |NULL| 216 | // +----+----+----+----+----+----+----+----+----+----+....+----+ 217 | // 1 1 2 4 variable 1 218 | if _, err := proxyConn.Write(append([]byte{request.VER, request.CMD}, destAddrByte...)); err != nil { 219 | return nil, err 220 | } 221 | // A reply packet is sent to the client when this connection is established,or when the request is rejected or the operation fails. 222 | // +----+----+----+----+----+----+----+----+ 223 | // | VN | CD | DSTPORT | DSTIP | 224 | // +----+----+----+----+----+----+----+----+ 225 | // 1 1 2 4 226 | tmp, err := ReadNBytes(proxyConn, 2) 227 | if err != nil { 228 | return nil, fmt.Errorf("failed to get reply version and command, %v", err) 229 | } 230 | if tmp[0] != 0 { 231 | return nil, fmt.Errorf("response VN wrong[%d]", tmp[0]) 232 | } 233 | if tmp[1] != Granted { 234 | return nil, errors.New("server refuse client request") 235 | } 236 | // Read address 237 | replyAddr, _, err := readSocks4ReplyAddress(proxyConn, request.VER) 238 | if err != nil { 239 | return nil, fmt.Errorf("failed to get reply address, %v", err) 240 | } 241 | return replyAddr, nil 242 | } 243 | 244 | // Connect send CONNECT Request. Returned a connected proxy connection. 245 | func (clt *Client) Connect(ver VER, dest string) (*net.TCPConn, error) { 246 | if ver != Version4 && ver != Version5 { 247 | return nil, &VersionError{ver} 248 | } 249 | 250 | destAddr, err := ParseAddress(dest) 251 | if err != nil { 252 | return nil, err 253 | } 254 | req := &Request{ 255 | VER: ver, 256 | CMD: CONNECT, 257 | RSV: 0, 258 | Address: destAddr, 259 | } 260 | 261 | conn, _, err := clt.handshake(req) 262 | if err != nil { 263 | return nil, err 264 | } 265 | return conn, nil 266 | } 267 | 268 | // UDPForward send UDP_ASSOCIATE Request. 269 | // The laddr Param specific Client address to send udp datagram. 270 | // If laddr is empty string, a local address (127.0.0.1:port) is automatically chosen. 271 | // If port is occupied will return error. 272 | func (clt *Client) UDPForward(laddr string) (*UDPConn, error) { 273 | if laddr == "" { 274 | laddr = "127.0.0.1:0" 275 | } 276 | 277 | // split laddr to host/port 278 | host, portStr, err := net.SplitHostPort(laddr) 279 | p, err := strconv.Atoi(portStr) 280 | if err != nil { 281 | return nil, err 282 | } 283 | port := uint16(p) 284 | 285 | // zero port, will automatically chosen. 286 | if port == 0 { 287 | err, port = GetRandomPort("udp") 288 | if err != nil { 289 | return nil, errors.New("automatically chosen port fail") 290 | } 291 | laddr = net.JoinHostPort(host, strconv.Itoa(int(port))) 292 | } 293 | 294 | // get addr 295 | addr, err := ParseAddress(laddr) 296 | if err != nil { 297 | return nil, err 298 | } 299 | 300 | req := &Request{ 301 | VER: Version5, 302 | CMD: UDP_ASSOCIATE, 303 | RSV: 0, 304 | Address: addr, 305 | } 306 | 307 | // Handshake base on TCP connection 308 | proxyTCPConn, UDPRelayAddr, err := clt.handshake(req) 309 | if err != nil { 310 | return nil, err 311 | } 312 | 313 | // Get local UDP addr 314 | localUDPAddr, err := addr.UDPAddr() 315 | if err != nil { 316 | return nil, err 317 | } 318 | 319 | // Get udp relay server bind addr. 320 | serverListenUDPAddr, err := UDPRelayAddr.UDPAddr() 321 | if err != nil { 322 | return nil, err 323 | } 324 | 325 | // Dial UDP relay Server 326 | err = IsFreePort("udp", port) 327 | if err != nil { 328 | proxyTCPConn.Close() 329 | return nil, fmt.Errorf("port %d is occupied", port) 330 | } 331 | proxyUDPConn, err := net.DialUDP("udp", localUDPAddr, serverListenUDPAddr) 332 | if err != nil { 333 | proxyTCPConn.Close() 334 | return nil, err 335 | } 336 | return NewUDPConn(proxyUDPConn, proxyTCPConn), nil 337 | } 338 | 339 | // Bind send BIND Request. return 4 params: 340 | // 1. Server bind address. 341 | // 2. a readable chan to recv second reply from socks server. 342 | // 3. A connection that is not immediately available, until read a nil from err chan. 343 | // 4. An error, indicate the first reply result. If nil, successes. 344 | func (clt *Client) Bind(ver VER, destAddr string) (*Address, <-chan error, net.Conn, error) { 345 | dest, err := ParseAddress(destAddr) 346 | if err != nil { 347 | return nil, nil, nil, err 348 | } 349 | 350 | request := &Request{ 351 | Address: dest, 352 | CMD: BIND, 353 | VER: ver, 354 | } 355 | proxyConn, err := net.Dial("tcp", clt.ProxyAddr) 356 | if err != nil { 357 | clt.logf()(err.Error()) 358 | return nil, nil, nil, err 359 | } 360 | if clt.Timeout != 0 { 361 | err = proxyConn.SetDeadline(time.Now().Add(clt.Timeout)) 362 | if err != nil { 363 | clt.logf()(err.Error()) 364 | return nil, nil, nil, err 365 | } 366 | defer proxyConn.SetDeadline(time.Time{}) 367 | } 368 | switch request.VER { 369 | case Version4: 370 | serverBindAddr, secondReply, err := clt.bind4(request, proxyConn) 371 | if err != nil { 372 | proxyConn.Close() 373 | clt.logf()(err.Error()) 374 | return nil, nil, nil, err 375 | } 376 | return serverBindAddr, secondReply, proxyConn, nil 377 | case Version5: 378 | serverBindAddr, secondReply, err := clt.bind5(request, proxyConn) 379 | if err != nil { 380 | proxyConn.Close() 381 | clt.logf()(err.Error()) 382 | return nil, nil, nil, err 383 | } 384 | return serverBindAddr, secondReply, proxyConn, nil 385 | default: 386 | proxyConn.Close() 387 | return nil, nil, nil, &VersionError{request.VER} 388 | } 389 | } 390 | 391 | // bind5 socks5 bind 392 | func (clt *Client) bind5(request *Request, proxyBindConn net.Conn) (*Address, <-chan error, error) { 393 | err := clt.authentication(proxyBindConn) 394 | if err != nil { 395 | return nil, nil, err 396 | } 397 | destAddrByte, err := request.Address.Bytes(Version5) 398 | if err != nil { 399 | return nil, nil, err 400 | } 401 | // The SOCKS request is formed as follows: 402 | // +----+-----+-------+------+----------+----------+ 403 | // // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 404 | // // +----+-----+-------+------+----------+----------+ 405 | // // | 1 | 1 | X'00' | 1 | Variable | 2 | 406 | // +----+-----+-------+------+----------+----------+ 407 | if _, err := proxyBindConn.Write(append([]byte{request.VER, request.CMD, request.RSV}, destAddrByte...)); err != nil { 408 | return nil, nil, err 409 | } 410 | // reply formed as follows: 411 | // +----+-----+-------+------+----------+----------+ 412 | // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 413 | // +----+-----+-------+------+----------+----------+ 414 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 415 | // +----+-----+-------+------+----------+----------+ 416 | reply := &Reply{} 417 | tmp, err := ReadNBytes(proxyBindConn, 3) 418 | if err != nil { 419 | return nil, nil, fmt.Errorf("failed to get reply version and command and reserved, %v", err) 420 | } 421 | reply.VER, reply.REP, reply.RSV = tmp[0], tmp[1], tmp[2] 422 | if reply.VER != Version5 { 423 | return nil, nil, fmt.Errorf("unrecognized SOCKS version[%d]", reply.VER) 424 | } 425 | // read address 426 | serverBoundAddr, _, err := readAddress(proxyBindConn, request.VER) 427 | if err != nil { 428 | return nil, nil, fmt.Errorf("failed to get reply address, %v", err) 429 | } 430 | reply.Address = serverBoundAddr 431 | if reply.REP != SUCCESSED { 432 | return nil, nil, fmt.Errorf("server refuse client request, %s,when first time reply", rep2Str[reply.REP]) 433 | } 434 | errorChan := make(chan error) 435 | go func() { 436 | reply2 := &Reply{} 437 | // The second time reply formed as follows: 438 | // +----+-----+-------+------+----------+----------+ 439 | // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 440 | // +----+-----+-------+------+----------+----------+ 441 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 442 | // +----+-----+-------+------+----------+----------+ 443 | tmp, err := ReadNBytes(proxyBindConn, 3) 444 | if err != nil { 445 | errorChan <- fmt.Errorf("failed to get reply version and command and reserved, %v", err) 446 | proxyBindConn.Close() 447 | } 448 | reply2.VER, reply2.REP, reply2.RSV = tmp[0], tmp[1], tmp[2] 449 | if reply2.VER != Version5 { 450 | errorChan <- fmt.Errorf("unrecognized SOCKS version[%d]", reply.VER) 451 | proxyBindConn.Close() 452 | } 453 | // read address 454 | serverBoundAddr, _, err := readAddress(proxyBindConn, request.VER) 455 | if err != nil { 456 | errorChan <- fmt.Errorf("failed to get reply address, %v", err) 457 | proxyBindConn.Close() 458 | } 459 | reply2.Address = serverBoundAddr 460 | if reply2.REP != SUCCESSED { 461 | errorChan <- errors.New("server refuse client request,when second time reply") 462 | proxyBindConn.Close() 463 | } 464 | errorChan <- nil 465 | }() 466 | return serverBoundAddr, errorChan, nil 467 | } 468 | 469 | // bind4 socks4 bind 470 | func (clt *Client) bind4(request *Request, proxyBindConn net.Conn) (*Address, <-chan error, error) { 471 | destAddrByte, err := request.Address.Bytes(Version4) 472 | if err != nil { 473 | return nil, nil, err 474 | } 475 | // The client connects to the SOCKS server and sends a CONNECT request when it wants to establish a connection to an application server. 476 | // The client includes in the request packet the IP address and the port number of the destination host, and userid, in the following format. 477 | // +----+----+----+----+----+----+----+----+----+----+....+----+ 478 | // | VN | CD | DSTPORT | DSTIP | USERID |NULL| 479 | // +----+----+----+----+----+----+----+----+----+----+....+----+ 480 | // 1 1 2 4 variable 1 481 | if _, err := proxyBindConn.Write(append([]byte{request.VER, request.CMD}, destAddrByte...)); err != nil { 482 | return nil, nil, err 483 | } 484 | // A reply packet is sent to the client when this connection is established,or when the request is rejected or the operation fails. 485 | // +----+----+----+----+----+----+----+----+ 486 | // | VN | CD | DSTPORT | DSTIP | 487 | // +----+----+----+----+----+----+----+----+ 488 | // 1 1 2 4 489 | tmp, err := ReadNBytes(proxyBindConn, 2) 490 | if err != nil { 491 | return nil, nil, fmt.Errorf("failed to get reply version and command, %v", err) 492 | } 493 | if tmp[0] != 0 { 494 | return nil, nil, fmt.Errorf("response VN wrong[%d]", tmp[0]) 495 | } 496 | // Read address 497 | serverBoundAddr, _, err := readSocks4ReplyAddress(proxyBindConn, request.VER) 498 | if err != nil { 499 | return nil, nil, fmt.Errorf("failed to get reply address, %v", err) 500 | } 501 | if tmp[1] != Granted { 502 | return nil, nil, errors.New("server refuse client request,when first time reply") 503 | } 504 | errorChan := make(chan error) 505 | go func() { 506 | // A reply packet is sent to the client,or when the request is rejected or the operation fails. 507 | // +----+----+----+----+----+----+----+----+ 508 | // | VN | CD | DSTPORT | DSTIP | 509 | // +----+----+----+----+----+----+----+----+ 510 | // 1 1 2 4 511 | tmp, err := ReadNBytes(proxyBindConn, 2) 512 | if err != nil { 513 | errorChan <- fmt.Errorf("failed to get reply version and command, %v", err) 514 | proxyBindConn.Close() 515 | } 516 | if tmp[0] != 0 { 517 | errorChan <- fmt.Errorf("response VN wrong[%d]", tmp[0]) 518 | proxyBindConn.Close() 519 | } 520 | // read address 521 | _, _, err = readSocks4ReplyAddress(proxyBindConn, request.VER) 522 | if err != nil { 523 | errorChan <- fmt.Errorf("failed to get reply address, %v", err) 524 | proxyBindConn.Close() 525 | } 526 | 527 | if tmp[1] != Granted { 528 | errorChan <- errors.New("server refuse client request,when second time reply") 529 | proxyBindConn.Close() 530 | } 531 | errorChan <- nil 532 | }() 533 | return serverBoundAddr, errorChan, nil 534 | } 535 | 536 | // logf Logging is done using the client's errorlog 537 | func (clt *Client) logf() func(format string, args ...interface{}) { 538 | if clt.ErrorLog == nil { 539 | return log.Printf 540 | } 541 | return clt.ErrorLog.Printf 542 | } 543 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package socks5 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "log" 7 | "net" 8 | "strconv" 9 | "sync" 10 | "sync/atomic" 11 | "time" 12 | ) 13 | 14 | // Server defines parameters for running socks server. 15 | // The zero value for Server is a valid configuration(tcp listen on :1080). 16 | type Server struct { 17 | // Addr optionally specifies the TCP address for the server to listen on, 18 | // in the form "host:port". If empty, ":1080" (port 1080) is used. 19 | Addr string 20 | 21 | // BindIP specific UDP relay server IP and bind listen IP. 22 | // It shouldn't be ipv4zero like "0,0,0,0" or ipv6zero like [:] 23 | // If empty, localhost used. 24 | BindIP string 25 | 26 | // ReadTimeout is the maximum duration for reading from socks client. 27 | // it's only effective to socks server handshake process. 28 | // 29 | // If zero, there is no timeout. 30 | ReadTimeout time.Duration 31 | 32 | // WriteTimeout is the maximum duration for writing to socks client. 33 | // it's only effective to socks server handshake process. 34 | // 35 | // If zero, there is no timeout. 36 | WriteTimeout time.Duration 37 | 38 | // method mapping to the authenticator 39 | // if nil server provide NO_AUTHENTICATION_REQUIRED method by default 40 | Authenticators map[METHOD]Authenticator 41 | 42 | // The server select method to use policy 43 | //MethodSelector 44 | 45 | // Server transmit data between client and dest server. 46 | // if nil, DefaultTransport is used. 47 | Transporter 48 | 49 | // ErrorLog specifics an options logger for errors accepting 50 | // connections, unexpected socks protocol handshake process, 51 | // and server to remote connection errors. 52 | // If nil, logging is done via log package's standard logger. 53 | ErrorLog *log.Logger 54 | 55 | // DisableSocks4, disable socks4 server, default enable socks4 compatible. 56 | DisableSocks4 bool 57 | 58 | // 1 indicate server is shutting down. 59 | // 0 indicate server is running. 60 | // Atomic operation must be guaranteed. 61 | isShutdown int32 62 | 63 | mu sync.Mutex 64 | listeners map[*net.Listener]struct{} 65 | activeConn map[net.Conn]struct{} 66 | doneCh chan struct{} 67 | } 68 | 69 | func (srv *Server) getDoneChan() <-chan struct{} { 70 | srv.mu.Lock() 71 | defer srv.mu.Unlock() 72 | return srv.getDoneChanLocked() 73 | } 74 | 75 | func (srv *Server) getDoneChanLocked() chan struct{} { 76 | if srv.doneCh == nil { 77 | srv.doneCh = make(chan struct{}) 78 | } 79 | return srv.doneCh 80 | } 81 | 82 | func (srv *Server) closeDoneChanLocked() { 83 | ch := srv.getDoneChanLocked() 84 | select { 85 | case <-ch: 86 | default: 87 | close(srv.doneCh) 88 | } 89 | } 90 | 91 | func (srv *Server) Close() error { 92 | atomic.StoreInt32(&srv.isShutdown, 1) 93 | srv.mu.Lock() 94 | defer srv.mu.Unlock() 95 | // close all listeners. 96 | err := srv.closeListenerLocked() 97 | if err != nil { 98 | return err 99 | } 100 | // close doneCh to broadcast close message. 101 | srv.closeDoneChanLocked() 102 | // Close all open connections. 103 | for conn, _ := range srv.activeConn { 104 | conn.Close() 105 | } 106 | return nil 107 | } 108 | 109 | func (srv *Server) inShuttingDown() bool { 110 | return atomic.LoadInt32(&srv.isShutdown) != 0 111 | } 112 | 113 | func (srv *Server) closeListenerLocked() error { 114 | var err error 115 | for ln := range srv.listeners { 116 | if cerr := (*ln).Close(); cerr != nil { 117 | err = cerr 118 | } 119 | } 120 | return err 121 | } 122 | 123 | // trackListener adds or removes a net.Listener to the set of tracked 124 | // listeners. 125 | // 126 | // We store a pointer to interface in the map set, in case the 127 | // net.Listener is not comparable. This is safe because we only call 128 | // trackListener via Serve and can track+defer untrack the same 129 | // pointer to local variable there. We never need to compare a 130 | // Listener from another caller. 131 | // 132 | // It reports whether the server is still up (not Shutdown or Closed). 133 | func (srv *Server) trackListener(l *net.Listener, add bool) bool { 134 | srv.mu.Lock() 135 | defer srv.mu.Unlock() 136 | if srv.listeners == nil { 137 | srv.listeners = make(map[*net.Listener]struct{}) 138 | } 139 | 140 | if add { 141 | if srv.inShuttingDown() { 142 | return false 143 | } 144 | srv.listeners[l] = struct{}{} 145 | } else { 146 | delete(srv.listeners, l) 147 | } 148 | return true 149 | } 150 | 151 | func (srv *Server) trackConn(c net.Conn, add bool) { 152 | srv.mu.Lock() 153 | defer srv.mu.Unlock() 154 | if srv.activeConn == nil { 155 | srv.activeConn = make(map[net.Conn]struct{}) 156 | } 157 | if add { 158 | srv.activeConn[c] = struct{}{} 159 | } else { 160 | delete(srv.activeConn, c) 161 | } 162 | } 163 | 164 | // ListenAndServe listens on the TCP network address srv.Addr and then 165 | // calls serve to handle requests on incoming connections. 166 | // 167 | // If srv.Addr is blank, ":1080" is used. 168 | func (srv *Server) ListenAndServe() error { 169 | if srv.inShuttingDown() { 170 | return ErrServerClosed 171 | } 172 | 173 | addr := srv.Addr 174 | if addr == "" { 175 | addr = "0.0.0.0:1080" 176 | } 177 | 178 | if srv.BindIP == "" { 179 | srv.BindIP = "localhost" 180 | } else if srv.BindIP == net.IPv4zero.String() || srv.BindIP == net.IPv6zero.String() { 181 | return errors.New("socks: server bindIP shouldn't be zero") 182 | } 183 | 184 | ln, err := net.Listen("tcp", addr) 185 | if err != nil { 186 | return err 187 | } 188 | return srv.Serve(ln) 189 | } 190 | 191 | // ErrServerClosed is returned by the Server's Serve, ListenAndServe methods after a call to Shutdown or Close. 192 | var ErrServerClosed = errors.New("socks: Server closed") 193 | 194 | // Serve accepts incoming connections on the Listener l, creating a 195 | // new service goroutine for each. The service goroutine select client 196 | // list methods and reply client. Then process authentication and reply 197 | // to them. At then end of handshake, read socks request from client and 198 | // establish a connection to the target. 199 | func (srv *Server) Serve(l net.Listener) error { 200 | srv.trackListener(&l, true) 201 | defer srv.trackListener(&l, false) 202 | 203 | var tempDelay time.Duration 204 | 205 | for { 206 | client, err := l.Accept() 207 | if err != nil { 208 | select { 209 | case <-srv.getDoneChan(): 210 | return ErrServerClosed 211 | default: 212 | } 213 | if ne, ok := err.(net.Error); ok && ne.Temporary() { 214 | if tempDelay == 0 { 215 | tempDelay = 5 * time.Millisecond 216 | } else { 217 | tempDelay *= 2 218 | } 219 | if max := time.Second; tempDelay > max { 220 | tempDelay = max 221 | } 222 | srv.logf()("socks: Accept error: %v, retrying in %v", err, tempDelay) 223 | time.Sleep(tempDelay) 224 | continue 225 | } 226 | return err 227 | } 228 | go srv.serveconn(client) 229 | } 230 | } 231 | 232 | func (srv *Server) serveconn(client net.Conn) { 233 | if srv.ReadTimeout != 0 { 234 | client.SetReadDeadline(time.Now().Add(srv.ReadTimeout)) 235 | } 236 | if srv.WriteTimeout != 0 { 237 | client.SetWriteDeadline(time.Now().Add(srv.WriteTimeout)) 238 | } 239 | 240 | // handshake 241 | request, err := srv.handShake(client) 242 | if err != nil { 243 | srv.logf()(err.Error()) 244 | client.Close() 245 | return 246 | } 247 | 248 | // establish connection to remote 249 | remote, err := srv.establish(client, request) 250 | if err != nil { 251 | srv.logf()(err.Error()) 252 | client.Close() 253 | return 254 | } 255 | 256 | // establish over, reset deadline. 257 | client.SetReadDeadline(time.Time{}) 258 | client.SetWriteDeadline(time.Time{}) 259 | 260 | // transport data 261 | switch request.CMD { 262 | case CONNECT, BIND: 263 | srv.trackConn(client, true) 264 | defer srv.trackConn(client, false) 265 | srv.trackConn(remote, true) 266 | defer srv.trackConn(remote, false) 267 | 268 | errCh := srv.transport().TransportTCP(client.(*net.TCPConn), remote.(*net.TCPConn)) 269 | for err := range errCh { 270 | if err != nil { 271 | srv.logf()(err.Error()) 272 | } 273 | } 274 | case UDP_ASSOCIATE: 275 | relay := NewUDPConn(remote.(*net.UDPConn), client.(*net.TCPConn)) 276 | srv.trackConn(relay, true) 277 | defer srv.trackConn(relay, false) 278 | 279 | err = srv.transport().TransportUDP(relay, request) 280 | if err != nil { 281 | srv.logf()(err.Error()) 282 | } 283 | } 284 | } 285 | 286 | func (srv *Server) transport() Transporter { 287 | if srv.Transporter == nil { 288 | return DefaultTransporter 289 | } 290 | return srv.Transporter 291 | } 292 | 293 | var errDisableSocks4 = errors.New("socks4 server has been disabled") 294 | 295 | // handShake socks protocol handshake process 296 | func (srv *Server) handShake(client net.Conn) (*Request, error) { 297 | //validate socks version message 298 | version, err := checkVersion(client) 299 | if err != nil { 300 | return nil, &OpError{Version5, "read", client.RemoteAddr(), "\"check version\"", err} 301 | } 302 | 303 | //socks4 protocol process 304 | if version == Version4 { 305 | if srv.DisableSocks4 { 306 | //send server reject reply 307 | address := &Address{net.IPv4zero, IPV4_ADDRESS, 0} 308 | addr, err := address.Bytes(Version4) 309 | if err != nil { 310 | return nil, &OpError{Version4, "", client.RemoteAddr(), "\"authentication\"", err} 311 | } 312 | _, err = client.Write(append([]byte{0, Rejected}, addr...)) 313 | if err != nil { 314 | return nil, &OpError{Version4, "write", client.RemoteAddr(), "\"authentication\"", err} 315 | } 316 | return nil, errDisableSocks4 317 | } 318 | 319 | //handle socks4 request 320 | return srv.readSocks4Request(client) 321 | } 322 | 323 | //socks5 protocol authentication 324 | err = srv.authentication(client) 325 | if err != nil { 326 | return nil, err 327 | } 328 | 329 | //handle socks5 request 330 | return srv.readSocks5Request(client) 331 | } 332 | 333 | // authentication socks5 authentication process 334 | func (srv *Server) authentication(client net.Conn) error { 335 | //get nMethods 336 | nMethods, err := ReadNBytes(client, 1) 337 | if err != nil { 338 | return err 339 | } 340 | 341 | //Get methods 342 | methods, err := ReadNBytes(client, int(nMethods[0])) 343 | if err != nil { 344 | return err 345 | } 346 | 347 | return srv.MethodSelect(methods, client) 348 | } 349 | 350 | // readSocks4Request receive socks4 protocol client request. 351 | func (srv *Server) readSocks4Request(client net.Conn) (*Request, error) { 352 | reply := &Reply{ 353 | VER: Version4, 354 | Address: &Address{net.IPv4zero, IPV4_ADDRESS, 0}, 355 | } 356 | req := &Request{ 357 | VER: Version4, 358 | } 359 | // CMD 360 | cmd, err := ReadNBytes(client, 1) 361 | if err != nil { 362 | return nil, &OpError{req.VER, "read", client.RemoteAddr(), "\"process request command\"", err} 363 | } 364 | req.CMD = cmd[0] 365 | // DST.PORT, DST.IP 366 | addr, rep, err := readAddress(client, req.VER) 367 | if err != nil { 368 | reply.REP = rep 369 | err := srv.sendReply(client, reply) 370 | if err != nil { 371 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request address type\"", err} 372 | } 373 | } 374 | req.Address = addr 375 | return req, nil 376 | } 377 | 378 | // readSocks5Request read socks5 protocol client request. 379 | func (srv *Server) readSocks5Request(client net.Conn) (*Request, error) { 380 | reply := &Reply{ 381 | VER: Version5, 382 | Address: &Address{net.IPv4zero, IPV4_ADDRESS, 0}, 383 | } 384 | req := &Request{} 385 | //VER, CMD, RSV 386 | cmd, err := ReadNBytes(client, 3) 387 | if err != nil { 388 | return nil, &OpError{req.VER, "read", client.RemoteAddr(), "\"process request ver,cmd,rsv\"", err} 389 | } 390 | req.VER = cmd[0] 391 | req.CMD = cmd[1] 392 | req.RSV = cmd[2] 393 | // ATYPE, DST.IP, DST.PORT 394 | addr, rep, err := readAddress(client, req.VER) 395 | if err != nil { 396 | reply.REP = rep 397 | err := srv.sendReply(client, reply) 398 | if err != nil { 399 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request address\"", err} 400 | } 401 | } 402 | req.Address = addr 403 | 404 | return req, nil 405 | } 406 | 407 | // IsAllowNoAuthRequired return true if server enable NO_AUTHENTICATION_REQUIRED. 408 | // Or the server doesn't has no Authenticator return true. Otherwise return false. 409 | func (srv *Server) IsAllowNoAuthRequired() bool { 410 | if len(srv.Authenticators) == 0 { 411 | return true 412 | } 413 | for method := range srv.Authenticators { 414 | if method == NO_AUTHENTICATION_REQUIRED { 415 | return true 416 | } 417 | } 418 | return false 419 | } 420 | 421 | // establish tcp connection to remote host if command is CONNECT or 422 | // start listen on udp socket when command is UDP_ASSOCIATE. Listen 423 | // and accept host connection when command is BIND. Finally, send 424 | // corresponding reply to client. 425 | func (srv *Server) establish(client net.Conn, req *Request) (dest net.Conn, err error) { 426 | reply := &Reply{ 427 | VER: req.VER, 428 | Address: &Address{net.IPv4zero, IPV4_ADDRESS, 0}, 429 | } 430 | 431 | // version4 432 | if req.VER == Version4 { 433 | switch req.CMD { 434 | case CONNECT: 435 | // dial to dest host. 436 | dest, err = net.Dial("tcp", req.Address.String()) 437 | if err != nil { 438 | reply.REP = Rejected 439 | err2 := srv.sendReply(client, reply) 440 | if err != nil { 441 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 442 | } 443 | return nil, err 444 | } 445 | 446 | // parse remote host address. 447 | remoteAddr, err := ParseAddress(dest.RemoteAddr().String()) 448 | if err != nil { 449 | reply.REP = Rejected 450 | err2 := srv.sendReply(client, reply) 451 | if err2 != nil { 452 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 453 | } 454 | return nil, err 455 | } 456 | reply.Address = remoteAddr 457 | 458 | // success 459 | reply.REP = Granted 460 | err = srv.sendReply(client, reply) 461 | if err != nil { 462 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 463 | } 464 | case BIND: 465 | bindAddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(srv.BindIP, "0")) 466 | if err != nil { 467 | return nil, err 468 | } 469 | 470 | // start listening on random port. 471 | bindServer, err := net.ListenTCP("tcp", bindAddr) 472 | if err != nil { 473 | reply.REP = Rejected 474 | err2 := srv.sendReply(client, reply) 475 | if err2 != nil { 476 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 477 | } 478 | return nil, err 479 | } 480 | defer bindServer.Close() 481 | reply.REP = Granted 482 | reply.Address, err = ParseAddress(bindServer.Addr().String()) 483 | if err != nil { 484 | return nil, err 485 | } 486 | 487 | // send first reply to client. 488 | err = srv.sendReply(client, reply) 489 | if err != nil { 490 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 491 | } 492 | // waiting target host connect. 493 | dest, err = bindServer.Accept() 494 | if err != nil { 495 | reply.REP = Rejected 496 | err2 := srv.sendReply(client, reply) 497 | if err2 != nil { 498 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 499 | } 500 | return nil, err 501 | } 502 | 503 | // send second reply to client. 504 | if req.Address.String() == dest.RemoteAddr().String() { 505 | err2 := srv.sendReply(client, reply) 506 | if err2 != nil { 507 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 508 | } 509 | } else { 510 | reply.REP = Rejected 511 | err = srv.sendReply(client, reply) 512 | if err != nil { 513 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 514 | } 515 | } 516 | default: 517 | reply.REP = Rejected 518 | err = srv.sendReply(client, reply) 519 | if err != nil { 520 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 521 | } 522 | return nil, &OpError{req.VER, "", client.RemoteAddr(), "\"process request\"", &CMDError{req.CMD}} 523 | } 524 | } else if req.VER == Version5 { // version5 525 | switch req.CMD { 526 | case CONNECT: 527 | // dial dest host. 528 | dest, err = net.Dial("tcp", req.Address.String()) 529 | if err != nil { 530 | reply.REP = HOST_UNREACHABLE 531 | err2 := srv.sendReply(client, reply) 532 | if err2 != nil { 533 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 534 | 535 | } 536 | return nil, err 537 | } 538 | 539 | // parse remote host address. 540 | remoteAddr, err := ParseAddress(dest.RemoteAddr().String()) 541 | if err != nil { 542 | reply.REP = GENERAL_SOCKS_SERVER_FAILURE 543 | err2 := srv.sendReply(client, reply) 544 | if err2 != nil { 545 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 546 | } 547 | return nil, err 548 | } 549 | reply.Address = remoteAddr 550 | 551 | // success 552 | reply.REP = SUCCESSED 553 | err = srv.sendReply(client, reply) 554 | if err != nil { 555 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 556 | } 557 | case UDP_ASSOCIATE: 558 | addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(srv.BindIP, "0")) 559 | if err != nil { 560 | return nil, err 561 | } 562 | 563 | // start udp listening on random port. 564 | dest, err = net.ListenUDP("udp", addr) 565 | if err != nil { 566 | reply.REP = GENERAL_SOCKS_SERVER_FAILURE 567 | err2 := srv.sendReply(client, reply) 568 | if err2 != nil { 569 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 570 | } 571 | return nil, err 572 | } 573 | 574 | // success 575 | reply.REP = SUCCESSED 576 | relayAddr, err := ParseAddress(dest.LocalAddr().String()) 577 | if err != nil { 578 | return nil, err 579 | } 580 | reply.Address = relayAddr 581 | err = srv.sendReply(client, reply) 582 | if err != nil { 583 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 584 | } 585 | case BIND: 586 | bindAddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(srv.BindIP, "0")) 587 | if err != nil { 588 | return nil, err 589 | } 590 | 591 | // start tcp listening on random port. 592 | bindServer, err := net.ListenTCP("tcp", bindAddr) 593 | if err != nil { 594 | reply.REP = GENERAL_SOCKS_SERVER_FAILURE 595 | err2 := srv.sendReply(client, reply) 596 | if err2 != nil { 597 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 598 | } 599 | return nil, err 600 | } 601 | defer bindServer.Close() 602 | reply.REP = SUCCESSED 603 | reply.Address, err = ParseAddress(bindServer.Addr().String()) 604 | if err != nil { 605 | return nil, err 606 | } 607 | 608 | // send first reply to client. 609 | err = srv.sendReply(client, reply) 610 | if err != nil { 611 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 612 | } 613 | dest, err = bindServer.Accept() 614 | if err != nil { 615 | reply.REP = GENERAL_SOCKS_SERVER_FAILURE 616 | err2 := srv.sendReply(client, reply) 617 | if err2 != nil { 618 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err2} 619 | } 620 | return nil, err 621 | } 622 | 623 | // send second reply to client. 624 | if req.Address.String() == dest.RemoteAddr().String() { 625 | reply.Address, err = ParseAddress(dest.RemoteAddr().String()) 626 | if err != nil { 627 | return nil, err 628 | } 629 | err = srv.sendReply(client, reply) 630 | if err != nil { 631 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 632 | } 633 | } else { 634 | reply.REP = GENERAL_SOCKS_SERVER_FAILURE 635 | err = srv.sendReply(client, reply) 636 | if err != nil { 637 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 638 | } 639 | } 640 | default: 641 | reply.REP = COMMAND_NOT_SUPPORTED 642 | err = srv.sendReply(client, reply) 643 | if err != nil { 644 | return nil, &OpError{req.VER, "write", client.RemoteAddr(), "\"process request\"", err} 645 | } 646 | 647 | return nil, &OpError{Version5, "", client.RemoteAddr(), "\"process request\"", &CMDError{req.CMD}} 648 | } 649 | } else { // unknown version 650 | return nil, &VersionError{req.VER} 651 | } 652 | return 653 | } 654 | 655 | var errErrorATPE = errors.New("socks4 server bind address type should be ipv4") 656 | 657 | // sendReply The server send socks protocol reply to client 658 | func (srv *Server) sendReply(out io.Writer, r *Reply) error { 659 | var reply []byte 660 | var err error 661 | 662 | if r.VER == Version4 { 663 | if r.Address.ATYPE != IPV4_ADDRESS { 664 | return errErrorATPE 665 | } 666 | addr, err := r.Address.Bytes(r.VER) 667 | if err != nil { 668 | return err 669 | } 670 | reply = append(reply, 0, r.REP) 671 | // Remove NULL at the end. Please see Address.Bytes() Method. 672 | reply = append(reply, addr[:len(addr)-1]...) 673 | } else if r.VER == Version5 { 674 | addr, err := r.Address.Bytes(r.VER) 675 | if err != nil { 676 | return err 677 | } 678 | reply = append(reply, r.VER, r.REP, r.RSV) 679 | reply = append(reply, addr...) 680 | } else { 681 | return &VersionError{r.VER} 682 | } 683 | 684 | _, err = out.Write(reply) 685 | return err 686 | } 687 | 688 | // MethodSelect select authentication method and reply to client. 689 | func (srv *Server) MethodSelect(methods []CMD, client net.Conn) error { 690 | // Select method to authenticate, then send selected method to client. 691 | for _, method := range methods { 692 | //Preferred to use NO_AUTHENTICATION_REQUIRED method 693 | if method == NO_AUTHENTICATION_REQUIRED && srv.IsAllowNoAuthRequired() { 694 | reply := []byte{Version5, NO_AUTHENTICATION_REQUIRED} 695 | _, err := client.Write(reply) 696 | if err != nil { 697 | return &OpError{Version5, "write", client.RemoteAddr(), "authentication", err} 698 | } 699 | return nil 700 | } 701 | for m := range srv.Authenticators { 702 | //Select the first matched method to authenticate 703 | if m == method { 704 | reply := []byte{Version5, method} 705 | _, err := client.Write(reply) 706 | if err != nil { 707 | return &OpError{Version5, "write", client.RemoteAddr(), "authentication", err} 708 | } 709 | 710 | err = srv.Authenticators[m].Authenticate(client, client) 711 | if err != nil { 712 | return &OpError{Version5, "", client.RemoteAddr(), "authentication", err} 713 | } 714 | return nil 715 | } 716 | } 717 | } 718 | 719 | // There are no Methods can use 720 | reply := []byte{Version5, NO_ACCEPTABLE_METHODS} 721 | _, err := client.Write(reply) 722 | if err != nil { 723 | return &OpError{Version5, "write", client.RemoteAddr(), "authentication", err} 724 | } 725 | return &OpError{Version5, "", client.RemoteAddr(), "authentication", &MethodError{methods[0]}} 726 | } 727 | 728 | func (srv *Server) logf() func(format string, args ...interface{}) { 729 | if srv.ErrorLog == nil { 730 | return log.Printf 731 | } 732 | return srv.ErrorLog.Printf 733 | } 734 | 735 | // checkVersion check version is 4 or 5. 736 | func checkVersion(in io.Reader) (VER, error) { 737 | version, err := ReadNBytes(in, 1) 738 | if err != nil { 739 | return 0, err 740 | } 741 | 742 | if (version[0] != Version5) && (version[0] != Version4) { 743 | return 0, &VersionError{version[0]} 744 | } 745 | return version[0], nil 746 | } 747 | 748 | // OpError is the error type usually returned by functions in the socks5 749 | // package. It describes the socks version, operation, client address, 750 | // and address of an error. 751 | type OpError struct { 752 | // VER describe the socks server version on process. 753 | VER 754 | 755 | // Op is the operation which caused the error, such as 756 | // "read", "write". 757 | Op string 758 | 759 | // Addr define client's address which caused the error. 760 | Addr net.Addr 761 | 762 | // Step is the client's current connection stage, such as 763 | // "check version", "authentication", "process request", 764 | Step string 765 | 766 | // Err is the error that occurred during the operation. 767 | // The Error method panics if the error is nil. 768 | Err error 769 | } 770 | 771 | func (o *OpError) Error() string { 772 | str := "socks" + strconv.Itoa(int(o.VER)) 773 | str += " " + o.Op 774 | if o.Addr == nil { 775 | str += " " 776 | } else { 777 | str += " " + o.Addr.String() 778 | } 779 | str += " " + o.Step 780 | str += ":" + o.Err.Error() 781 | return str 782 | } 783 | --------------------------------------------------------------------------------