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