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  }