github.com/laof/lite-speed-test@v0.0.0-20230930011949-1f39b7037845/transport/ssr/obfs/tls1.2_ticket_auth.go (about) 1 package obfs 2 3 import ( 4 "bytes" 5 "crypto/hmac" 6 "encoding/binary" 7 "math/rand" 8 "net" 9 "strings" 10 "time" 11 12 "github.com/laof/lite-speed-test/common/pool" 13 "github.com/laof/lite-speed-test/transport/ssr/tools" 14 ) 15 16 func init() { 17 register("tls1.2_ticket_auth", newTLS12Ticket, 5) 18 register("tls1.2_ticket_fastauth", newTLS12Ticket, 5) 19 } 20 21 type tls12Ticket struct { 22 *Base 23 *authData 24 } 25 26 func newTLS12Ticket(b *Base) Obfs { 27 r := &tls12Ticket{Base: b, authData: &authData{}} 28 rand.Read(r.clientID[:]) 29 return r 30 } 31 32 type tls12TicketConn struct { 33 net.Conn 34 *tls12Ticket 35 handshakeStatus int 36 decoded bytes.Buffer 37 underDecoded bytes.Buffer 38 sendBuf bytes.Buffer 39 } 40 41 func (t *tls12Ticket) StreamConn(c net.Conn) net.Conn { 42 return &tls12TicketConn{Conn: c, tls12Ticket: t} 43 } 44 45 func (c *tls12TicketConn) Read(b []byte) (int, error) { 46 if c.decoded.Len() > 0 { 47 return c.decoded.Read(b) 48 } 49 50 buf := pool.Get(pool.RelayBufferSize) 51 defer pool.Put(buf) 52 n, err := c.Conn.Read(buf) 53 if err != nil { 54 return 0, err 55 } 56 57 if c.handshakeStatus == 8 { 58 c.underDecoded.Write(buf[:n]) 59 for c.underDecoded.Len() > 5 { 60 if !bytes.Equal(c.underDecoded.Bytes()[:3], []byte{0x17, 3, 3}) { 61 c.underDecoded.Reset() 62 return 0, errTLS12TicketAuthIncorrectMagicNumber 63 } 64 size := int(binary.BigEndian.Uint16(c.underDecoded.Bytes()[3:5])) 65 if c.underDecoded.Len() < 5+size { 66 break 67 } 68 c.underDecoded.Next(5) 69 c.decoded.Write(c.underDecoded.Next(size)) 70 } 71 n, _ = c.decoded.Read(b) 72 return n, nil 73 } 74 75 if n < 11+32+1+32 { 76 return 0, errTLS12TicketAuthTooShortData 77 } 78 79 if !hmac.Equal(buf[33:43], c.hmacSHA1(buf[11:33])[:10]) || !hmac.Equal(buf[n-10:n], c.hmacSHA1(buf[:n-10])[:10]) { 80 return 0, errTLS12TicketAuthHMACError 81 } 82 83 c.Write(nil) 84 return 0, nil 85 } 86 87 func (c *tls12TicketConn) Write(b []byte) (int, error) { 88 length := len(b) 89 if c.handshakeStatus == 8 { 90 buf := pool.GetBuffer() 91 defer pool.PutBuffer(buf) 92 for len(b) > 2048 { 93 size := rand.Intn(4096) + 100 94 if len(b) < size { 95 size = len(b) 96 } 97 packData(buf, b[:size]) 98 b = b[size:] 99 } 100 if len(b) > 0 { 101 packData(buf, b) 102 } 103 _, err := c.Conn.Write(buf.Bytes()) 104 if err != nil { 105 return 0, err 106 } 107 return length, nil 108 } 109 110 if len(b) > 0 { 111 packData(&c.sendBuf, b) 112 } 113 114 if c.handshakeStatus == 0 { 115 c.handshakeStatus = 1 116 117 data := pool.GetBuffer() 118 defer pool.PutBuffer(data) 119 120 data.Write([]byte{3, 3}) 121 c.packAuthData(data) 122 data.WriteByte(0x20) 123 data.Write(c.clientID[:]) 124 data.Write([]byte{0x00, 0x1c, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x9c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0x0a}) 125 data.Write([]byte{0x1, 0x0}) 126 127 ext := pool.GetBuffer() 128 defer pool.PutBuffer(ext) 129 130 host := c.getHost() 131 ext.Write([]byte{0xff, 0x01, 0x00, 0x01, 0x00}) 132 packSNIData(ext, host) 133 ext.Write([]byte{0, 0x17, 0, 0}) 134 c.packTicketBuf(ext, host) 135 ext.Write([]byte{0x00, 0x0d, 0x00, 0x16, 0x00, 0x14, 0x06, 0x01, 0x06, 0x03, 0x05, 0x01, 0x05, 0x03, 0x04, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x03, 0x02, 0x01, 0x02, 0x03}) 136 ext.Write([]byte{0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00}) 137 ext.Write([]byte{0x00, 0x12, 0x00, 0x00}) 138 ext.Write([]byte{0x75, 0x50, 0x00, 0x00}) 139 ext.Write([]byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00}) 140 ext.Write([]byte{0x00, 0x0a, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18}) 141 142 binary.Write(data, binary.BigEndian, uint16(ext.Len())) 143 data.ReadFrom(ext) 144 145 ret := pool.GetBuffer() 146 defer pool.PutBuffer(ret) 147 148 ret.Write([]byte{0x16, 3, 1}) 149 binary.Write(ret, binary.BigEndian, uint16(data.Len()+4)) 150 ret.Write([]byte{1, 0}) 151 binary.Write(ret, binary.BigEndian, uint16(data.Len())) 152 ret.ReadFrom(data) 153 154 _, err := c.Conn.Write(ret.Bytes()) 155 if err != nil { 156 return 0, err 157 } 158 return length, nil 159 } else if c.handshakeStatus == 1 && len(b) == 0 { 160 buf := pool.GetBuffer() 161 defer pool.PutBuffer(buf) 162 163 buf.Write([]byte{0x14, 3, 3, 0, 1, 1, 0x16, 3, 3, 0, 0x20}) 164 tools.AppendRandBytes(buf, 22) 165 buf.Write(c.hmacSHA1(buf.Bytes())[:10]) 166 buf.ReadFrom(&c.sendBuf) 167 168 c.handshakeStatus = 8 169 170 _, err := c.Conn.Write(buf.Bytes()) 171 return 0, err 172 } 173 return length, nil 174 } 175 176 func packData(buf *bytes.Buffer, data []byte) { 177 buf.Write([]byte{0x17, 3, 3}) 178 binary.Write(buf, binary.BigEndian, uint16(len(data))) 179 buf.Write(data) 180 } 181 182 func (t *tls12Ticket) packAuthData(buf *bytes.Buffer) { 183 binary.Write(buf, binary.BigEndian, uint32(time.Now().Unix())) 184 tools.AppendRandBytes(buf, 18) 185 buf.Write(t.hmacSHA1(buf.Bytes()[buf.Len()-22:])[:10]) 186 } 187 188 func packSNIData(buf *bytes.Buffer, u string) { 189 len := uint16(len(u)) 190 buf.Write([]byte{0, 0}) 191 binary.Write(buf, binary.BigEndian, len+5) 192 binary.Write(buf, binary.BigEndian, len+3) 193 buf.WriteByte(0) 194 binary.Write(buf, binary.BigEndian, len) 195 buf.WriteString(u) 196 } 197 198 func (c *tls12TicketConn) packTicketBuf(buf *bytes.Buffer, u string) { 199 length := 16 * (rand.Intn(17) + 8) 200 buf.Write([]byte{0, 0x23}) 201 binary.Write(buf, binary.BigEndian, uint16(length)) 202 tools.AppendRandBytes(buf, length) 203 } 204 205 func (t *tls12Ticket) hmacSHA1(data []byte) []byte { 206 key := pool.Get(len(t.Key) + 32) 207 defer pool.Put(key) 208 copy(key, t.Key) 209 copy(key[len(t.Key):], t.clientID[:]) 210 211 sha1Data := tools.HmacSHA1(key, data) 212 return sha1Data[:10] 213 } 214 215 func (t *tls12Ticket) getHost() string { 216 host := t.Param 217 if len(host) == 0 { 218 host = t.Host 219 } 220 if len(host) > 0 && host[len(host)-1] >= '0' && host[len(host)-1] <= '9' { 221 host = "" 222 } 223 hosts := strings.Split(host, ",") 224 host = hosts[rand.Intn(len(hosts))] 225 return host 226 }