github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/proxy/socks/protocol.go (about) 1 package socks 2 3 import ( 4 "encoding/binary" 5 "io" 6 gonet "net" 7 8 "github.com/v2fly/v2ray-core/v5/common" 9 "github.com/v2fly/v2ray-core/v5/common/buf" 10 "github.com/v2fly/v2ray-core/v5/common/net" 11 "github.com/v2fly/v2ray-core/v5/common/protocol" 12 ) 13 14 const ( 15 socks5Version = 0x05 16 socks4Version = 0x04 17 18 cmdTCPConnect = 0x01 19 cmdTCPBind = 0x02 20 cmdUDPAssociate = 0x03 21 cmdTorResolve = 0xF0 22 cmdTorResolvePTR = 0xF1 23 24 socks4RequestGranted = 90 25 socks4RequestRejected = 91 26 27 authNotRequired = 0x00 28 // authGssAPI = 0x01 29 authPassword = 0x02 30 authNoMatchingMethod = 0xFF 31 32 statusSuccess = 0x00 33 statusCmdNotSupport = 0x07 34 ) 35 36 var addrParser = protocol.NewAddressParser( 37 protocol.AddressFamilyByte(0x01, net.AddressFamilyIPv4), 38 protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6), 39 protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain), 40 ) 41 42 type ServerSession struct { 43 config *ServerConfig 44 address net.Address 45 port net.Port 46 clientAddress net.Address 47 } 48 49 func (s *ServerSession) handshake4(cmd byte, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) { 50 if s.config.AuthType == AuthType_PASSWORD { 51 writeSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0)) 52 return nil, newError("socks 4 is not allowed when auth is required.") 53 } 54 55 var port net.Port 56 var address net.Address 57 58 { 59 buffer := buf.StackNew() 60 if _, err := buffer.ReadFullFrom(reader, 6); err != nil { 61 buffer.Release() 62 return nil, newError("insufficient header").Base(err) 63 } 64 port = net.PortFromBytes(buffer.BytesRange(0, 2)) 65 address = net.IPAddress(buffer.BytesRange(2, 6)) 66 buffer.Release() 67 } 68 69 if _, err := ReadUntilNull(reader); /* user id */ err != nil { 70 return nil, err 71 } 72 if address.IP()[0] == 0x00 { 73 domain, err := ReadUntilNull(reader) 74 if err != nil { 75 return nil, newError("failed to read domain for socks 4a").Base(err) 76 } 77 address = net.DomainAddress(domain) 78 } 79 80 switch cmd { 81 case cmdTCPConnect: 82 request := &protocol.RequestHeader{ 83 Command: protocol.RequestCommandTCP, 84 Address: address, 85 Port: port, 86 Version: socks4Version, 87 } 88 if err := writeSocks4Response(writer, socks4RequestGranted, net.AnyIP, net.Port(0)); err != nil { 89 return nil, err 90 } 91 return request, nil 92 default: 93 writeSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0)) 94 return nil, newError("unsupported command: ", cmd) 95 } 96 } 97 98 func (s *ServerSession) auth5(nMethod byte, reader io.Reader, writer io.Writer) (username string, err error) { 99 buffer := buf.StackNew() 100 defer buffer.Release() 101 102 if _, err = buffer.ReadFullFrom(reader, int32(nMethod)); err != nil { 103 return "", newError("failed to read auth methods").Base(err) 104 } 105 106 var expectedAuth byte = authNotRequired 107 if s.config.AuthType == AuthType_PASSWORD { 108 expectedAuth = authPassword 109 } 110 111 if !hasAuthMethod(expectedAuth, buffer.BytesRange(0, int32(nMethod))) { 112 writeSocks5AuthenticationResponse(writer, socks5Version, authNoMatchingMethod) 113 return "", newError("no matching auth method") 114 } 115 116 if err := writeSocks5AuthenticationResponse(writer, socks5Version, expectedAuth); err != nil { 117 return "", newError("failed to write auth response").Base(err) 118 } 119 120 if expectedAuth == authPassword { 121 username, password, err := ReadUsernamePassword(reader) 122 if err != nil { 123 return "", newError("failed to read username and password for authentication").Base(err) 124 } 125 126 if !s.config.HasAccount(username, password) { 127 writeSocks5AuthenticationResponse(writer, 0x01, 0xFF) 128 return "", newError("invalid username or password") 129 } 130 131 if err := writeSocks5AuthenticationResponse(writer, 0x01, 0x00); err != nil { 132 return "", newError("failed to write auth response").Base(err) 133 } 134 return username, nil 135 } 136 137 return "", nil 138 } 139 140 func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) { 141 var ( 142 username string 143 err error 144 ) 145 if username, err = s.auth5(nMethod, reader, writer); err != nil { 146 return nil, err 147 } 148 149 var cmd byte 150 { 151 buffer := buf.StackNew() 152 if _, err := buffer.ReadFullFrom(reader, 3); err != nil { 153 buffer.Release() 154 return nil, newError("failed to read request").Base(err) 155 } 156 cmd = buffer.Byte(1) 157 buffer.Release() 158 } 159 160 request := new(protocol.RequestHeader) 161 if username != "" { 162 request.User = &protocol.MemoryUser{Email: username} 163 } 164 switch cmd { 165 case cmdTCPConnect, cmdTorResolve, cmdTorResolvePTR: 166 // We don't have a solution for Tor case now. Simply treat it as connect command. 167 request.Command = protocol.RequestCommandTCP 168 case cmdUDPAssociate: 169 if !s.config.UdpEnabled { 170 writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0)) 171 return nil, newError("UDP is not enabled.") 172 } 173 request.Command = protocol.RequestCommandUDP 174 case cmdTCPBind: 175 writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0)) 176 return nil, newError("TCP bind is not supported.") 177 default: 178 writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0)) 179 return nil, newError("unknown command ", cmd) 180 } 181 182 request.Version = socks5Version 183 184 addr, port, err := addrParser.ReadAddressPort(nil, reader) 185 if err != nil { 186 return nil, newError("failed to read address").Base(err) 187 } 188 request.Address = addr 189 request.Port = port 190 191 responseAddress := s.address 192 responsePort := s.port 193 //nolint:gocritic // Use if else chain for clarity 194 if request.Command == protocol.RequestCommandUDP { 195 if s.config.Address != nil { 196 // Use configured IP as remote address in the response to UdpAssociate 197 responseAddress = s.config.Address.AsAddress() 198 } else if s.clientAddress == net.LocalHostIP || s.clientAddress == net.LocalHostIPv6 { 199 // For localhost clients use loopback IP 200 responseAddress = s.clientAddress 201 } else { 202 // For non-localhost clients use inbound listening address 203 responseAddress = s.address 204 } 205 } 206 if err := writeSocks5Response(writer, statusSuccess, responseAddress, responsePort); err != nil { 207 return nil, err 208 } 209 210 return request, nil 211 } 212 213 // Handshake performs a Socks4/4a/5 handshake. 214 func (s *ServerSession) Handshake(reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) { 215 buffer := buf.StackNew() 216 if _, err := buffer.ReadFullFrom(reader, 2); err != nil { 217 buffer.Release() 218 return nil, newError("insufficient header").Base(err) 219 } 220 221 version := buffer.Byte(0) 222 cmd := buffer.Byte(1) 223 buffer.Release() 224 225 switch version { 226 case socks4Version: 227 return s.handshake4(cmd, reader, writer) 228 case socks5Version: 229 return s.handshake5(cmd, reader, writer) 230 default: 231 return nil, newError("unknown Socks version: ", version) 232 } 233 } 234 235 // ReadUsernamePassword reads Socks 5 username/password message from the given reader. 236 // +----+------+----------+------+----------+ 237 // |VER | ULEN | UNAME | PLEN | PASSWD | 238 // +----+------+----------+------+----------+ 239 // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | 240 // +----+------+----------+------+----------+ 241 func ReadUsernamePassword(reader io.Reader) (string, string, error) { 242 buffer := buf.StackNew() 243 defer buffer.Release() 244 245 if _, err := buffer.ReadFullFrom(reader, 2); err != nil { 246 return "", "", err 247 } 248 nUsername := int32(buffer.Byte(1)) 249 250 buffer.Clear() 251 if _, err := buffer.ReadFullFrom(reader, nUsername); err != nil { 252 return "", "", err 253 } 254 username := buffer.String() 255 256 buffer.Clear() 257 if _, err := buffer.ReadFullFrom(reader, 1); err != nil { 258 return "", "", err 259 } 260 nPassword := int32(buffer.Byte(0)) 261 262 buffer.Clear() 263 if _, err := buffer.ReadFullFrom(reader, nPassword); err != nil { 264 return "", "", err 265 } 266 password := buffer.String() 267 return username, password, nil 268 } 269 270 // ReadUntilNull reads content from given reader, until a null (0x00) byte. 271 func ReadUntilNull(reader io.Reader) (string, error) { 272 b := buf.StackNew() 273 defer b.Release() 274 275 for { 276 _, err := b.ReadFullFrom(reader, 1) 277 if err != nil { 278 return "", err 279 } 280 if b.Byte(b.Len()-1) == 0x00 { 281 b.Resize(0, b.Len()-1) 282 return b.String(), nil 283 } 284 if b.IsFull() { 285 return "", newError("buffer overrun") 286 } 287 } 288 } 289 290 func hasAuthMethod(expectedAuth byte, authCandidates []byte) bool { 291 for _, a := range authCandidates { 292 if a == expectedAuth { 293 return true 294 } 295 } 296 return false 297 } 298 299 func writeSocks5AuthenticationResponse(writer io.Writer, version byte, auth byte) error { 300 return buf.WriteAllBytes(writer, []byte{version, auth}) 301 } 302 303 func writeSocks5Response(writer io.Writer, errCode byte, address net.Address, port net.Port) error { 304 buffer := buf.New() 305 defer buffer.Release() 306 307 common.Must2(buffer.Write([]byte{socks5Version, errCode, 0x00 /* reserved */})) 308 if err := addrParser.WriteAddressPort(buffer, address, port); err != nil { 309 return err 310 } 311 312 return buf.WriteAllBytes(writer, buffer.Bytes()) 313 } 314 315 func writeSocks4Response(writer io.Writer, errCode byte, address net.Address, port net.Port) error { 316 buffer := buf.StackNew() 317 defer buffer.Release() 318 319 common.Must(buffer.WriteByte(0x00)) 320 common.Must(buffer.WriteByte(errCode)) 321 portBytes := buffer.Extend(2) 322 binary.BigEndian.PutUint16(portBytes, port.Value()) 323 common.Must2(buffer.Write(address.IP())) 324 return buf.WriteAllBytes(writer, buffer.Bytes()) 325 } 326 327 func DecodeUDPPacket(packet *buf.Buffer) (*protocol.RequestHeader, error) { 328 if packet.Len() < 5 { 329 return nil, newError("insufficient length of packet.") 330 } 331 request := &protocol.RequestHeader{ 332 Version: socks5Version, 333 Command: protocol.RequestCommandUDP, 334 } 335 336 // packet[0] and packet[1] are reserved 337 if packet.Byte(2) != 0 /* fragments */ { 338 return nil, newError("discarding fragmented payload.") 339 } 340 341 packet.Advance(3) 342 343 addr, port, err := addrParser.ReadAddressPort(nil, packet) 344 if err != nil { 345 return nil, newError("failed to read UDP header").Base(err) 346 } 347 request.Address = addr 348 request.Port = port 349 return request, nil 350 } 351 352 func EncodeUDPPacket(request *protocol.RequestHeader, data []byte) (*buf.Buffer, error) { 353 b := buf.New() 354 common.Must2(b.Write([]byte{0, 0, 0 /* Fragment */})) 355 if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil { 356 b.Release() 357 return nil, err 358 } 359 common.Must2(b.Write(data)) 360 return b, nil 361 } 362 363 func EncodeUDPPacketFromAddress(address net.Destination, data []byte) (*buf.Buffer, error) { 364 b := buf.New() 365 common.Must2(b.Write([]byte{0, 0, 0 /* Fragment */})) 366 if err := addrParser.WriteAddressPort(b, address.Address, address.Port); err != nil { 367 b.Release() 368 return nil, err 369 } 370 common.Must2(b.Write(data)) 371 return b, nil 372 } 373 374 type UDPReader struct { 375 reader io.Reader 376 } 377 378 func NewUDPReader(reader io.Reader) *UDPReader { 379 return &UDPReader{reader: reader} 380 } 381 382 func (r *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) { 383 b := buf.New() 384 if _, err := b.ReadFrom(r.reader); err != nil { 385 return nil, err 386 } 387 if _, err := DecodeUDPPacket(b); err != nil { 388 return nil, err 389 } 390 return buf.MultiBuffer{b}, nil 391 } 392 393 func (r *UDPReader) ReadFrom(p []byte) (n int, addr gonet.Addr, err error) { 394 buffer := buf.New() 395 _, err = buffer.ReadFrom(r.reader) 396 if err != nil { 397 buffer.Release() 398 return 0, nil, err 399 } 400 req, err := DecodeUDPPacket(buffer) 401 if err != nil { 402 buffer.Release() 403 return 0, nil, err 404 } 405 n = copy(p, buffer.Bytes()) 406 buffer.Release() 407 return n, &gonet.UDPAddr{IP: req.Address.IP(), Port: int(req.Port)}, nil 408 } 409 410 type UDPWriter struct { 411 request *protocol.RequestHeader 412 writer io.Writer 413 } 414 415 func NewUDPWriter(request *protocol.RequestHeader, writer io.Writer) *UDPWriter { 416 return &UDPWriter{ 417 request: request, 418 writer: writer, 419 } 420 } 421 422 // Write implements io.Writer. 423 func (w *UDPWriter) Write(b []byte) (int, error) { 424 eb, err := EncodeUDPPacket(w.request, b) 425 if err != nil { 426 return 0, err 427 } 428 defer eb.Release() 429 if _, err := w.writer.Write(eb.Bytes()); err != nil { 430 return 0, err 431 } 432 return len(b), nil 433 } 434 435 func (w *UDPWriter) WriteTo(payload []byte, addr gonet.Addr) (n int, err error) { 436 request := *w.request 437 udpAddr := addr.(*gonet.UDPAddr) 438 request.Command = protocol.RequestCommandUDP 439 request.Address = net.IPAddress(udpAddr.IP) 440 request.Port = net.Port(udpAddr.Port) 441 packet, err := EncodeUDPPacket(&request, payload) 442 if err != nil { 443 return 0, err 444 } 445 _, err = w.writer.Write(packet.Bytes()) 446 packet.Release() 447 return len(payload), err 448 } 449 450 func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer io.Writer, delayAuthWrite bool) (*protocol.RequestHeader, error) { 451 authByte := byte(authNotRequired) 452 if request.User != nil { 453 authByte = byte(authPassword) 454 } 455 456 b := buf.New() 457 defer b.Release() 458 459 common.Must2(b.Write([]byte{socks5Version, 0x01, authByte})) 460 if !delayAuthWrite { 461 if authByte == authPassword { 462 account := request.User.Account.(*Account) 463 common.Must(b.WriteByte(0x01)) 464 common.Must(b.WriteByte(byte(len(account.Username)))) 465 common.Must2(b.WriteString(account.Username)) 466 common.Must(b.WriteByte(byte(len(account.Password)))) 467 common.Must2(b.WriteString(account.Password)) 468 } 469 } 470 471 if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil { 472 return nil, err 473 } 474 475 b.Clear() 476 if _, err := b.ReadFullFrom(reader, 2); err != nil { 477 return nil, err 478 } 479 480 if b.Byte(0) != socks5Version { 481 return nil, newError("unexpected server version: ", b.Byte(0)).AtWarning() 482 } 483 if b.Byte(1) != authByte { 484 return nil, newError("auth method not supported.").AtWarning() 485 } 486 487 if authByte == authPassword { 488 b.Clear() 489 if delayAuthWrite { 490 account := request.User.Account.(*Account) 491 common.Must(b.WriteByte(0x01)) 492 common.Must(b.WriteByte(byte(len(account.Username)))) 493 common.Must2(b.WriteString(account.Username)) 494 common.Must(b.WriteByte(byte(len(account.Password)))) 495 common.Must2(b.WriteString(account.Password)) 496 if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil { 497 return nil, err 498 } 499 b.Clear() 500 } 501 if _, err := b.ReadFullFrom(reader, 2); err != nil { 502 return nil, err 503 } 504 if b.Byte(1) != 0x00 { 505 return nil, newError("server rejects account: ", b.Byte(1)) 506 } 507 } 508 509 b.Clear() 510 511 command := byte(cmdTCPConnect) 512 if request.Command == protocol.RequestCommandUDP { 513 command = byte(cmdUDPAssociate) 514 } 515 common.Must2(b.Write([]byte{socks5Version, command, 0x00 /* reserved */})) 516 if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil { 517 return nil, err 518 } 519 520 if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil { 521 return nil, err 522 } 523 524 b.Clear() 525 if _, err := b.ReadFullFrom(reader, 3); err != nil { 526 return nil, err 527 } 528 529 resp := b.Byte(1) 530 if resp != 0x00 { 531 return nil, newError("server rejects request: ", resp) 532 } 533 534 b.Clear() 535 536 address, port, err := addrParser.ReadAddressPort(b, reader) 537 if err != nil { 538 return nil, err 539 } 540 541 if request.Command == protocol.RequestCommandUDP { 542 udpRequest := &protocol.RequestHeader{ 543 Version: socks5Version, 544 Command: protocol.RequestCommandUDP, 545 Address: address, 546 Port: port, 547 } 548 return udpRequest, nil 549 } 550 551 return nil, nil 552 } 553 554 func ClientHandshake4(request *protocol.RequestHeader, reader io.Reader, writer io.Writer) error { 555 b := buf.New() 556 defer b.Release() 557 558 common.Must2(b.Write([]byte{socks4Version, cmdTCPConnect})) 559 portBytes := b.Extend(2) 560 binary.BigEndian.PutUint16(portBytes, request.Port.Value()) 561 switch request.Address.Family() { 562 case net.AddressFamilyIPv4: 563 common.Must2(b.Write(request.Address.IP())) 564 case net.AddressFamilyDomain: 565 common.Must2(b.Write([]byte{0x00, 0x00, 0x00, 0x01})) 566 case net.AddressFamilyIPv6: 567 return newError("ipv6 is not supported in socks4") 568 default: 569 panic("Unknown family type.") 570 } 571 if request.User != nil { 572 account := request.User.Account.(*Account) 573 common.Must2(b.WriteString(account.Username)) 574 } 575 common.Must(b.WriteByte(0x00)) 576 if request.Address.Family() == net.AddressFamilyDomain { 577 common.Must2(b.WriteString(request.Address.Domain())) 578 common.Must(b.WriteByte(0x00)) 579 } 580 if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil { 581 return err 582 } 583 584 b.Clear() 585 if _, err := b.ReadFullFrom(reader, 8); err != nil { 586 return err 587 } 588 if b.Byte(0) != 0x00 { 589 return newError("unexpected version of the reply code: ", b.Byte(0)) 590 } 591 if b.Byte(1) != socks4RequestGranted { 592 return newError("server rejects request: ", b.Byte(1)) 593 } 594 return nil 595 }