github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/libs/tinysocks/socks5.go (about) 1 package tinysocks 2 3 import ( 4 "errors" 5 "io" 6 "net" 7 "strconv" 8 ) 9 10 // SOCKS request commands as defined in RFC 1928 section 4. 11 const ( 12 CmdConnect = 1 13 CmdBind = 2 14 CmdUDPAssociate = 3 15 ) 16 17 // SOCKS address types as defined in RFC 1928 section 5. 18 const ( 19 AtypIPv4 = 1 20 AtypDomainName = 3 21 AtypIPv6 = 4 22 ) 23 24 // Error represents a SOCKS error 25 type Error byte 26 27 func (err Error) Error() string { 28 return "SOCKS error: " + strconv.Itoa(int(err)) 29 } 30 31 // SOCKS errors as defined in RFC 1928 section 6. 32 const ( 33 ErrGeneralFailure = Error(1) 34 ErrConnectionNotAllowed = Error(2) 35 ErrNetworkUnreachable = Error(3) 36 ErrHostUnreachable = Error(4) 37 ErrConnectionRefused = Error(5) 38 ErrTTLExpired = Error(6) 39 ErrCommandNotSupported = Error(7) 40 ErrAddressNotSupported = Error(8) 41 InfoUDPAssociate = Error(9) 42 ) 43 44 // MaxAddrLen is the maximum size of SOCKS address in bytes. 45 const MaxAddrLen = 1 + 1 + 255 + 2 46 47 // Addr represents a SOCKS address as defined in RFC 1928 section 5. 48 type Addr []byte 49 50 // String serializes SOCKS address a to string form. 51 func (a Addr) String() string { 52 var host, port string 53 54 switch a[0] { // address type 55 case AtypDomainName: 56 host = string(a[2 : 2+int(a[1])]) 57 port = strconv.Itoa((int(a[2+int(a[1])]) << 8) | int(a[2+int(a[1])+1])) 58 case AtypIPv4: 59 host = net.IP(a[1 : 1+net.IPv4len]).String() 60 port = strconv.Itoa((int(a[1+net.IPv4len]) << 8) | int(a[1+net.IPv4len+1])) 61 case AtypIPv6: 62 host = net.IP(a[1 : 1+net.IPv6len]).String() 63 port = strconv.Itoa((int(a[1+net.IPv6len]) << 8) | int(a[1+net.IPv6len+1])) 64 } 65 66 return net.JoinHostPort(host, port) 67 } 68 69 func readAddr(r io.Reader, b []byte) (Addr, error) { 70 if len(b) < MaxAddrLen { 71 return nil, io.ErrShortBuffer 72 } 73 _, err := io.ReadFull(r, b[:1]) // read 1st byte for address type 74 if err != nil { 75 return nil, err 76 } 77 78 switch b[0] { 79 case AtypDomainName: 80 _, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length 81 if err != nil { 82 return nil, err 83 } 84 _, err = io.ReadFull(r, b[2:2+int(b[1])+2]) 85 return b[:1+1+int(b[1])+2], err 86 case AtypIPv4: 87 _, err = io.ReadFull(r, b[1:1+net.IPv4len+2]) 88 return b[:1+net.IPv4len+2], err 89 case AtypIPv6: 90 _, err = io.ReadFull(r, b[1:1+net.IPv6len+2]) 91 return b[:1+net.IPv6len+2], err 92 } 93 94 return nil, ErrAddressNotSupported 95 } 96 97 // ReadAddr reads just enough bytes from r to get a valid Addr. 98 func ReadAddr(r io.Reader) (Addr, error) { 99 return readAddr(r, make([]byte, MaxAddrLen)) 100 } 101 102 // SplitAddr slices a SOCKS address from beginning of b. Returns nil if failed. 103 func SplitAddr(b []byte) Addr { 104 addrLen := 1 105 if len(b) < addrLen { 106 return nil 107 } 108 109 switch b[0] { 110 case AtypDomainName: 111 if len(b) < 2 { 112 return nil 113 } 114 addrLen = 1 + 1 + int(b[1]) + 2 115 case AtypIPv4: 116 addrLen = 1 + net.IPv4len + 2 117 case AtypIPv6: 118 addrLen = 1 + net.IPv6len + 2 119 default: 120 return nil 121 122 } 123 124 if len(b) < addrLen { 125 return nil 126 } 127 128 return b[:addrLen] 129 } 130 131 // ParseAddr parses the address in string s. Returns nil if failed. 132 func ParseAddr(s string) Addr { 133 var addr Addr 134 host, port, err := net.SplitHostPort(s) 135 if err != nil { 136 return nil 137 } 138 if ip := net.ParseIP(host); ip != nil { 139 if ip4 := ip.To4(); ip4 != nil { 140 addr = make([]byte, 1+net.IPv4len+2) 141 addr[0] = AtypIPv4 142 copy(addr[1:], ip4) 143 } else { 144 addr = make([]byte, 1+net.IPv6len+2) 145 addr[0] = AtypIPv6 146 copy(addr[1:], ip) 147 } 148 } else { 149 if len(host) > 255 { 150 return nil 151 } 152 addr = make([]byte, 1+1+len(host)+2) 153 addr[0] = AtypDomainName 154 addr[1] = byte(len(host)) 155 copy(addr[2:], host) 156 } 157 158 portnum, err := strconv.ParseUint(port, 10, 16) 159 if err != nil { 160 return nil 161 } 162 163 addr[len(addr)-2], addr[len(addr)-1] = byte(portnum>>8), byte(portnum) 164 165 return addr 166 } 167 168 // Handshake fast-tracks SOCKS initialization to get target address to connect. 169 func ReadRequest(rw io.ReadWriter) (byte, Addr, error) { 170 // Read RFC 1928 for request and reply structure and sizes. 171 buf := make([]byte, MaxAddrLen) 172 // read VER, NMETHODS, METHODS 173 if _, err := io.ReadFull(rw, buf[:2]); err != nil { 174 return 0, nil, err 175 } 176 nmethods := buf[1] 177 if _, err := io.ReadFull(rw, buf[:nmethods]); err != nil { 178 return 0, nil, err 179 } 180 // write VER METHOD 181 if _, err := rw.Write([]byte{5, 0}); err != nil { 182 return 0, nil, err 183 } 184 // read VER CMD RSV ATYP DST.ADDR DST.PORT 185 if _, err := io.ReadFull(rw, buf[:3]); err != nil { 186 return 0, nil, err 187 } 188 cmd := buf[1] 189 addr, err := readAddr(rw, buf) 190 if err != nil { 191 return 0, nil, err 192 } 193 return cmd, addr, err // skip VER, RSV fields 194 } 195 196 // Reply to client abount condition of proxy target 197 func CompleteRequestTCP(errcode byte, conn io.ReadWriteCloser) error { 198 _, err := conn.Write([]byte{5, errcode, 0, 1, 0, 0, 0, 0, 0, 0}) 199 if err != nil { 200 return errors.New("Couldn't complete handshake") 201 } 202 return nil 203 } 204 205 // Client outbounds SOCKS5 requests. 206 func Client(rw io.ReadWriter, ad Addr, conntype int) (error, Addr) { 207 // Read RFC 1928 for request and reply structure and sizes. 208 buf := make([]byte, MaxAddrLen) 209 // write VER, NMETHODS, METHODS 210 if _, err := rw.Write([]byte{5, 1, 0}); err != nil { 211 return err, nil 212 } 213 // read VER METHOD 214 if _, err := io.ReadFull(rw, buf[:2]); err != nil { 215 return err, nil 216 } 217 if buf[0] != 5 || buf[1] != 0 { 218 return errors.New("SOCKS server mismatch"), nil 219 } 220 if conntype == CmdConnect { 221 // write VER, CMD, RSV, ATYP, DST.ADDR, DST.PORT 222 copy(buf[:], []byte{5, 1, 0}) 223 copy(buf[3:], ad) 224 lentosend := 3 + len(ad) 225 if _, err := rw.Write(buf[:lentosend]); err != nil { 226 return err, nil 227 } 228 _, err := io.ReadFull(rw, buf[:3]) 229 if err != nil { 230 return errors.New("Couldn't read server response"), nil 231 } 232 if buf[1] != 0 { 233 err = errors.New("Failed to pass to local proxy") 234 } 235 readAddr(rw, buf) 236 return err, nil 237 } else if conntype == CmdUDPAssociate { 238 // write VER, CMD, RSV, ATYP, DST.ADDR, DST.PORT 239 copy(buf[:], []byte{5, 3, 0}) 240 copy(buf[3:], ad) 241 lentosend := 3 + len(ad) 242 if _, err := rw.Write(buf[:lentosend]); err != nil { 243 return err, nil 244 } 245 _, err := io.ReadFull(rw, buf[:3]) 246 if err != nil { 247 return errors.New("Couldn't read server response"), nil 248 } 249 if buf[1] != 0 { 250 err = errors.New("Failed to pass to local proxy") 251 } 252 addr, err := readAddr(rw, buf) 253 return err, addr 254 } else { 255 return errors.New("SOCKS command unsupported"), nil 256 } 257 }