github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/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.NewSize(len(request.Methods) + 2) 52 defer buffer.Release() 53 common.Must( 54 buffer.WriteByte(Version), 55 buffer.WriteByte(byte(len(request.Methods))), 56 common.Error(buffer.Write(request.Methods)), 57 ) 58 return rw.WriteBytes(writer, buffer.Bytes()) 59 } 60 61 func ReadAuthRequest(reader io.Reader) (request AuthRequest, err error) { 62 version, err := rw.ReadByte(reader) 63 if err != nil { 64 return 65 } 66 if version != Version { 67 err = E.New("expected socks version 5, got ", version) 68 return 69 } 70 return ReadAuthRequest0(reader) 71 } 72 73 func ReadAuthRequest0(reader io.Reader) (request AuthRequest, err error) { 74 methodLen, err := rw.ReadByte(reader) 75 if err != nil { 76 return 77 } 78 request.Methods, err = rw.ReadBytes(reader, int(methodLen)) 79 return 80 } 81 82 // +----+--------+ 83 // |VER | METHOD | 84 // +----+--------+ 85 // | 1 | 1 | 86 // +----+--------+ 87 88 type AuthResponse struct { 89 Method byte 90 } 91 92 func WriteAuthResponse(writer io.Writer, response AuthResponse) error { 93 return rw.WriteBytes(writer, []byte{Version, response.Method}) 94 } 95 96 func ReadAuthResponse(reader io.Reader) (response AuthResponse, err error) { 97 version, err := rw.ReadByte(reader) 98 if err != nil { 99 return 100 } 101 if version != Version { 102 err = E.New("expected socks version 5, got ", version) 103 return 104 } 105 response.Method, err = rw.ReadByte(reader) 106 return 107 } 108 109 // +----+------+----------+------+----------+ 110 // |VER | ULEN | UNAME | PLEN | PASSWD | 111 // +----+------+----------+------+----------+ 112 // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | 113 // +----+------+----------+------+----------+ 114 115 type UsernamePasswordAuthRequest struct { 116 Username string 117 Password string 118 } 119 120 func WriteUsernamePasswordAuthRequest(writer io.Writer, request UsernamePasswordAuthRequest) error { 121 buffer := buf.NewSize(3 + len(request.Username) + len(request.Password)) 122 defer buffer.Release() 123 common.Must( 124 buffer.WriteByte(1), 125 M.WriteSocksString(buffer, request.Username), 126 M.WriteSocksString(buffer, request.Password), 127 ) 128 return rw.WriteBytes(writer, buffer.Bytes()) 129 } 130 131 func ReadUsernamePasswordAuthRequest(reader io.Reader) (request UsernamePasswordAuthRequest, err error) { 132 version, err := rw.ReadByte(reader) 133 if err != nil { 134 return 135 } 136 if version != 1 { 137 err = E.New("excepted password request version 1, got ", version) 138 return 139 } 140 request.Username, err = M.ReadSockString(reader) 141 if err != nil { 142 return 143 } 144 request.Password, err = M.ReadSockString(reader) 145 if err != nil { 146 return 147 } 148 return 149 } 150 151 // +----+--------+ 152 // |VER | STATUS | 153 // +----+--------+ 154 // | 1 | 1 | 155 // +----+--------+ 156 157 type UsernamePasswordAuthResponse struct { 158 Status byte 159 } 160 161 func WriteUsernamePasswordAuthResponse(writer io.Writer, response UsernamePasswordAuthResponse) error { 162 return rw.WriteBytes(writer, []byte{1, response.Status}) 163 } 164 165 func ReadUsernamePasswordAuthResponse(reader io.Reader) (response UsernamePasswordAuthResponse, err error) { 166 version, err := rw.ReadByte(reader) 167 if err != nil { 168 return 169 } 170 if version != 1 { 171 err = E.New("excepted password request version 1, got ", version) 172 return 173 } 174 response.Status, err = rw.ReadByte(reader) 175 return 176 } 177 178 // +----+-----+-------+------+----------+----------+ 179 // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 180 // +----+-----+-------+------+----------+----------+ 181 // | 1 | 1 | X'00' | 1 | Variable | 2 | 182 // +----+-----+-------+------+----------+----------+ 183 184 type Request struct { 185 Command byte 186 Destination M.Socksaddr 187 } 188 189 func WriteRequest(writer io.Writer, request Request) error { 190 buffer := buf.NewSize(3 + M.SocksaddrSerializer.AddrPortLen(request.Destination)) 191 defer buffer.Release() 192 common.Must( 193 buffer.WriteByte(Version), 194 buffer.WriteByte(request.Command), 195 buffer.WriteZero(), 196 ) 197 err := M.SocksaddrSerializer.WriteAddrPort(buffer, request.Destination) 198 if err != nil { 199 return err 200 } 201 return rw.WriteBytes(writer, buffer.Bytes()) 202 } 203 204 func ReadRequest(reader io.Reader) (request Request, err error) { 205 version, err := rw.ReadByte(reader) 206 if err != nil { 207 return 208 } 209 if version != Version { 210 err = E.New("expected socks version 5, got ", version) 211 return 212 } 213 request.Command, err = rw.ReadByte(reader) 214 if err != nil { 215 return 216 } 217 err = rw.Skip(reader) 218 if err != nil { 219 return 220 } 221 request.Destination, err = M.SocksaddrSerializer.ReadAddrPort(reader) 222 return 223 } 224 225 // +----+-----+-------+------+----------+----------+ 226 // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 227 // +----+-----+-------+------+----------+----------+ 228 // | 1 | 1 | X'00' | 1 | Variable | 2 | 229 // +----+-----+-------+------+----------+----------+ 230 231 type Response struct { 232 ReplyCode byte 233 Bind M.Socksaddr 234 } 235 236 func WriteResponse(writer io.Writer, response Response) error { 237 var bind M.Socksaddr 238 if response.Bind.IsValid() { 239 bind = response.Bind 240 } else { 241 bind.Addr = netip.IPv4Unspecified() 242 } 243 244 buffer := buf.NewSize(3 + M.SocksaddrSerializer.AddrPortLen(bind)) 245 defer buffer.Release() 246 common.Must( 247 buffer.WriteByte(Version), 248 buffer.WriteByte(response.ReplyCode), 249 buffer.WriteZero(), 250 ) 251 err := M.SocksaddrSerializer.WriteAddrPort(buffer, bind) 252 if err != nil { 253 return err 254 } 255 return rw.WriteBytes(writer, buffer.Bytes()) 256 } 257 258 func ReadResponse(reader io.Reader) (response Response, err error) { 259 version, err := rw.ReadByte(reader) 260 if err != nil { 261 return 262 } 263 if version != Version { 264 err = E.New("expected socks version 5, got ", version) 265 return 266 } 267 response.ReplyCode, err = rw.ReadByte(reader) 268 if err != nil { 269 return 270 } 271 err = rw.Skip(reader) 272 if err != nil { 273 return 274 } 275 response.Bind, err = M.SocksaddrSerializer.ReadAddrPort(reader) 276 return 277 }