github.com/sagernet/sing-box@v1.2.7/common/tls/reality_client.go (about) 1 //go:build with_utls 2 3 package tls 4 5 import ( 6 "bytes" 7 "context" 8 "crypto/aes" 9 "crypto/cipher" 10 "crypto/ed25519" 11 "crypto/hmac" 12 "crypto/sha256" 13 "crypto/sha512" 14 "crypto/tls" 15 "crypto/x509" 16 "encoding/base64" 17 "encoding/binary" 18 "encoding/hex" 19 "fmt" 20 "io" 21 mRand "math/rand" 22 "net" 23 "net/http" 24 "reflect" 25 "strings" 26 "time" 27 "unsafe" 28 29 "github.com/sagernet/sing-box/adapter" 30 "github.com/sagernet/sing-box/option" 31 "github.com/sagernet/sing/common/debug" 32 E "github.com/sagernet/sing/common/exceptions" 33 aTLS "github.com/sagernet/sing/common/tls" 34 utls "github.com/sagernet/utls" 35 36 "golang.org/x/crypto/hkdf" 37 "golang.org/x/net/http2" 38 ) 39 40 var _ ConfigCompat = (*RealityClientConfig)(nil) 41 42 type RealityClientConfig struct { 43 uClient *UTLSClientConfig 44 publicKey []byte 45 shortID [8]byte 46 } 47 48 func NewRealityClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (*RealityClientConfig, error) { 49 if options.UTLS == nil || !options.UTLS.Enabled { 50 return nil, E.New("uTLS is required by reality client") 51 } 52 53 uClient, err := NewUTLSClient(router, serverAddress, options) 54 if err != nil { 55 return nil, err 56 } 57 58 publicKey, err := base64.RawURLEncoding.DecodeString(options.Reality.PublicKey) 59 if err != nil { 60 return nil, E.Cause(err, "decode public_key") 61 } 62 if len(publicKey) != 32 { 63 return nil, E.New("invalid public_key") 64 } 65 var shortID [8]byte 66 decodedLen, err := hex.Decode(shortID[:], []byte(options.Reality.ShortID)) 67 if err != nil { 68 return nil, E.Cause(err, "decode short_id") 69 } 70 if decodedLen > 8 { 71 return nil, E.New("invalid short_id") 72 } 73 return &RealityClientConfig{uClient, publicKey, shortID}, nil 74 } 75 76 func (e *RealityClientConfig) ServerName() string { 77 return e.uClient.ServerName() 78 } 79 80 func (e *RealityClientConfig) SetServerName(serverName string) { 81 e.uClient.SetServerName(serverName) 82 } 83 84 func (e *RealityClientConfig) NextProtos() []string { 85 return e.uClient.NextProtos() 86 } 87 88 func (e *RealityClientConfig) SetNextProtos(nextProto []string) { 89 e.uClient.SetNextProtos(nextProto) 90 } 91 92 func (e *RealityClientConfig) Config() (*STDConfig, error) { 93 return nil, E.New("unsupported usage for reality") 94 } 95 96 func (e *RealityClientConfig) Client(conn net.Conn) (Conn, error) { 97 return ClientHandshake(context.Background(), conn, e) 98 } 99 100 func (e *RealityClientConfig) ClientHandshake(ctx context.Context, conn net.Conn) (aTLS.Conn, error) { 101 verifier := &realityVerifier{ 102 serverName: e.uClient.ServerName(), 103 } 104 uConfig := e.uClient.config.Clone() 105 uConfig.InsecureSkipVerify = true 106 uConfig.SessionTicketsDisabled = true 107 uConfig.VerifyPeerCertificate = verifier.VerifyPeerCertificate 108 uConn := utls.UClient(conn, uConfig, e.uClient.id) 109 verifier.UConn = uConn 110 err := uConn.BuildHandshakeState() 111 if err != nil { 112 return nil, err 113 } 114 115 if len(uConfig.NextProtos) > 0 { 116 for _, extension := range uConn.Extensions { 117 if alpnExtension, isALPN := extension.(*utls.ALPNExtension); isALPN { 118 alpnExtension.AlpnProtocols = uConfig.NextProtos 119 break 120 } 121 } 122 } 123 124 hello := uConn.HandshakeState.Hello 125 hello.SessionId = make([]byte, 32) 126 copy(hello.Raw[39:], hello.SessionId) 127 128 var nowTime time.Time 129 if uConfig.Time != nil { 130 nowTime = uConfig.Time() 131 } else { 132 nowTime = time.Now() 133 } 134 binary.BigEndian.PutUint64(hello.SessionId, uint64(nowTime.Unix())) 135 136 hello.SessionId[0] = 1 137 hello.SessionId[1] = 8 138 hello.SessionId[2] = 0 139 binary.BigEndian.PutUint32(hello.SessionId[4:], uint32(time.Now().Unix())) 140 copy(hello.SessionId[8:], e.shortID[:]) 141 142 if debug.Enabled { 143 fmt.Printf("REALITY hello.sessionId[:16]: %v\n", hello.SessionId[:16]) 144 } 145 146 authKey := uConn.HandshakeState.State13.EcdheParams.SharedKey(e.publicKey) 147 if authKey == nil { 148 return nil, E.New("nil auth_key") 149 } 150 verifier.authKey = authKey 151 _, err = hkdf.New(sha256.New, authKey, hello.Random[:20], []byte("REALITY")).Read(authKey) 152 if err != nil { 153 return nil, err 154 } 155 aesBlock, _ := aes.NewCipher(authKey) 156 aesGcmCipher, _ := cipher.NewGCM(aesBlock) 157 aesGcmCipher.Seal(hello.SessionId[:0], hello.Random[20:], hello.SessionId[:16], hello.Raw) 158 copy(hello.Raw[39:], hello.SessionId) 159 if debug.Enabled { 160 fmt.Printf("REALITY hello.sessionId: %v\n", hello.SessionId) 161 fmt.Printf("REALITY uConn.AuthKey: %v\n", authKey) 162 } 163 164 err = uConn.HandshakeContext(ctx) 165 if err != nil { 166 return nil, err 167 } 168 169 if debug.Enabled { 170 fmt.Printf("REALITY Conn.Verified: %v\n", verifier.verified) 171 } 172 173 if !verifier.verified { 174 go realityClientFallback(uConn, e.uClient.ServerName(), e.uClient.id) 175 return nil, E.New("reality verification failed") 176 } 177 178 return &utlsConnWrapper{uConn}, nil 179 } 180 181 func realityClientFallback(uConn net.Conn, serverName string, fingerprint utls.ClientHelloID) { 182 defer uConn.Close() 183 client := &http.Client{ 184 Transport: &http2.Transport{ 185 DialTLSContext: func(ctx context.Context, network, addr string, config *tls.Config) (net.Conn, error) { 186 return uConn, nil 187 }, 188 }, 189 } 190 request, _ := http.NewRequest("GET", "https://"+serverName, nil) 191 request.Header.Set("User-Agent", fingerprint.Client) 192 request.AddCookie(&http.Cookie{Name: "padding", Value: strings.Repeat("0", mRand.Intn(32)+30)}) 193 response, err := client.Do(request) 194 if err != nil { 195 return 196 } 197 _, _ = io.Copy(io.Discard, response.Body) 198 response.Body.Close() 199 } 200 201 func (e *RealityClientConfig) SetSessionIDGenerator(generator func(clientHello []byte, sessionID []byte) error) { 202 e.uClient.config.SessionIDGenerator = generator 203 } 204 205 func (e *RealityClientConfig) Clone() Config { 206 return &RealityClientConfig{ 207 e.uClient.Clone().(*UTLSClientConfig), 208 e.publicKey, 209 e.shortID, 210 } 211 } 212 213 type realityVerifier struct { 214 *utls.UConn 215 serverName string 216 authKey []byte 217 verified bool 218 } 219 220 func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { 221 p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates") 222 certs := *(*([]*x509.Certificate))(unsafe.Pointer(uintptr(unsafe.Pointer(c.Conn)) + p.Offset)) 223 if pub, ok := certs[0].PublicKey.(ed25519.PublicKey); ok { 224 h := hmac.New(sha512.New, c.authKey) 225 h.Write(pub) 226 if bytes.Equal(h.Sum(nil), certs[0].Signature) { 227 c.verified = true 228 return nil 229 } 230 } 231 opts := x509.VerifyOptions{ 232 DNSName: c.serverName, 233 Intermediates: x509.NewCertPool(), 234 } 235 for _, cert := range certs[1:] { 236 opts.Intermediates.AddCert(cert) 237 } 238 if _, err := certs[0].Verify(opts); err != nil { 239 return err 240 } 241 return nil 242 }