github.com/kelleygo/clashcore@v1.0.2/transport/tuic/v5/protocol.go (about)

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