github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/proxy/socks/protocol.go (about)

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