github.com/laof/lite-speed-test@v0.0.0-20230930011949-1f39b7037845/transport/socks5/socks5.go (about) 1 package socks5 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "io" 8 "net" 9 "strconv" 10 ) 11 12 // Error represents a SOCKS error 13 type Error byte 14 15 func (err Error) Error() string { 16 return "SOCKS error: " + strconv.Itoa(int(err)) 17 } 18 19 const ( 20 AtypIPv4 = 1 21 AtypDomainName = 3 22 AtypIPv6 = 4 23 ) 24 25 // SOCKS errors as defined in RFC 1928 section 6. 26 const ( 27 ErrGeneralFailure = Error(1) 28 ErrConnectionNotAllowed = Error(2) 29 ErrNetworkUnreachable = Error(3) 30 ErrHostUnreachable = Error(4) 31 ErrConnectionRefused = Error(5) 32 ErrTTLExpired = Error(6) 33 ErrCommandNotSupported = Error(7) 34 ErrAddressNotSupported = Error(8) 35 ) 36 37 // MaxAddrLen is the maximum size of SOCKS address in bytes. 38 const MaxAddrLen = 1 + 1 + 255 + 2 39 40 type Addr []byte 41 42 func (a Addr) String() string { 43 var host, port string 44 45 switch a[0] { 46 case AtypDomainName: 47 hostLen := uint16(a[1]) 48 host = string(a[2 : 2+hostLen]) 49 port = strconv.Itoa((int(a[2+hostLen]) << 8) | int(a[2+hostLen+1])) 50 case AtypIPv4: 51 host = net.IP(a[1 : 1+net.IPv4len]).String() 52 port = strconv.Itoa((int(a[1+net.IPv4len]) << 8) | int(a[1+net.IPv4len+1])) 53 case AtypIPv6: 54 host = net.IP(a[1 : 1+net.IPv6len]).String() 55 port = strconv.Itoa((int(a[1+net.IPv6len]) << 8) | int(a[1+net.IPv6len+1])) 56 } 57 58 return net.JoinHostPort(host, port) 59 } 60 61 func (a Addr) UDPAddr() *net.UDPAddr { 62 if len(a) == 0 { 63 return nil 64 } 65 switch a[0] { 66 case AtypIPv4: 67 var ip [net.IPv4len]byte 68 copy(ip[0:], a[1:1+net.IPv4len]) 69 return &net.UDPAddr{IP: net.IP(ip[:]), Port: int(binary.BigEndian.Uint16(a[1+net.IPv4len : 1+net.IPv4len+2]))} 70 case AtypIPv6: 71 var ip [net.IPv6len]byte 72 copy(ip[0:], a[1:1+net.IPv6len]) 73 return &net.UDPAddr{IP: net.IP(ip[:]), Port: int(binary.BigEndian.Uint16(a[1+net.IPv6len : 1+net.IPv6len+2]))} 74 } 75 // Other Atyp 76 return nil 77 } 78 79 func SplitAddr(b []byte) Addr { 80 addrLen := 1 81 if len(b) < addrLen { 82 return nil 83 } 84 85 switch b[0] { 86 case AtypDomainName: 87 if len(b) < 2 { 88 return nil 89 } 90 addrLen = 1 + 1 + int(b[1]) + 2 91 case AtypIPv4: 92 addrLen = 1 + net.IPv4len + 2 93 case AtypIPv6: 94 addrLen = 1 + net.IPv6len + 2 95 default: 96 return nil 97 98 } 99 100 if len(b) < addrLen { 101 return nil 102 } 103 104 return b[:addrLen] 105 } 106 107 func ReadAddr(r io.Reader, b []byte) (Addr, error) { 108 if len(b) < MaxAddrLen { 109 return nil, io.ErrShortBuffer 110 } 111 _, err := io.ReadFull(r, b[:1]) // read 1st byte for address type 112 if err != nil { 113 return nil, err 114 } 115 116 switch b[0] { 117 case AtypDomainName: 118 _, err = io.ReadFull(r, b[1:2]) // read 2nd byte for domain length 119 if err != nil { 120 return nil, err 121 } 122 domainLength := uint16(b[1]) 123 _, err = io.ReadFull(r, b[2:2+domainLength+2]) 124 return b[:1+1+domainLength+2], err 125 case AtypIPv4: 126 _, err = io.ReadFull(r, b[1:1+net.IPv4len+2]) 127 return b[:1+net.IPv4len+2], err 128 case AtypIPv6: 129 _, err = io.ReadFull(r, b[1:1+net.IPv6len+2]) 130 return b[:1+net.IPv6len+2], err 131 } 132 133 return nil, ErrAddressNotSupported 134 } 135 136 func ParseAddrToSocksAddr(addr net.Addr) Addr { 137 var hostip net.IP 138 var port int 139 if udpaddr, ok := addr.(*net.UDPAddr); ok { 140 hostip = udpaddr.IP 141 port = udpaddr.Port 142 } else if tcpaddr, ok := addr.(*net.TCPAddr); ok { 143 hostip = tcpaddr.IP 144 port = tcpaddr.Port 145 } 146 147 // fallback parse 148 if hostip == nil { 149 return ParseAddr(addr.String()) 150 } 151 152 var parsed Addr 153 if ip4 := hostip.To4(); ip4.DefaultMask() != nil { 154 parsed = make([]byte, 1+net.IPv4len+2) 155 parsed[0] = AtypIPv4 156 copy(parsed[1:], ip4) 157 binary.BigEndian.PutUint16(parsed[1+net.IPv4len:], uint16(port)) 158 159 } else { 160 parsed = make([]byte, 1+net.IPv6len+2) 161 parsed[0] = AtypIPv6 162 copy(parsed[1:], hostip) 163 binary.BigEndian.PutUint16(parsed[1+net.IPv6len:], uint16(port)) 164 } 165 return parsed 166 } 167 168 // ParseAddr parses the address in string s. Returns nil if failed. 169 func ParseAddr(s string) Addr { 170 var addr Addr 171 host, port, err := net.SplitHostPort(s) 172 if err != nil { 173 return nil 174 } 175 if ip := net.ParseIP(host); ip != nil { 176 if ip4 := ip.To4(); ip4 != nil { 177 addr = make([]byte, 1+net.IPv4len+2) 178 addr[0] = AtypIPv4 179 copy(addr[1:], ip4) 180 } else { 181 addr = make([]byte, 1+net.IPv6len+2) 182 addr[0] = AtypIPv6 183 copy(addr[1:], ip) 184 } 185 } else { 186 if len(host) > 255 { 187 return nil 188 } 189 addr = make([]byte, 1+1+len(host)+2) 190 addr[0] = AtypDomainName 191 addr[1] = byte(len(host)) 192 copy(addr[2:], host) 193 } 194 195 portnum, err := strconv.ParseUint(port, 10, 16) 196 if err != nil { 197 return nil 198 } 199 200 addr[len(addr)-2], addr[len(addr)-1] = byte(portnum>>8), byte(portnum) 201 202 return addr 203 } 204 205 func EncodeUDPPacket(addr Addr, payload []byte) (packet []byte, err error) { 206 if addr == nil { 207 err = errors.New("address is invalid") 208 return 209 } 210 packet = bytes.Join([][]byte{{0, 0, 0}, addr, payload}, []byte{}) 211 return 212 }