github.com/sagernet/sing@v0.2.6/protocol/socks/socks5/protocol.go (about) 1 package socks5 2 3 import ( 4 "io" 5 "net/netip" 6 7 "github.com/sagernet/sing/common" 8 "github.com/sagernet/sing/common/buf" 9 E "github.com/sagernet/sing/common/exceptions" 10 M "github.com/sagernet/sing/common/metadata" 11 "github.com/sagernet/sing/common/rw" 12 ) 13 14 const ( 15 Version byte = 5 16 17 AuthTypeNotRequired byte = 0x00 18 AuthTypeGSSAPI byte = 0x01 19 AuthTypeUsernamePassword byte = 0x02 20 AuthTypeNoAcceptedMethods byte = 0xFF 21 22 UsernamePasswordStatusSuccess byte = 0x00 23 UsernamePasswordStatusFailure byte = 0x01 24 25 CommandConnect byte = 0x01 26 CommandBind byte = 0x02 27 CommandUDPAssociate byte = 0x03 28 29 ReplyCodeSuccess byte = 0 30 ReplyCodeFailure byte = 1 31 ReplyCodeNotAllowed byte = 2 32 ReplyCodeNetworkUnreachable byte = 3 33 ReplyCodeHostUnreachable byte = 4 34 ReplyCodeConnectionRefused byte = 5 35 ReplyCodeTTLExpired byte = 6 36 ReplyCodeUnsupported byte = 7 37 ReplyCodeAddressTypeUnsupported byte = 8 38 ) 39 40 // +----+----------+----------+ 41 // |VER | NMETHODS | METHODS | 42 // +----+----------+----------+ 43 // | 1 | 1 | 1 to 255 | 44 // +----+----------+----------+ 45 46 type AuthRequest struct { 47 Methods []byte 48 } 49 50 func WriteAuthRequest(writer io.Writer, request AuthRequest) error { 51 _buffer := buf.StackNewSize(len(request.Methods) + 2) 52 defer common.KeepAlive(_buffer) 53 buffer := common.Dup(_buffer) 54 defer buffer.Release() 55 common.Must( 56 buffer.WriteByte(Version), 57 buffer.WriteByte(byte(len(request.Methods))), 58 common.Error(buffer.Write(request.Methods)), 59 ) 60 return rw.WriteBytes(writer, buffer.Bytes()) 61 } 62 63 func ReadAuthRequest(reader io.Reader) (request AuthRequest, err error) { 64 version, err := rw.ReadByte(reader) 65 if err != nil { 66 return 67 } 68 if version != Version { 69 err = E.New("expected socks version 5, got ", version) 70 return 71 } 72 return ReadAuthRequest0(reader) 73 } 74 75 func ReadAuthRequest0(reader io.Reader) (request AuthRequest, err error) { 76 methodLen, err := rw.ReadByte(reader) 77 if err != nil { 78 return 79 } 80 request.Methods, err = rw.ReadBytes(reader, int(methodLen)) 81 return 82 } 83 84 // +----+--------+ 85 // |VER | METHOD | 86 // +----+--------+ 87 // | 1 | 1 | 88 // +----+--------+ 89 90 type AuthResponse struct { 91 Method byte 92 } 93 94 func WriteAuthResponse(writer io.Writer, response AuthResponse) error { 95 return rw.WriteBytes(writer, []byte{Version, response.Method}) 96 } 97 98 func ReadAuthResponse(reader io.Reader) (response AuthResponse, err error) { 99 version, err := rw.ReadByte(reader) 100 if err != nil { 101 return 102 } 103 if version != Version { 104 err = E.New("expected socks version 5, got ", version) 105 return 106 } 107 response.Method, err = rw.ReadByte(reader) 108 return 109 } 110 111 // +----+------+----------+------+----------+ 112 // |VER | ULEN | UNAME | PLEN | PASSWD | 113 // +----+------+----------+------+----------+ 114 // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | 115 // +----+------+----------+------+----------+ 116 117 type UsernamePasswordAuthRequest struct { 118 Username string 119 Password string 120 } 121 122 func WriteUsernamePasswordAuthRequest(writer io.Writer, request UsernamePasswordAuthRequest) error { 123 _buffer := buf.StackNewSize(3 + len(request.Username) + len(request.Password)) 124 defer common.KeepAlive(_buffer) 125 buffer := common.Dup(_buffer) 126 defer buffer.Release() 127 common.Must( 128 buffer.WriteByte(1), 129 M.WriteSocksString(buffer, request.Username), 130 M.WriteSocksString(buffer, request.Password), 131 ) 132 return rw.WriteBytes(writer, buffer.Bytes()) 133 } 134 135 func ReadUsernamePasswordAuthRequest(reader io.Reader) (request UsernamePasswordAuthRequest, err error) { 136 version, err := rw.ReadByte(reader) 137 if err != nil { 138 return 139 } 140 if version != 1 { 141 err = E.New("excepted password request version 1, got ", version) 142 return 143 } 144 request.Username, err = M.ReadSockString(reader) 145 if err != nil { 146 return 147 } 148 request.Password, err = M.ReadSockString(reader) 149 if err != nil { 150 return 151 } 152 return 153 } 154 155 // +----+--------+ 156 // |VER | STATUS | 157 // +----+--------+ 158 // | 1 | 1 | 159 // +----+--------+ 160 161 type UsernamePasswordAuthResponse struct { 162 Status byte 163 } 164 165 func WriteUsernamePasswordAuthResponse(writer io.Writer, response UsernamePasswordAuthResponse) error { 166 return rw.WriteBytes(writer, []byte{1, response.Status}) 167 } 168 169 func ReadUsernamePasswordAuthResponse(reader io.Reader) (response UsernamePasswordAuthResponse, err error) { 170 version, err := rw.ReadByte(reader) 171 if err != nil { 172 return 173 } 174 if version != 1 { 175 err = E.New("excepted password request version 1, got ", version) 176 return 177 } 178 response.Status, err = rw.ReadByte(reader) 179 return 180 } 181 182 // +----+-----+-------+------+----------+----------+ 183 // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 184 // +----+-----+-------+------+----------+----------+ 185 // | 1 | 1 | X'00' | 1 | Variable | 2 | 186 // +----+-----+-------+------+----------+----------+ 187 188 type Request struct { 189 Command byte 190 Destination M.Socksaddr 191 } 192 193 func WriteRequest(writer io.Writer, request Request) error { 194 _buffer := buf.StackNewSize(3 + M.SocksaddrSerializer.AddrPortLen(request.Destination)) 195 defer common.KeepAlive(_buffer) 196 buffer := common.Dup(_buffer) 197 defer buffer.Release() 198 common.Must( 199 buffer.WriteByte(Version), 200 buffer.WriteByte(request.Command), 201 buffer.WriteZero(), 202 M.SocksaddrSerializer.WriteAddrPort(buffer, request.Destination), 203 ) 204 return rw.WriteBytes(writer, buffer.Bytes()) 205 } 206 207 func ReadRequest(reader io.Reader) (request Request, err error) { 208 version, err := rw.ReadByte(reader) 209 if err != nil { 210 return 211 } 212 if version != Version { 213 err = E.New("expected socks version 5, got ", version) 214 return 215 } 216 request.Command, err = rw.ReadByte(reader) 217 if err != nil { 218 return 219 } 220 err = rw.Skip(reader) 221 if err != nil { 222 return 223 } 224 request.Destination, err = M.SocksaddrSerializer.ReadAddrPort(reader) 225 return 226 } 227 228 // +----+-----+-------+------+----------+----------+ 229 // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 230 // +----+-----+-------+------+----------+----------+ 231 // | 1 | 1 | X'00' | 1 | Variable | 2 | 232 // +----+-----+-------+------+----------+----------+ 233 234 type Response struct { 235 ReplyCode byte 236 Bind M.Socksaddr 237 } 238 239 func WriteResponse(writer io.Writer, response Response) error { 240 var bind M.Socksaddr 241 if response.Bind.IsValid() { 242 bind = response.Bind 243 } else { 244 bind.Addr = netip.IPv4Unspecified() 245 } 246 247 _buffer := buf.StackNewSize(3 + M.SocksaddrSerializer.AddrPortLen(bind)) 248 defer common.KeepAlive(_buffer) 249 buffer := common.Dup(_buffer) 250 defer buffer.Release() 251 common.Must( 252 buffer.WriteByte(Version), 253 buffer.WriteByte(response.ReplyCode), 254 buffer.WriteZero(), 255 M.SocksaddrSerializer.WriteAddrPort(buffer, bind), 256 ) 257 return rw.WriteBytes(writer, buffer.Bytes()) 258 } 259 260 func ReadResponse(reader io.Reader) (response Response, err error) { 261 version, err := rw.ReadByte(reader) 262 if err != nil { 263 return 264 } 265 if version != Version { 266 err = E.New("expected socks version 5, got ", version) 267 return 268 } 269 response.ReplyCode, err = rw.ReadByte(reader) 270 if err != nil { 271 return 272 } 273 err = rw.Skip(reader) 274 if err != nil { 275 return 276 } 277 response.Bind, err = M.SocksaddrSerializer.ReadAddrPort(reader) 278 return 279 }