github.com/metacubex/mihomo@v1.18.5/transport/simple-obfs/tls.go (about)

     1  package obfs
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"io"
     7  	"net"
     8  	"time"
     9  
    10  	"github.com/metacubex/mihomo/common/pool"
    11  
    12  	"github.com/zhangyunhao116/fastrand"
    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.GetBuffer()
   104  	defer pool.PutBuffer(buf)
   105  	buf.Write([]byte{0x17, 0x03, 0x03})
   106  	binary.Write(buf, binary.BigEndian, uint16(len(b)))
   107  	buf.Write(b)
   108  	_, err := to.Conn.Write(buf.Bytes())
   109  	if err != nil {
   110  		// return 0 because errors occur here make the
   111  		// whole situation irrecoverable
   112  		return 0, err
   113  	}
   114  	return len(b), nil
   115  }
   116  
   117  // NewTLSObfs return a SimpleObfs
   118  func NewTLSObfs(conn net.Conn, server string) net.Conn {
   119  	return &TLSObfs{
   120  		Conn:          conn,
   121  		server:        server,
   122  		firstRequest:  true,
   123  		firstResponse: true,
   124  	}
   125  }
   126  
   127  func makeClientHelloMsg(data []byte, server string) []byte {
   128  	random := make([]byte, 28)
   129  	sessionID := make([]byte, 32)
   130  	fastrand.Read(random)
   131  	fastrand.Read(sessionID)
   132  
   133  	buf := &bytes.Buffer{}
   134  
   135  	// handshake, TLS 1.0 version, length
   136  	buf.WriteByte(22)
   137  	buf.Write([]byte{0x03, 0x01})
   138  	length := uint16(212 + len(data) + len(server))
   139  	buf.WriteByte(byte(length >> 8))
   140  	buf.WriteByte(byte(length & 0xff))
   141  
   142  	// clientHello, length, TLS 1.2 version
   143  	buf.WriteByte(1)
   144  	buf.WriteByte(0)
   145  	binary.Write(buf, binary.BigEndian, uint16(208+len(data)+len(server)))
   146  	buf.Write([]byte{0x03, 0x03})
   147  
   148  	// random with timestamp, sid len, sid
   149  	binary.Write(buf, binary.BigEndian, uint32(time.Now().Unix()))
   150  	buf.Write(random)
   151  	buf.WriteByte(32)
   152  	buf.Write(sessionID)
   153  
   154  	// cipher suites
   155  	buf.Write([]byte{0x00, 0x38})
   156  	buf.Write([]byte{
   157  		0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x2b, 0xc0, 0x2f,
   158  		0x00, 0x9e, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x6b, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x67, 0xc0, 0x0a,
   159  		0xc0, 0x14, 0x00, 0x39, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x33, 0x00, 0x9d, 0x00, 0x9c, 0x00, 0x3d,
   160  		0x00, 0x3c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0xff,
   161  	})
   162  
   163  	// compression
   164  	buf.Write([]byte{0x01, 0x00})
   165  
   166  	// extension length
   167  	binary.Write(buf, binary.BigEndian, uint16(79+len(data)+len(server)))
   168  
   169  	// session ticket
   170  	buf.Write([]byte{0x00, 0x23})
   171  	binary.Write(buf, binary.BigEndian, uint16(len(data)))
   172  	buf.Write(data)
   173  
   174  	// server name
   175  	buf.Write([]byte{0x00, 0x00})
   176  	binary.Write(buf, binary.BigEndian, uint16(len(server)+5))
   177  	binary.Write(buf, binary.BigEndian, uint16(len(server)+3))
   178  	buf.WriteByte(0)
   179  	binary.Write(buf, binary.BigEndian, uint16(len(server)))
   180  	buf.Write([]byte(server))
   181  
   182  	// ec_point
   183  	buf.Write([]byte{0x00, 0x0b, 0x00, 0x04, 0x03, 0x01, 0x00, 0x02})
   184  
   185  	// groups
   186  	buf.Write([]byte{0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x19, 0x00, 0x18})
   187  
   188  	// signature
   189  	buf.Write([]byte{
   190  		0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05,
   191  		0x01, 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01,
   192  		0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
   193  	})
   194  
   195  	// encrypt then mac
   196  	buf.Write([]byte{0x00, 0x16, 0x00, 0x00})
   197  
   198  	// extended master secret
   199  	buf.Write([]byte{0x00, 0x17, 0x00, 0x00})
   200  
   201  	return buf.Bytes()
   202  }