Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

尝试支持ECH #3253

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ require (
github.com/onsi/ginkgo/v2 v2.16.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a // indirect
github.com/vishvananda/netns v0.0.4 // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ github.com/refraction-networking/utls v1.6.3/go.mod h1:yil9+7qSl+gBwJqztoQseO6Pr
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
github.com/sagernet/sing v0.3.8 h1:gm4JKalPhydMYX2zFOTnnd4TXtM/16WFRqSjMepYQQk=
github.com/sagernet/sing v0.3.8/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
Expand Down
2 changes: 2 additions & 0 deletions infra/conf/transport_internet.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ type TLSConfig struct {
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
MasterKeyLog string `json:"masterKeyLog"`
ECHConfig string `json:"ECHConfig"`
}

// Build implements Buildable.
Expand Down Expand Up @@ -454,6 +455,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
}

config.MasterKeyLog = c.MasterKeyLog
config.EchConfig = c.ECHConfig

return config, nil
}
Expand Down
2 changes: 2 additions & 0 deletions transport/internet/grpc/dial.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
}
if fingerprint := tls.GetFingerprint(tlsConfig.Fingerprint); fingerprint != nil {
return tls.UClient(c, config, fingerprint), nil
} else if ECHConfig := tls.GetEchConfig(streamSettings); ECHConfig != nil {
return tls.ECHClient(c, config, ECHConfig), nil
} else { // Fallback to normal gRPC TLS
return tls.Client(c, config), nil
}
Expand Down
2 changes: 2 additions & 0 deletions transport/internet/httpupgrade/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *
if err := conn.(*tls.UConn).WebsocketHandshakeContext(ctx); err != nil {
return nil, err
}
} else if ECHConfig := tls.GetEchConfig(streamSettings); ECHConfig != nil {
conn = tls.ECHClient(conn, tlsConfig, ECHConfig)
} else {
conn = tls.Client(pconn, tlsConfig)
}
Expand Down
2 changes: 2 additions & 0 deletions transport/internet/tcp/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
if err := conn.(*tls.UConn).HandshakeContext(ctx); err != nil {
return nil, err
}
} else if ECHConfig := tls.GetEchConfig(streamSettings); ECHConfig != nil {
conn = tls.ECHClient(conn, tlsConfig, ECHConfig)
} else {
conn = tls.Client(conn, tlsConfig)
}
Expand Down
9 changes: 9 additions & 0 deletions transport/internet/tls/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,12 @@ func ConfigFromStreamSettings(settings *internet.MemoryStreamConfig) *Config {
}
return config
}

// To confirm if ECH is enabled.
func GetEchConfig(settings *internet.MemoryStreamConfig) *string {
if settings.SecuritySettings.(*Config).EchConfig != "" {
ECHConfig := settings.SecuritySettings.(*Config).EchConfig
return &ECHConfig
}
return nil
}
32 changes: 21 additions & 11 deletions transport/internet/tls/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions transport/internet/tls/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@ message Config {
repeated bytes pinned_peer_certificate_public_key_sha256 = 14;

string master_key_log = 15;
string ech_config = 16;
}
40 changes: 40 additions & 0 deletions transport/internet/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"context"
"crypto/rand"
"crypto/tls"
"encoding/base64"
"math/big"
"time"

utls "github.com/refraction-networking/utls"
cftls "github.com/sagernet/cloudflare-tls"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
)
Expand Down Expand Up @@ -66,6 +68,44 @@ func Client(c net.Conn, config *tls.Config) net.Conn {
return &Conn{Conn: tlsConn}
}

// ←--------ECH part--------→
// This is a temporary solution before the official GOTLS support ECH.
// We use Cloudflare's fork.

type ECHConn struct {
*cftls.Conn
}

// We convert tls.Config to cftls.Config.
// And add ECH config in this step
func copyECHConfig(c *tls.Config, ECHConfig *string) *cftls.Config {
echConfig, err := base64.StdEncoding.DecodeString(*ECHConfig)
if err != nil {
return nil
}
echConfigs, err := cftls.UnmarshalECHConfigs(echConfig)
if err != nil {
return nil
}
return &cftls.Config{
RootCAs: c.RootCAs,
ServerName: c.ServerName,
InsecureSkipVerify: c.InsecureSkipVerify,
VerifyPeerCertificate: c.VerifyPeerCertificate,
KeyLogWriter: c.KeyLogWriter,
ECHEnabled: true,
ClientECHConfigs: echConfigs,
}
}

// Client initiates a *ECH* TLS client handshake on the given connection.
func ECHClient(c net.Conn, config *tls.Config, ECHConfig *string) net.Conn {
tlsConn := cftls.Client(c, copyECHConfig(config, ECHConfig))
return &ECHConn{Conn: tlsConn}
}

// ←--------ECH part--------→

// Server initiates a TLS server handshake on the given connection.
func Server(c net.Conn, config *tls.Config) net.Conn {
tlsConn := tls.Server(c, config)
Expand Down