github.com/sagernet/sing-box@v1.9.0-rc.20/transport/simple-obfs/tls.go (about)

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