github.com/yaling888/clash@v1.53.0/transport/ssr/protocol/auth_aes128_sha1.go (about)

     1  package protocol
     2  
     3  import (
     4  	"bytes"
     5  	R "crypto/rand"
     6  	"encoding/binary"
     7  	"math"
     8  	"math/rand/v2"
     9  	"net"
    10  	"strconv"
    11  	"strings"
    12  
    13  	"github.com/phuslu/log"
    14  
    15  	"github.com/yaling888/clash/common/pool"
    16  	"github.com/yaling888/clash/transport/ssr/tools"
    17  )
    18  
    19  type (
    20  	hmacMethod       func(key, data []byte) []byte
    21  	hashDigestMethod func([]byte) []byte
    22  )
    23  
    24  func init() {
    25  	register("auth_aes128_sha1", newAuthAES128SHA1, 9)
    26  }
    27  
    28  type authAES128Function struct {
    29  	salt       string
    30  	hmac       hmacMethod
    31  	hashDigest hashDigestMethod
    32  }
    33  
    34  type authAES128 struct {
    35  	*Base
    36  	*authData
    37  	*authAES128Function
    38  	*userData
    39  	iv            []byte
    40  	hasSentHeader bool
    41  	rawTrans      bool
    42  	packID        uint32
    43  	recvID        uint32
    44  }
    45  
    46  func newAuthAES128SHA1(b *Base) Protocol {
    47  	a := &authAES128{
    48  		Base:               b,
    49  		authData:           &authData{},
    50  		authAES128Function: &authAES128Function{salt: "auth_aes128_sha1", hmac: tools.HmacSHA1, hashDigest: tools.SHA1Sum},
    51  		userData:           &userData{},
    52  	}
    53  	a.initUserData()
    54  	return a
    55  }
    56  
    57  func (a *authAES128) initUserData() {
    58  	params := strings.Split(a.Param, ":")
    59  	if len(params) > 1 {
    60  		if userID, err := strconv.ParseUint(params[0], 10, 32); err == nil {
    61  			binary.LittleEndian.PutUint32(a.userID[:], uint32(userID))
    62  			a.userKey = a.hashDigest([]byte(params[1]))
    63  		} else {
    64  			log.Warn().Msgf("[SSR] wrong protocol-param for %s, only digits are expected before ':'", a.salt)
    65  		}
    66  	}
    67  	if len(a.userKey) == 0 {
    68  		a.userKey = a.Key
    69  		_, _ = R.Read(a.userID[:])
    70  	}
    71  }
    72  
    73  func (a *authAES128) StreamConn(c net.Conn, iv []byte) net.Conn {
    74  	p := &authAES128{
    75  		Base:               a.Base,
    76  		authData:           a.next(),
    77  		authAES128Function: a.authAES128Function,
    78  		userData:           a.userData,
    79  		packID:             1,
    80  		recvID:             1,
    81  	}
    82  	p.iv = iv
    83  	return &Conn{Conn: c, Protocol: p}
    84  }
    85  
    86  func (a *authAES128) PacketConn(c net.PacketConn) net.PacketConn {
    87  	p := &authAES128{
    88  		Base:               a.Base,
    89  		authAES128Function: a.authAES128Function,
    90  		userData:           a.userData,
    91  	}
    92  	return &PacketConn{PacketConn: c, Protocol: p}
    93  }
    94  
    95  func (a *authAES128) Decode(dst, src *bytes.Buffer) error {
    96  	if a.rawTrans {
    97  		_, _ = dst.ReadFrom(src)
    98  		return nil
    99  	}
   100  	for src.Len() > 4 {
   101  		macKey := pool.GetBufferWriter()
   102  		macKey.Grow(len(a.userKey) + 4)
   103  		copy(*macKey, a.userKey)
   104  		binary.LittleEndian.PutUint32((*macKey)[len(a.userKey):], a.recvID)
   105  		if !bytes.Equal(a.hmac(macKey.Bytes(), src.Bytes()[:2])[:2], src.Bytes()[2:4]) {
   106  			src.Reset()
   107  			pool.PutBufferWriter(macKey)
   108  			return errAuthAES128MACError
   109  		}
   110  
   111  		length := int(binary.LittleEndian.Uint16(src.Bytes()[:2]))
   112  		if length >= 8192 || length < 7 {
   113  			a.rawTrans = true
   114  			src.Reset()
   115  			pool.PutBufferWriter(macKey)
   116  			return errAuthAES128LengthError
   117  		}
   118  		if length > src.Len() {
   119  			pool.PutBufferWriter(macKey)
   120  			break
   121  		}
   122  
   123  		ok := bytes.Equal(a.hmac(macKey.Bytes(), src.Bytes()[:length-4])[:4], src.Bytes()[length-4:length])
   124  		pool.PutBufferWriter(macKey)
   125  		if !ok {
   126  			a.rawTrans = true
   127  			src.Reset()
   128  			return errAuthAES128ChksumError
   129  		}
   130  
   131  		a.recvID++
   132  
   133  		pos := int(src.Bytes()[4])
   134  		if pos < 255 {
   135  			pos += 4
   136  		} else {
   137  			pos = int(binary.LittleEndian.Uint16(src.Bytes()[5:7])) + 4
   138  		}
   139  		dst.Write(src.Bytes()[pos : length-4])
   140  		src.Next(length)
   141  	}
   142  	return nil
   143  }
   144  
   145  func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error {
   146  	fullDataLength := len(b)
   147  	if !a.hasSentHeader {
   148  		dataLength := getDataLength(b)
   149  		a.packAuthData(buf, b[:dataLength])
   150  		b = b[dataLength:]
   151  		a.hasSentHeader = true
   152  	}
   153  	for len(b) > 8100 {
   154  		a.packData(buf, b[:8100], fullDataLength)
   155  		b = b[8100:]
   156  	}
   157  	if len(b) > 0 {
   158  		a.packData(buf, b, fullDataLength)
   159  	}
   160  	return nil
   161  }
   162  
   163  func (a *authAES128) DecodePacket(b []byte) ([]byte, error) {
   164  	if len(b) < 4 {
   165  		return nil, errAuthAES128LengthError
   166  	}
   167  	if !bytes.Equal(a.hmac(a.Key, b[:len(b)-4])[:4], b[len(b)-4:]) {
   168  		return nil, errAuthAES128ChksumError
   169  	}
   170  	return b[:len(b)-4], nil
   171  }
   172  
   173  func (a *authAES128) EncodePacket(buf *bytes.Buffer, b []byte) error {
   174  	buf.Write(b)
   175  	buf.Write(a.userID[:])
   176  	buf.Write(a.hmac(a.userKey, buf.Bytes())[:4])
   177  	return nil
   178  }
   179  
   180  func (a *authAES128) packData(poolBuf *bytes.Buffer, data []byte, fullDataLength int) {
   181  	dataLength := len(data)
   182  	randDataLength := a.getRandDataLengthForPackData(dataLength, fullDataLength)
   183  	/*
   184  		2:	uint16 LittleEndian packedDataLength
   185  		2:	hmac of packedDataLength
   186  		3:	maxRandDataLengthPrefix (min:1)
   187  		4:	hmac of packedData except the last 4 bytes
   188  	*/
   189  	packedDataLength := 2 + 2 + 3 + randDataLength + dataLength + 4
   190  	if randDataLength < 128 {
   191  		packedDataLength -= 2
   192  	}
   193  
   194  	macKey := pool.GetBufferWriter()
   195  	macKey.Grow(len(a.userKey) + 4)
   196  	defer pool.PutBufferWriter(macKey)
   197  	copy(*macKey, a.userKey)
   198  	binary.LittleEndian.PutUint32((*macKey)[len(a.userKey):], a.packID)
   199  	a.packID++
   200  
   201  	_ = binary.Write(poolBuf, binary.LittleEndian, uint16(packedDataLength))
   202  	poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes()[poolBuf.Len()-2:])[:2])
   203  	a.packRandData(poolBuf, randDataLength)
   204  	poolBuf.Write(data)
   205  	poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes()[poolBuf.Len()-packedDataLength+4:])[:4])
   206  }
   207  
   208  func trapezoidRandom(maxVal int, d float64) int {
   209  	base := rand.Float64()
   210  	if d-0 > 1e-6 {
   211  		a := 1 - d
   212  		base = (math.Sqrt(a*a+4*d*base) - a) / (2 * d)
   213  	}
   214  	return int(base * float64(maxVal))
   215  }
   216  
   217  func (a *authAES128) getRandDataLengthForPackData(dataLength, fullDataLength int) int {
   218  	if fullDataLength >= 32*1024-a.Overhead {
   219  		return 0
   220  	}
   221  	// 1460: tcp_mss
   222  	revLength := 1460 - dataLength - 9
   223  	if revLength == 0 {
   224  		return 0
   225  	}
   226  	if revLength < 0 {
   227  		if revLength > -1460 {
   228  			return trapezoidRandom(revLength+1460, -0.3)
   229  		}
   230  		return rand.IntN(32)
   231  	}
   232  	if dataLength > 900 {
   233  		return rand.IntN(revLength)
   234  	}
   235  	return trapezoidRandom(revLength, -0.3)
   236  }
   237  
   238  func (a *authAES128) packAuthData(poolBuf *bytes.Buffer, data []byte) {
   239  	if len(data) == 0 {
   240  		return
   241  	}
   242  	dataLength := len(data)
   243  	randDataLength := a.getRandDataLengthForPackAuthData(dataLength)
   244  	/*
   245  		7:	checkHead(1) and hmac of checkHead(6)
   246  		4:	userID
   247  		16:	encrypted data of authdata(12), uint16 BigEndian packedDataLength(2) and uint16 BigEndian randDataLength(2)
   248  		4:	hmac of userID and encrypted data
   249  		4:	hmac of packedAuthData except the last 4 bytes
   250  	*/
   251  	packedAuthDataLength := 7 + 4 + 16 + 4 + randDataLength + dataLength + 4
   252  
   253  	macKey := pool.GetBufferWriter()
   254  	defer pool.PutBufferWriter(macKey)
   255  	macKey.PutSlice(a.iv)
   256  	macKey.PutSlice(a.Key)
   257  
   258  	poolBuf.WriteByte(byte(rand.IntN(256)))
   259  	poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes())[:6])
   260  	poolBuf.Write(a.userID[:])
   261  	err := a.authData.putEncryptedData(poolBuf, a.userKey, [2]int{packedAuthDataLength, randDataLength}, a.salt)
   262  	if err != nil {
   263  		poolBuf.Reset()
   264  		return
   265  	}
   266  	poolBuf.Write(a.hmac(macKey.Bytes(), poolBuf.Bytes()[7:])[:4])
   267  	tools.AppendRandBytes(poolBuf, randDataLength)
   268  	poolBuf.Write(data)
   269  	poolBuf.Write(a.hmac(a.userKey, poolBuf.Bytes())[:4])
   270  }
   271  
   272  func (a *authAES128) getRandDataLengthForPackAuthData(size int) int {
   273  	if size > 400 {
   274  		return rand.IntN(512)
   275  	}
   276  	return rand.IntN(1024)
   277  }
   278  
   279  func (a *authAES128) packRandData(poolBuf *bytes.Buffer, size int) {
   280  	if size < 128 {
   281  		poolBuf.WriteByte(byte(size + 1))
   282  		tools.AppendRandBytes(poolBuf, size)
   283  		return
   284  	}
   285  	poolBuf.WriteByte(255)
   286  	_ = binary.Write(poolBuf, binary.LittleEndian, uint16(size+3))
   287  	tools.AppendRandBytes(poolBuf, size)
   288  }