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  }