github.com/metacubex/mihomo@v1.18.5/transport/tuic/v4/protocol.go (about)

     1  package v4
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"net/netip"
     9  	"strconv"
    10  
    11  	"github.com/metacubex/quic-go"
    12  	"lukechampine.com/blake3"
    13  
    14  	C "github.com/metacubex/mihomo/constant"
    15  	"github.com/metacubex/mihomo/transport/socks5"
    16  )
    17  
    18  type BufferedReader interface {
    19  	io.Reader
    20  	io.ByteReader
    21  }
    22  
    23  type BufferedWriter interface {
    24  	io.Writer
    25  	io.ByteWriter
    26  }
    27  
    28  type CommandType byte
    29  
    30  const (
    31  	AuthenticateType = CommandType(0x00)
    32  	ConnectType      = CommandType(0x01)
    33  	PacketType       = CommandType(0x02)
    34  	DissociateType   = CommandType(0x03)
    35  	HeartbeatType    = CommandType(0x04)
    36  	ResponseType     = CommandType(0xff)
    37  )
    38  
    39  const VER byte = 0x04
    40  
    41  func (c CommandType) String() string {
    42  	switch c {
    43  	case AuthenticateType:
    44  		return "Authenticate"
    45  	case ConnectType:
    46  		return "Connect"
    47  	case PacketType:
    48  		return "Packet"
    49  	case DissociateType:
    50  		return "Dissociate"
    51  	case HeartbeatType:
    52  		return "Heartbeat"
    53  	case ResponseType:
    54  		return "Response"
    55  	default:
    56  		return fmt.Sprintf("UnknowCommand: %#x", byte(c))
    57  	}
    58  }
    59  
    60  func (c CommandType) BytesLen() int {
    61  	return 1
    62  }
    63  
    64  type CommandHead struct {
    65  	VER  byte
    66  	TYPE CommandType
    67  }
    68  
    69  func NewCommandHead(TYPE CommandType) CommandHead {
    70  	return CommandHead{
    71  		VER:  VER,
    72  		TYPE: TYPE,
    73  	}
    74  }
    75  
    76  func ReadCommandHead(reader BufferedReader) (c CommandHead, err error) {
    77  	c.VER, err = reader.ReadByte()
    78  	if err != nil {
    79  		return
    80  	}
    81  	TYPE, err := reader.ReadByte()
    82  	if err != nil {
    83  		return
    84  	}
    85  	c.TYPE = CommandType(TYPE)
    86  	return
    87  }
    88  
    89  func (c CommandHead) WriteTo(writer BufferedWriter) (err error) {
    90  	err = writer.WriteByte(c.VER)
    91  	if err != nil {
    92  		return
    93  	}
    94  	err = writer.WriteByte(byte(c.TYPE))
    95  	if err != nil {
    96  		return
    97  	}
    98  	return
    99  }
   100  
   101  func (c CommandHead) BytesLen() int {
   102  	return 1 + c.TYPE.BytesLen()
   103  }
   104  
   105  type Authenticate struct {
   106  	CommandHead
   107  	TKN [32]byte
   108  }
   109  
   110  func NewAuthenticate(TKN [32]byte) Authenticate {
   111  	return Authenticate{
   112  		CommandHead: NewCommandHead(AuthenticateType),
   113  		TKN:         TKN,
   114  	}
   115  }
   116  
   117  func ReadAuthenticateWithHead(head CommandHead, reader BufferedReader) (c Authenticate, err error) {
   118  	c.CommandHead = head
   119  	if c.CommandHead.TYPE != AuthenticateType {
   120  		err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE)
   121  		return
   122  	}
   123  	_, err = io.ReadFull(reader, c.TKN[:])
   124  	if err != nil {
   125  		return
   126  	}
   127  	return
   128  }
   129  
   130  func ReadAuthenticate(reader BufferedReader) (c Authenticate, err error) {
   131  	head, err := ReadCommandHead(reader)
   132  	if err != nil {
   133  		return
   134  	}
   135  	return ReadAuthenticateWithHead(head, reader)
   136  }
   137  
   138  func GenTKN(token string) [32]byte {
   139  	return blake3.Sum256([]byte(token))
   140  }
   141  
   142  func (c Authenticate) WriteTo(writer BufferedWriter) (err error) {
   143  	err = c.CommandHead.WriteTo(writer)
   144  	if err != nil {
   145  		return
   146  	}
   147  	_, err = writer.Write(c.TKN[:])
   148  	if err != nil {
   149  		return
   150  	}
   151  	return
   152  }
   153  
   154  func (c Authenticate) BytesLen() int {
   155  	return c.CommandHead.BytesLen() + 32
   156  }
   157  
   158  type Connect struct {
   159  	CommandHead
   160  	ADDR Address
   161  }
   162  
   163  func NewConnect(ADDR Address) Connect {
   164  	return Connect{
   165  		CommandHead: NewCommandHead(ConnectType),
   166  		ADDR:        ADDR,
   167  	}
   168  }
   169  
   170  func ReadConnectWithHead(head CommandHead, reader BufferedReader) (c Connect, err error) {
   171  	c.CommandHead = head
   172  	if c.CommandHead.TYPE != ConnectType {
   173  		err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE)
   174  		return
   175  	}
   176  	c.ADDR, err = ReadAddress(reader)
   177  	if err != nil {
   178  		return
   179  	}
   180  	return
   181  }
   182  
   183  func ReadConnect(reader BufferedReader) (c Connect, err error) {
   184  	head, err := ReadCommandHead(reader)
   185  	if err != nil {
   186  		return
   187  	}
   188  	return ReadConnectWithHead(head, reader)
   189  }
   190  
   191  func (c Connect) WriteTo(writer BufferedWriter) (err error) {
   192  	err = c.CommandHead.WriteTo(writer)
   193  	if err != nil {
   194  		return
   195  	}
   196  	err = c.ADDR.WriteTo(writer)
   197  	if err != nil {
   198  		return
   199  	}
   200  	return
   201  }
   202  
   203  func (c Connect) BytesLen() int {
   204  	return c.CommandHead.BytesLen() + c.ADDR.BytesLen()
   205  }
   206  
   207  type Packet struct {
   208  	CommandHead
   209  	ASSOC_ID uint32
   210  	LEN      uint16
   211  	ADDR     Address
   212  	DATA     []byte
   213  }
   214  
   215  func NewPacket(ASSOC_ID uint32, LEN uint16, ADDR Address, DATA []byte) Packet {
   216  	return Packet{
   217  		CommandHead: NewCommandHead(PacketType),
   218  		ASSOC_ID:    ASSOC_ID,
   219  		LEN:         LEN,
   220  		ADDR:        ADDR,
   221  		DATA:        DATA,
   222  	}
   223  }
   224  
   225  func ReadPacketWithHead(head CommandHead, reader BufferedReader) (c Packet, err error) {
   226  	c.CommandHead = head
   227  	if c.CommandHead.TYPE != PacketType {
   228  		err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE)
   229  		return
   230  	}
   231  	err = binary.Read(reader, binary.BigEndian, &c.ASSOC_ID)
   232  	if err != nil {
   233  		return
   234  	}
   235  	err = binary.Read(reader, binary.BigEndian, &c.LEN)
   236  	if err != nil {
   237  		return
   238  	}
   239  	c.ADDR, err = ReadAddress(reader)
   240  	if err != nil {
   241  		return
   242  	}
   243  	c.DATA = make([]byte, c.LEN)
   244  	_, err = io.ReadFull(reader, c.DATA)
   245  	if err != nil {
   246  		return
   247  	}
   248  	return
   249  }
   250  
   251  func ReadPacket(reader BufferedReader) (c Packet, err error) {
   252  	head, err := ReadCommandHead(reader)
   253  	if err != nil {
   254  		return
   255  	}
   256  	return ReadPacketWithHead(head, reader)
   257  }
   258  
   259  func (c Packet) WriteTo(writer BufferedWriter) (err error) {
   260  	err = c.CommandHead.WriteTo(writer)
   261  	if err != nil {
   262  		return
   263  	}
   264  	err = binary.Write(writer, binary.BigEndian, c.ASSOC_ID)
   265  	if err != nil {
   266  		return
   267  	}
   268  	err = binary.Write(writer, binary.BigEndian, c.LEN)
   269  	if err != nil {
   270  		return
   271  	}
   272  	err = c.ADDR.WriteTo(writer)
   273  	if err != nil {
   274  		return
   275  	}
   276  	_, err = writer.Write(c.DATA)
   277  	if err != nil {
   278  		return
   279  	}
   280  	return
   281  }
   282  
   283  func (c Packet) BytesLen() int {
   284  	return c.CommandHead.BytesLen() + 4 + 2 + c.ADDR.BytesLen() + len(c.DATA)
   285  }
   286  
   287  var PacketOverHead = NewPacket(0, 0, NewAddressAddrPort(netip.AddrPortFrom(netip.IPv6Unspecified(), 0)), nil).BytesLen()
   288  
   289  type Dissociate struct {
   290  	CommandHead
   291  	ASSOC_ID uint32
   292  }
   293  
   294  func NewDissociate(ASSOC_ID uint32) Dissociate {
   295  	return Dissociate{
   296  		CommandHead: NewCommandHead(DissociateType),
   297  		ASSOC_ID:    ASSOC_ID,
   298  	}
   299  }
   300  
   301  func ReadDissociateWithHead(head CommandHead, reader BufferedReader) (c Dissociate, err error) {
   302  	c.CommandHead = head
   303  	if c.CommandHead.TYPE != DissociateType {
   304  		err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE)
   305  		return
   306  	}
   307  	err = binary.Read(reader, binary.BigEndian, &c.ASSOC_ID)
   308  	if err != nil {
   309  		return
   310  	}
   311  	return
   312  }
   313  
   314  func ReadDissociate(reader BufferedReader) (c Dissociate, err error) {
   315  	head, err := ReadCommandHead(reader)
   316  	if err != nil {
   317  		return
   318  	}
   319  	return ReadDissociateWithHead(head, reader)
   320  }
   321  
   322  func (c Dissociate) WriteTo(writer BufferedWriter) (err error) {
   323  	err = c.CommandHead.WriteTo(writer)
   324  	if err != nil {
   325  		return
   326  	}
   327  	err = binary.Write(writer, binary.BigEndian, c.ASSOC_ID)
   328  	if err != nil {
   329  		return
   330  	}
   331  	return
   332  }
   333  
   334  func (c Dissociate) BytesLen() int {
   335  	return c.CommandHead.BytesLen() + 4
   336  }
   337  
   338  type Heartbeat struct {
   339  	CommandHead
   340  }
   341  
   342  func NewHeartbeat() Heartbeat {
   343  	return Heartbeat{
   344  		CommandHead: NewCommandHead(HeartbeatType),
   345  	}
   346  }
   347  
   348  func ReadHeartbeatWithHead(head CommandHead, reader BufferedReader) (c Heartbeat, err error) {
   349  	c.CommandHead = head
   350  	if c.CommandHead.TYPE != HeartbeatType {
   351  		err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE)
   352  		return
   353  	}
   354  	return
   355  }
   356  
   357  func ReadHeartbeat(reader BufferedReader) (c Heartbeat, err error) {
   358  	head, err := ReadCommandHead(reader)
   359  	if err != nil {
   360  		return
   361  	}
   362  	return ReadHeartbeatWithHead(head, reader)
   363  }
   364  
   365  type Response struct {
   366  	CommandHead
   367  	REP byte
   368  }
   369  
   370  func NewResponse(REP byte) Response {
   371  	return Response{
   372  		CommandHead: NewCommandHead(ResponseType),
   373  		REP:         REP,
   374  	}
   375  }
   376  
   377  func NewResponseSucceed() Response {
   378  	return NewResponse(0x00)
   379  }
   380  
   381  func NewResponseFailed() Response {
   382  	return NewResponse(0xff)
   383  }
   384  
   385  func ReadResponseWithHead(head CommandHead, reader BufferedReader) (c Response, err error) {
   386  	c.CommandHead = head
   387  	if c.CommandHead.TYPE != ResponseType {
   388  		err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE)
   389  		return
   390  	}
   391  	c.REP, err = reader.ReadByte()
   392  	if err != nil {
   393  		return
   394  	}
   395  	return
   396  }
   397  
   398  func ReadResponse(reader BufferedReader) (c Response, err error) {
   399  	head, err := ReadCommandHead(reader)
   400  	if err != nil {
   401  		return
   402  	}
   403  	return ReadResponseWithHead(head, reader)
   404  }
   405  
   406  func (c Response) WriteTo(writer BufferedWriter) (err error) {
   407  	err = c.CommandHead.WriteTo(writer)
   408  	if err != nil {
   409  		return
   410  	}
   411  	err = writer.WriteByte(c.REP)
   412  	if err != nil {
   413  		return
   414  	}
   415  	return
   416  }
   417  
   418  func (c Response) IsSucceed() bool {
   419  	return c.REP == 0x00
   420  }
   421  
   422  func (c Response) IsFailed() bool {
   423  	return c.REP == 0xff
   424  }
   425  
   426  func (c Response) BytesLen() int {
   427  	return c.CommandHead.BytesLen() + 1
   428  }
   429  
   430  // Addr types
   431  const (
   432  	AtypDomainName byte = 0
   433  	AtypIPv4       byte = 1
   434  	AtypIPv6       byte = 2
   435  )
   436  
   437  type Address struct {
   438  	TYPE byte
   439  	ADDR []byte
   440  	PORT uint16
   441  }
   442  
   443  func NewAddress(metadata *C.Metadata) Address {
   444  	var addrType byte
   445  	var addr []byte
   446  	switch metadata.AddrType() {
   447  	case socks5.AtypIPv4:
   448  		addrType = AtypIPv4
   449  		addr = metadata.DstIP.AsSlice()
   450  	case socks5.AtypIPv6:
   451  		addrType = AtypIPv6
   452  		addr = metadata.DstIP.AsSlice()
   453  	case socks5.AtypDomainName:
   454  		addrType = AtypDomainName
   455  		addr = make([]byte, len(metadata.Host)+1)
   456  		addr[0] = byte(len(metadata.Host))
   457  		copy(addr[1:], metadata.Host)
   458  	}
   459  
   460  	return Address{
   461  		TYPE: addrType,
   462  		ADDR: addr,
   463  		PORT: metadata.DstPort,
   464  	}
   465  }
   466  
   467  func NewAddressNetAddr(addr net.Addr) (Address, error) {
   468  	if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok {
   469  		if addrPort := addr.AddrPort(); addrPort.IsValid() { // sing's M.Socksaddr maybe return an invalid AddrPort if it's a DomainName
   470  			return NewAddressAddrPort(addrPort), nil
   471  		}
   472  	}
   473  	addrStr := addr.String()
   474  	if addrPort, err := netip.ParseAddrPort(addrStr); err == nil {
   475  		return NewAddressAddrPort(addrPort), nil
   476  	}
   477  	metadata := &C.Metadata{}
   478  	if err := metadata.SetRemoteAddress(addrStr); err != nil {
   479  		return Address{}, err
   480  	}
   481  	return NewAddress(metadata), nil
   482  }
   483  
   484  func NewAddressAddrPort(addrPort netip.AddrPort) Address {
   485  	var addrType byte
   486  	port := addrPort.Port()
   487  	addr := addrPort.Addr().Unmap()
   488  	if addr.Is4() {
   489  		addrType = AtypIPv4
   490  	} else {
   491  		addrType = AtypIPv6
   492  	}
   493  	return Address{
   494  		TYPE: addrType,
   495  		ADDR: addr.AsSlice(),
   496  		PORT: port,
   497  	}
   498  }
   499  
   500  func ReadAddress(reader BufferedReader) (c Address, err error) {
   501  	c.TYPE, err = reader.ReadByte()
   502  	if err != nil {
   503  		return
   504  	}
   505  	switch c.TYPE {
   506  	case AtypIPv4:
   507  		c.ADDR = make([]byte, net.IPv4len)
   508  		_, err = io.ReadFull(reader, c.ADDR)
   509  		if err != nil {
   510  			return
   511  		}
   512  	case AtypIPv6:
   513  		c.ADDR = make([]byte, net.IPv6len)
   514  		_, err = io.ReadFull(reader, c.ADDR)
   515  		if err != nil {
   516  			return
   517  		}
   518  	case AtypDomainName:
   519  		var addrLen byte
   520  		addrLen, err = reader.ReadByte()
   521  		if err != nil {
   522  			return
   523  		}
   524  		c.ADDR = make([]byte, addrLen+1)
   525  		c.ADDR[0] = addrLen
   526  		_, err = io.ReadFull(reader, c.ADDR[1:])
   527  		if err != nil {
   528  			return
   529  		}
   530  	}
   531  
   532  	err = binary.Read(reader, binary.BigEndian, &c.PORT)
   533  	if err != nil {
   534  		return
   535  	}
   536  	return
   537  }
   538  
   539  func (c Address) WriteTo(writer BufferedWriter) (err error) {
   540  	err = writer.WriteByte(c.TYPE)
   541  	if err != nil {
   542  		return
   543  	}
   544  	_, err = writer.Write(c.ADDR[:])
   545  	if err != nil {
   546  		return
   547  	}
   548  	err = binary.Write(writer, binary.BigEndian, c.PORT)
   549  	if err != nil {
   550  		return
   551  	}
   552  	return
   553  }
   554  
   555  func (c Address) String() string {
   556  	switch c.TYPE {
   557  	case AtypDomainName:
   558  		return net.JoinHostPort(string(c.ADDR[1:]), strconv.Itoa(int(c.PORT)))
   559  	default:
   560  		addr, _ := netip.AddrFromSlice(c.ADDR)
   561  		addrPort := netip.AddrPortFrom(addr, c.PORT)
   562  		return addrPort.String()
   563  	}
   564  }
   565  
   566  func (c Address) SocksAddr() socks5.Addr {
   567  	addr := make([]byte, 1+len(c.ADDR)+2)
   568  	switch c.TYPE {
   569  	case AtypIPv4:
   570  		addr[0] = socks5.AtypIPv4
   571  	case AtypIPv6:
   572  		addr[0] = socks5.AtypIPv6
   573  	case AtypDomainName:
   574  		addr[0] = socks5.AtypDomainName
   575  	}
   576  	copy(addr[1:], c.ADDR)
   577  	binary.BigEndian.PutUint16(addr[len(addr)-2:], c.PORT)
   578  	return addr
   579  }
   580  
   581  func (c Address) UDPAddr() *net.UDPAddr {
   582  	return &net.UDPAddr{
   583  		IP:   c.ADDR,
   584  		Port: int(c.PORT),
   585  		Zone: "",
   586  	}
   587  }
   588  
   589  func (c Address) BytesLen() int {
   590  	return 1 + len(c.ADDR) + 2
   591  }
   592  
   593  const (
   594  	ProtocolError         = quic.ApplicationErrorCode(0xfffffff0)
   595  	AuthenticationFailed  = quic.ApplicationErrorCode(0xfffffff1)
   596  	AuthenticationTimeout = quic.ApplicationErrorCode(0xfffffff2)
   597  	BadCommand            = quic.ApplicationErrorCode(0xfffffff3)
   598  )