github.com/kelleygo/clashcore@v1.0.2/transport/ssr/obfs/tls1.2_ticket_auth.go (about)

     1  package obfs
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/hmac"
     6  	"encoding/binary"
     7  	"net"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/kelleygo/clashcore/common/pool"
    12  	"github.com/kelleygo/clashcore/transport/ssr/tools"
    13  
    14  	"github.com/zhangyunhao116/fastrand"
    15  )
    16  
    17  func init() {
    18  	register("tls1.2_ticket_auth", newTLS12Ticket, 5)
    19  	register("tls1.2_ticket_fastauth", newTLS12Ticket, 5)
    20  }
    21  
    22  type tls12Ticket struct {
    23  	*Base
    24  	*authData
    25  }
    26  
    27  func newTLS12Ticket(b *Base) Obfs {
    28  	r := &tls12Ticket{Base: b, authData: &authData{}}
    29  	fastrand.Read(r.clientID[:])
    30  	return r
    31  }
    32  
    33  type tls12TicketConn struct {
    34  	net.Conn
    35  	*tls12Ticket
    36  	handshakeStatus int
    37  	decoded         bytes.Buffer
    38  	underDecoded    bytes.Buffer
    39  	sendBuf         bytes.Buffer
    40  }
    41  
    42  func (t *tls12Ticket) StreamConn(c net.Conn) net.Conn {
    43  	return &tls12TicketConn{Conn: c, tls12Ticket: t}
    44  }
    45  
    46  func (c *tls12TicketConn) Read(b []byte) (int, error) {
    47  	if c.decoded.Len() > 0 {
    48  		return c.decoded.Read(b)
    49  	}
    50  
    51  	buf := pool.Get(pool.RelayBufferSize)
    52  	defer pool.Put(buf)
    53  	n, err := c.Conn.Read(buf)
    54  	if err != nil {
    55  		return 0, err
    56  	}
    57  
    58  	if c.handshakeStatus == 8 {
    59  		c.underDecoded.Write(buf[:n])
    60  		for c.underDecoded.Len() > 5 {
    61  			if !bytes.Equal(c.underDecoded.Bytes()[:3], []byte{0x17, 3, 3}) {
    62  				c.underDecoded.Reset()
    63  				return 0, errTLS12TicketAuthIncorrectMagicNumber
    64  			}
    65  			size := int(binary.BigEndian.Uint16(c.underDecoded.Bytes()[3:5]))
    66  			if c.underDecoded.Len() < 5+size {
    67  				break
    68  			}
    69  			c.underDecoded.Next(5)
    70  			c.decoded.Write(c.underDecoded.Next(size))
    71  		}
    72  		n, _ = c.decoded.Read(b)
    73  		return n, nil
    74  	}
    75  
    76  	if n < 11+32+1+32 {
    77  		return 0, errTLS12TicketAuthTooShortData
    78  	}
    79  
    80  	if !hmac.Equal(buf[33:43], c.hmacSHA1(buf[11:33])[:10]) || !hmac.Equal(buf[n-10:n], c.hmacSHA1(buf[:n-10])[:10]) {
    81  		return 0, errTLS12TicketAuthHMACError
    82  	}
    83  
    84  	c.Write(nil)
    85  	return 0, nil
    86  }
    87  
    88  func (c *tls12TicketConn) Write(b []byte) (int, error) {
    89  	length := len(b)
    90  	if c.handshakeStatus == 8 {
    91  		buf := pool.GetBuffer()
    92  		defer pool.PutBuffer(buf)
    93  		for len(b) > 2048 {
    94  			size := fastrand.Intn(4096) + 100
    95  			if len(b) < size {
    96  				size = len(b)
    97  			}
    98  			packData(buf, b[:size])
    99  			b = b[size:]
   100  		}
   101  		if len(b) > 0 {
   102  			packData(buf, b)
   103  		}
   104  		_, err := c.Conn.Write(buf.Bytes())
   105  		if err != nil {
   106  			return 0, err
   107  		}
   108  		return length, nil
   109  	}
   110  
   111  	if len(b) > 0 {
   112  		packData(&c.sendBuf, b)
   113  	}
   114  
   115  	if c.handshakeStatus == 0 {
   116  		c.handshakeStatus = 1
   117  
   118  		data := pool.GetBuffer()
   119  		defer pool.PutBuffer(data)
   120  
   121  		data.Write([]byte{3, 3})
   122  		c.packAuthData(data)
   123  		data.WriteByte(0x20)
   124  		data.Write(c.clientID[:])
   125  		data.Write([]byte{0x00, 0x1c, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x9c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0x0a})
   126  		data.Write([]byte{0x1, 0x0})
   127  
   128  		ext := pool.GetBuffer()
   129  		defer pool.PutBuffer(ext)
   130  
   131  		host := c.getHost()
   132  		ext.Write([]byte{0xff, 0x01, 0x00, 0x01, 0x00})
   133  		packSNIData(ext, host)
   134  		ext.Write([]byte{0, 0x17, 0, 0})
   135  		c.packTicketBuf(ext, host)
   136  		ext.Write([]byte{0x00, 0x0d, 0x00, 0x16, 0x00, 0x14, 0x06, 0x01, 0x06, 0x03, 0x05, 0x01, 0x05, 0x03, 0x04, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x03, 0x02, 0x01, 0x02, 0x03})
   137  		ext.Write([]byte{0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00})
   138  		ext.Write([]byte{0x00, 0x12, 0x00, 0x00})
   139  		ext.Write([]byte{0x75, 0x50, 0x00, 0x00})
   140  		ext.Write([]byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00})
   141  		ext.Write([]byte{0x00, 0x0a, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18})
   142  
   143  		binary.Write(data, binary.BigEndian, uint16(ext.Len()))
   144  		data.ReadFrom(ext)
   145  
   146  		ret := pool.GetBuffer()
   147  		defer pool.PutBuffer(ret)
   148  
   149  		ret.Write([]byte{0x16, 3, 1})
   150  		binary.Write(ret, binary.BigEndian, uint16(data.Len()+4))
   151  		ret.Write([]byte{1, 0})
   152  		binary.Write(ret, binary.BigEndian, uint16(data.Len()))
   153  		ret.ReadFrom(data)
   154  
   155  		_, err := c.Conn.Write(ret.Bytes())
   156  		if err != nil {
   157  			return 0, err
   158  		}
   159  		return length, nil
   160  	} else if c.handshakeStatus == 1 && len(b) == 0 {
   161  		buf := pool.GetBuffer()
   162  		defer pool.PutBuffer(buf)
   163  
   164  		buf.Write([]byte{0x14, 3, 3, 0, 1, 1, 0x16, 3, 3, 0, 0x20})
   165  		tools.AppendRandBytes(buf, 22)
   166  		buf.Write(c.hmacSHA1(buf.Bytes())[:10])
   167  		buf.ReadFrom(&c.sendBuf)
   168  
   169  		c.handshakeStatus = 8
   170  
   171  		_, err := c.Conn.Write(buf.Bytes())
   172  		return 0, err
   173  	}
   174  	return length, nil
   175  }
   176  
   177  func packData(buf *bytes.Buffer, data []byte) {
   178  	buf.Write([]byte{0x17, 3, 3})
   179  	binary.Write(buf, binary.BigEndian, uint16(len(data)))
   180  	buf.Write(data)
   181  }
   182  
   183  func (t *tls12Ticket) packAuthData(buf *bytes.Buffer) {
   184  	binary.Write(buf, binary.BigEndian, uint32(time.Now().Unix()))
   185  	tools.AppendRandBytes(buf, 18)
   186  	buf.Write(t.hmacSHA1(buf.Bytes()[buf.Len()-22:])[:10])
   187  }
   188  
   189  func packSNIData(buf *bytes.Buffer, u string) {
   190  	len := uint16(len(u))
   191  	buf.Write([]byte{0, 0})
   192  	binary.Write(buf, binary.BigEndian, len+5)
   193  	binary.Write(buf, binary.BigEndian, len+3)
   194  	buf.WriteByte(0)
   195  	binary.Write(buf, binary.BigEndian, len)
   196  	buf.WriteString(u)
   197  }
   198  
   199  func (c *tls12TicketConn) packTicketBuf(buf *bytes.Buffer, u string) {
   200  	length := 16 * (fastrand.Intn(17) + 8)
   201  	buf.Write([]byte{0, 0x23})
   202  	binary.Write(buf, binary.BigEndian, uint16(length))
   203  	tools.AppendRandBytes(buf, length)
   204  }
   205  
   206  func (t *tls12Ticket) hmacSHA1(data []byte) []byte {
   207  	key := pool.Get(len(t.Key) + 32)
   208  	defer pool.Put(key)
   209  	copy(key, t.Key)
   210  	copy(key[len(t.Key):], t.clientID[:])
   211  
   212  	sha1Data := tools.HmacSHA1(key, data)
   213  	return sha1Data[:10]
   214  }
   215  
   216  func (t *tls12Ticket) getHost() string {
   217  	host := t.Param
   218  	if len(host) == 0 {
   219  		host = t.Host
   220  	}
   221  	if len(host) > 0 && host[len(host)-1] >= '0' && host[len(host)-1] <= '9' {
   222  		host = ""
   223  	}
   224  	hosts := strings.Split(host, ",")
   225  	host = hosts[fastrand.Intn(len(hosts))]
   226  	return host
   227  }