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 }