github.com/yaling888/clash@v1.53.0/transport/simple-obfs/tls.go (about)

     1  package obfs
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"io"
     7  	"net"
     8  	"time"
     9  
    10  	"github.com/yaling888/clash/common/pool"
    11  )
    12  
    13  const (
    14  	chunkSize = 1 << 14 // 2 ** 14 == 16 * 1024
    15  )
    16  
    17  // TLSObfs is shadowsocks tls simple-obfs implementation
    18  type TLSObfs struct {
    19  	net.Conn
    20  	server        string
    21  	remain        int
    22  	firstRequest  bool
    23  	firstResponse bool
    24  }
    25  
    26  func (to *TLSObfs) read(b []byte, discardN int) (int, error) {
    27  	bufP := pool.GetBufferWriter()
    28  	bufP.Grow(discardN)
    29  	_, err := io.ReadFull(to.Conn, bufP.Bytes())
    30  	pool.PutBufferWriter(bufP)
    31  	if err != nil {
    32  		return 0, err
    33  	}
    34  
    35  	sizeBuf := make([]byte, 2)
    36  	_, err = io.ReadFull(to.Conn, sizeBuf)
    37  	if err != nil {
    38  		return 0, nil
    39  	}
    40  
    41  	length := int(binary.BigEndian.Uint16(sizeBuf))
    42  	if length > len(b) {
    43  		n, err := to.Conn.Read(b)
    44  		if err != nil {
    45  			return n, err
    46  		}
    47  		to.remain = length - n
    48  		return n, nil
    49  	}
    50  
    51  	return io.ReadFull(to.Conn, b[:length])
    52  }
    53  
    54  func (to *TLSObfs) Read(b []byte) (int, error) {
    55  	if to.remain > 0 {
    56  		length := to.remain
    57  		if length > len(b) {
    58  			length = len(b)
    59  		}
    60  
    61  		n, err := io.ReadFull(to.Conn, b[:length])
    62  		to.remain -= n
    63  		return n, err
    64  	}
    65  
    66  	if to.firstResponse {
    67  		// type + ver + lensize + 91 = 96
    68  		// type + ver + lensize + 1 = 6
    69  		// type + ver = 3
    70  		to.firstResponse = false
    71  		return to.read(b, 105)
    72  	}
    73  
    74  	// type + ver = 3
    75  	return to.read(b, 3)
    76  }
    77  
    78  func (to *TLSObfs) Write(b []byte) (int, error) {
    79  	length := len(b)
    80  	for i := 0; i < length; i += chunkSize {
    81  		end := i + chunkSize
    82  		if end > length {
    83  			end = length
    84  		}
    85  
    86  		n, err := to.write(b[i:end])
    87  		if err != nil {
    88  			return n, err
    89  		}
    90  	}
    91  	return length, nil
    92  }
    93  
    94  func (to *TLSObfs) write(b []byte) (int, error) {
    95  	if to.firstRequest {
    96  		helloMsg := makeClientHelloMsg(b, to.server)
    97  		_, err := to.Conn.Write(helloMsg)
    98  		to.firstRequest = false
    99  		return len(b), err
   100  	}
   101  
   102  	buf := pool.GetBufferWriter()
   103  	defer pool.PutBufferWriter(buf)
   104  	buf.PutSlice([]byte{0x17, 0x03, 0x03})
   105  	buf.PutUint16be(uint16(len(b)))
   106  	buf.PutSlice(b)
   107  	_, err := to.Conn.Write(buf.Bytes())
   108  	return len(b), err
   109  }
   110  
   111  // NewTLSObfs return a SimpleObfs
   112  func NewTLSObfs(conn net.Conn, server string) net.Conn {
   113  	return &TLSObfs{
   114  		Conn:          conn,
   115  		server:        server,
   116  		firstRequest:  true,
   117  		firstResponse: true,
   118  	}
   119  }
   120  
   121  func makeClientHelloMsg(data []byte, server string) []byte {
   122  	var (
   123  		dataLen   = uint16(len(data))
   124  		serverLen = uint16(len(server))
   125  		buf       = pool.BufferWriter{}
   126  	)
   127  
   128  	// handshake, TLS 1.0 version, length
   129  	buf.PutUint8(22)
   130  	buf.PutSlice([]byte{0x03, 0x01})
   131  	buf.PutUint16be(212 + dataLen + serverLen)
   132  
   133  	// clientHello, length, TLS 1.2 version
   134  	buf.PutUint8(1)
   135  	buf.PutUint8(0)
   136  	buf.PutUint16be(208 + dataLen + serverLen)
   137  	buf.PutSlice([]byte{0x03, 0x03})
   138  
   139  	// random with timestamp, sid len, sid
   140  	buf.PutUint32be(uint32(time.Now().Unix()))
   141  	_ = buf.ReadFull(rand.Reader, 28)
   142  	buf.PutUint8(32)
   143  	_ = buf.ReadFull(rand.Reader, 32)
   144  
   145  	// cipher suites
   146  	buf.PutSlice([]byte{0x00, 0x38})
   147  	buf.PutSlice([]byte{
   148  		0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x2b, 0xc0, 0x2f,
   149  		0x00, 0x9e, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x6b, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x67, 0xc0, 0x0a,
   150  		0xc0, 0x14, 0x00, 0x39, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x33, 0x00, 0x9d, 0x00, 0x9c, 0x00, 0x3d,
   151  		0x00, 0x3c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0xff,
   152  	})
   153  
   154  	// compression
   155  	buf.PutSlice([]byte{0x01, 0x00})
   156  
   157  	// extension length
   158  	buf.PutUint16be(79 + dataLen + serverLen)
   159  
   160  	// session ticket
   161  	buf.PutSlice([]byte{0x00, 0x23})
   162  	buf.PutUint16be(dataLen)
   163  	buf.PutSlice(data)
   164  
   165  	// server name
   166  	buf.PutSlice([]byte{0x00, 0x00})
   167  	buf.PutUint16be(serverLen + 5)
   168  	buf.PutUint16be(serverLen + 3)
   169  	buf.PutUint8(0)
   170  	buf.PutUint16be(serverLen)
   171  	buf.PutString(server)
   172  
   173  	// ec_point
   174  	buf.PutSlice([]byte{0x00, 0x0b, 0x00, 0x04, 0x03, 0x01, 0x00, 0x02})
   175  
   176  	// groups
   177  	buf.PutSlice([]byte{0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x19, 0x00, 0x18})
   178  
   179  	// signature
   180  	buf.PutSlice([]byte{
   181  		0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05,
   182  		0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01,
   183  		0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
   184  	})
   185  
   186  	// encrypt then mac
   187  	buf.PutSlice([]byte{0x00, 0x16, 0x00, 0x00})
   188  
   189  	// extended master secret
   190  	buf.PutSlice([]byte{0x00, 0x17, 0x00, 0x00})
   191  
   192  	return buf.Bytes()
   193  }