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 }