mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-26 02:21:28 +00:00
Add reality client fallback
This commit is contained in:
parent
d0e9443031
commit
3b4e811907
|
@ -4,19 +4,25 @@ package tls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
mRand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -24,12 +30,14 @@ import (
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing/common/debug"
|
"github.com/sagernet/sing/common/debug"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
aTLS "github.com/sagernet/sing/common/tls"
|
||||||
utls "github.com/sagernet/utls"
|
utls "github.com/sagernet/utls"
|
||||||
|
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Config = (*RealityClientConfig)(nil)
|
var _ ConfigCompat = (*RealityClientConfig)(nil)
|
||||||
|
|
||||||
type RealityClientConfig struct {
|
type RealityClientConfig struct {
|
||||||
uClient *UTLSClientConfig
|
uClient *UTLSClientConfig
|
||||||
|
@ -85,6 +93,10 @@ func (e *RealityClientConfig) Config() (*STDConfig, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *RealityClientConfig) Client(conn net.Conn) (Conn, error) {
|
func (e *RealityClientConfig) Client(conn net.Conn) (Conn, error) {
|
||||||
|
return ClientHandshake(context.Background(), conn, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *RealityClientConfig) ClientHandshake(ctx context.Context, conn net.Conn) (aTLS.Conn, error) {
|
||||||
verifier := &realityVerifier{
|
verifier := &realityVerifier{
|
||||||
serverName: e.uClient.ServerName(),
|
serverName: e.uClient.ServerName(),
|
||||||
}
|
}
|
||||||
|
@ -137,9 +149,43 @@ func (e *RealityClientConfig) Client(conn net.Conn) (Conn, error) {
|
||||||
fmt.Printf("REALITY uConn.AuthKey: %v\n", authKey)
|
fmt.Printf("REALITY uConn.AuthKey: %v\n", authKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = uConn.HandshakeContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug.Enabled {
|
||||||
|
fmt.Printf("REALITY Conn.Verified: %v\n", verifier.verified)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !verifier.verified {
|
||||||
|
go realityClientFallback(uConn, e.uClient.ServerName(), e.uClient.id)
|
||||||
|
return nil, E.New("reality verification failed")
|
||||||
|
}
|
||||||
|
|
||||||
return &utlsConnWrapper{uConn}, nil
|
return &utlsConnWrapper{uConn}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func realityClientFallback(uConn net.Conn, serverName string, fingerprint utls.ClientHelloID) {
|
||||||
|
defer uConn.Close()
|
||||||
|
client := &http.Client{
|
||||||
|
Transport: &http2.Transport{
|
||||||
|
DialTLSContext: func(ctx context.Context, network, addr string, config *tls.Config) (net.Conn, error) {
|
||||||
|
return uConn, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
request, _ := http.NewRequest("GET", "https://"+serverName, nil)
|
||||||
|
request.Header.Set("User-Agent", fingerprint.Client)
|
||||||
|
request.AddCookie(&http.Cookie{Name: "padding", Value: strings.Repeat("0", mRand.Intn(32)+30)})
|
||||||
|
response, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = io.Copy(io.Discard, response.Body)
|
||||||
|
response.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (e *RealityClientConfig) SetSessionIDGenerator(generator func(clientHello []byte, sessionID []byte) error) {
|
func (e *RealityClientConfig) SetSessionIDGenerator(generator func(clientHello []byte, sessionID []byte) error) {
|
||||||
e.uClient.config.SessionIDGenerator = generator
|
e.uClient.config.SessionIDGenerator = generator
|
||||||
}
|
}
|
||||||
|
@ -180,8 +226,5 @@ func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChain
|
||||||
if _, err := certs[0].Verify(opts); err != nil {
|
if _, err := certs[0].Verify(opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !c.verified {
|
|
||||||
return E.New("reality verification failed")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue