mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-26 06:39:20 +02:00
Refine fingerprints
Fixes https://github.com/XTLS/Xray-core/issues/1577
This commit is contained in:
parent
74416570d4
commit
dc72cf2c78
|
@ -379,6 +379,9 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||||
config.CipherSuites = c.CipherSuites
|
config.CipherSuites = c.CipherSuites
|
||||||
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
||||||
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
||||||
|
if config.Fingerprint != "" && tls.GetFingerprint(config.Fingerprint) == nil {
|
||||||
|
return nil, newError(`unknown fingerprint: `, config.Fingerprint)
|
||||||
|
}
|
||||||
config.RejectUnknownSni = c.RejectUnknownSNI
|
config.RejectUnknownSni = c.RejectUnknownSNI
|
||||||
|
|
||||||
if c.PinnedPeerCertificateChainSha256 != nil {
|
if c.PinnedPeerCertificateChainSha256 != nil {
|
||||||
|
|
|
@ -122,7 +122,7 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||||
|
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
var transportCredential credentials.TransportCredentials
|
var transportCredential credentials.TransportCredentials
|
||||||
if fingerprint, exists := tls.GetFingerprint(ctx, tlsConfig.Fingerprint); exists {
|
if fingerprint := tls.GetFingerprint(tlsConfig.Fingerprint); fingerprint != nil {
|
||||||
transportCredential = tls.NewGrpcUtls(tlsConfig.GetTLSConfig(), fingerprint)
|
transportCredential = tls.NewGrpcUtls(tlsConfig.GetTLSConfig(), fingerprint)
|
||||||
} else { // Fallback to normal gRPC TLS
|
} else { // Fallback to normal gRPC TLS
|
||||||
transportCredential = credentials.NewTLS(tlsConfig.GetTLSConfig())
|
transportCredential = credentials.NewTLS(tlsConfig.GetTLSConfig())
|
||||||
|
|
|
@ -75,7 +75,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||||
}
|
}
|
||||||
|
|
||||||
var cn tls.Interface
|
var cn tls.Interface
|
||||||
if fingerprint, ok := tls.GetFingerprint(ctx, tlsConfigs.Fingerprint); ok {
|
if fingerprint := tls.GetFingerprint(tlsConfigs.Fingerprint); fingerprint != nil {
|
||||||
cn = tls.UClient(pconn, tlsConfig, fingerprint).(*tls.UConn)
|
cn = tls.UClient(pconn, tlsConfig, fingerprint).(*tls.UConn)
|
||||||
} else {
|
} else {
|
||||||
cn = tls.Client(pconn, tlsConfig).(*tls.Conn)
|
cn = tls.Client(pconn, tlsConfig).(*tls.Conn)
|
||||||
|
|
|
@ -22,7 +22,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||||
|
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
||||||
if fingerprint, ok := tls.GetFingerprint(ctx, config.Fingerprint); ok {
|
if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil {
|
||||||
conn = tls.UClient(conn, tlsConfig, fingerprint)
|
conn = tls.UClient(conn, tlsConfig, fingerprint)
|
||||||
if err := conn.(*tls.UConn).Handshake(); err != nil {
|
if err := conn.(*tls.UConn).Handshake(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package tls
|
package tls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -9,15 +8,12 @@ import (
|
||||||
utls "github.com/refraction-networking/utls"
|
utls "github.com/refraction-networking/utls"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
|
||||||
var _ buf.Writer = (*Conn)(nil)
|
var _ buf.Writer = (*Conn)(nil)
|
||||||
|
|
||||||
var XrayRandom *utls.ClientHelloID
|
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
*tls.Conn
|
*tls.Conn
|
||||||
}
|
}
|
||||||
|
@ -118,58 +114,51 @@ func copyConfig(c *tls.Config) *utls.Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFingerprint(ctx context.Context, config string) (*utls.ClientHelloID, bool) {
|
func init() {
|
||||||
if XrayRandom == nil {
|
bigInt, _ := rand.Int(rand.Reader, big.NewInt(int64(len(ModernFingerprints))))
|
||||||
// lazy init
|
stopAt := int(bigInt.Int64())
|
||||||
for k, v := range FingerprintsForRNG {
|
i := 0
|
||||||
Fingerprints[k] = v
|
for _, v := range ModernFingerprints {
|
||||||
}
|
if i == stopAt {
|
||||||
big, err := rand.Int(rand.Reader, big.NewInt(int64(len(FingerprintsForRNG))))
|
PresetFingerprints["random"] = v
|
||||||
if err != nil {
|
|
||||||
newError("failed to generate xray random fingerprint").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
}
|
|
||||||
var i = int(big.Int64())
|
|
||||||
count := 0
|
|
||||||
for k, v := range FingerprintsForRNG {
|
|
||||||
if count == i {
|
|
||||||
newError("xray random fingerprint: ", k).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
XrayRandom = v
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
count++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if config == "random" {
|
|
||||||
return XrayRandom, true
|
|
||||||
}
|
|
||||||
fingerprint, ok := Fingerprints[config]
|
|
||||||
return fingerprint, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
var Fingerprints = map[string]*utls.ClientHelloID{
|
func GetFingerprint(name string) (fingerprint *utls.ClientHelloID) {
|
||||||
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fingerprint = PresetFingerprints[name]; fingerprint != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fingerprint = ModernFingerprints[name]; fingerprint != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fingerprint = OtherFingerprints[name]; fingerprint != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var PresetFingerprints = map[string]*utls.ClientHelloID{
|
||||||
|
// Recommended preset options in GUI clients
|
||||||
"chrome": &utls.HelloChrome_Auto,
|
"chrome": &utls.HelloChrome_Auto,
|
||||||
"firefox": &utls.HelloFirefox_Auto,
|
"firefox": &utls.HelloFirefox_Auto,
|
||||||
"safari": &utls.HelloSafari_Auto,
|
"safari": &utls.HelloSafari_Auto,
|
||||||
|
"ios": &utls.HelloIOS_Auto,
|
||||||
|
"android": &utls.HelloAndroid_11_OkHttp,
|
||||||
|
"edge": &utls.HelloEdge_Auto,
|
||||||
|
"360": &utls.Hello360_Auto,
|
||||||
|
"qq": &utls.HelloQQ_Auto,
|
||||||
|
"random": nil,
|
||||||
"randomized": &utls.HelloRandomized,
|
"randomized": &utls.HelloRandomized,
|
||||||
// This is a bit lame, but it seems there is no good way to reflect variables from Golang package
|
|
||||||
// We don't RNG for go, randomized, or fingerprints that is more than 4 years old
|
|
||||||
"hellogolang": &utls.HelloGolang,
|
|
||||||
"hellorandomized": &utls.HelloRandomized,
|
|
||||||
"hellorandomizedalpn": &utls.HelloRandomizedALPN,
|
|
||||||
"hellorandomizednoalpn": &utls.HelloRandomizedNoALPN,
|
|
||||||
"hellofirefox_55": &utls.HelloFirefox_55,
|
|
||||||
"hellofirefox_56": &utls.HelloFirefox_56,
|
|
||||||
"hellofirefox_63": &utls.HelloFirefox_63,
|
|
||||||
"hellofirefox_65": &utls.HelloFirefox_65,
|
|
||||||
"hellochrome_58": &utls.HelloChrome_58,
|
|
||||||
"hellochrome_62": &utls.HelloChrome_62,
|
|
||||||
"hellochrome_70": &utls.HelloChrome_70,
|
|
||||||
"hellochrome_72": &utls.HelloChrome_72,
|
|
||||||
"helloios_11_1": &utls.HelloIOS_11_1,
|
|
||||||
"hello360_7_5": &utls.Hello360_7_5,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var FingerprintsForRNG = map[string]*utls.ClientHelloID{
|
var ModernFingerprints = map[string]*utls.ClientHelloID{
|
||||||
|
// One of these will be chosen as `random` at startup
|
||||||
"hellofirefox_auto": &utls.HelloFirefox_Auto,
|
"hellofirefox_auto": &utls.HelloFirefox_Auto,
|
||||||
"hellofirefox_99": &utls.HelloFirefox_99,
|
"hellofirefox_99": &utls.HelloFirefox_99,
|
||||||
"hellofirefox_102": &utls.HelloFirefox_102,
|
"hellofirefox_102": &utls.HelloFirefox_102,
|
||||||
|
@ -197,6 +186,24 @@ var FingerprintsForRNG = map[string]*utls.ClientHelloID{
|
||||||
"helloqq_11_1": &utls.HelloQQ_11_1,
|
"helloqq_11_1": &utls.HelloQQ_11_1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var OtherFingerprints = map[string]*utls.ClientHelloID{
|
||||||
|
// Golang, randomized, and fingerprints that are more than 4 years old
|
||||||
|
"hellogolang": &utls.HelloGolang,
|
||||||
|
"hellorandomized": &utls.HelloRandomized,
|
||||||
|
"hellorandomizedalpn": &utls.HelloRandomizedALPN,
|
||||||
|
"hellorandomizednoalpn": &utls.HelloRandomizedNoALPN,
|
||||||
|
"hellofirefox_55": &utls.HelloFirefox_55,
|
||||||
|
"hellofirefox_56": &utls.HelloFirefox_56,
|
||||||
|
"hellofirefox_63": &utls.HelloFirefox_63,
|
||||||
|
"hellofirefox_65": &utls.HelloFirefox_65,
|
||||||
|
"hellochrome_58": &utls.HelloChrome_58,
|
||||||
|
"hellochrome_62": &utls.HelloChrome_62,
|
||||||
|
"hellochrome_70": &utls.HelloChrome_70,
|
||||||
|
"hellochrome_72": &utls.HelloChrome_72,
|
||||||
|
"helloios_11_1": &utls.HelloIOS_11_1,
|
||||||
|
"hello360_7_5": &utls.Hello360_7_5,
|
||||||
|
}
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
net.Conn
|
net.Conn
|
||||||
Handshake() error
|
Handshake() error
|
||||||
|
|
|
@ -86,7 +86,7 @@ func dialWebSocket(ctx context.Context, dest net.Destination, streamSettings *in
|
||||||
protocol = "wss"
|
protocol = "wss"
|
||||||
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest), tls.WithNextProto("http/1.1"))
|
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest), tls.WithNextProto("http/1.1"))
|
||||||
dialer.TLSClientConfig = tlsConfig
|
dialer.TLSClientConfig = tlsConfig
|
||||||
if fingerprint, exists := tls.GetFingerprint(ctx, config.Fingerprint); exists {
|
if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil {
|
||||||
dialer.NetDialTLSContext = func(_ context.Context, _, addr string) (gonet.Conn, error) {
|
dialer.NetDialTLSContext = func(_ context.Context, _, addr string) (gonet.Conn, error) {
|
||||||
// Like the NetDial in the dialer
|
// Like the NetDial in the dialer
|
||||||
pconn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
pconn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
|
|
Loading…
Reference in New Issue