Skip to content

Commit

Permalink
Improve ECH support
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Aug 29, 2023
1 parent c75e32e commit f89889f
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 21 deletions.
16 changes: 9 additions & 7 deletions common/tls/ech_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"net"
"net/netip"
"os"
"strings"

cftls "github.com/sagernet/cloudflare-tls"
"github.com/sagernet/sing-box/adapter"
Expand Down Expand Up @@ -168,16 +170,16 @@ func NewECHClient(router adapter.Router, serverAddress string, options option.Ou
tlsConfig.ECHEnabled = true
tlsConfig.PQSignatureSchemesEnabled = options.ECH.PQSignatureSchemesEnabled
tlsConfig.DynamicRecordSizingDisabled = options.ECH.DynamicRecordSizingDisabled
if options.ECH.Config != "" {
clientConfigContent, err := base64.StdEncoding.DecodeString(options.ECH.Config)
if err != nil {
return nil, err
if len(options.ECH.Config) > 0 {
block, rest := pem.Decode([]byte(strings.Join(options.ECH.Config, "\n")))
if block == nil || block.Type != "ECH CONFIGS" || len(rest) > 0 {
return nil, E.New("invalid ECH configs pem")
}
clientConfig, err := cftls.UnmarshalECHConfigs(clientConfigContent)
echConfigs, err := cftls.UnmarshalECHConfigs(block.Bytes)
if err != nil {
return nil, err
return nil, E.Cause(err, "parse ECH configs")
}
tlsConfig.ClientECHConfigs = clientConfig
tlsConfig.ClientECHConfigs = echConfigs
} else {
tlsConfig.GetClientECHConfigs = fetchECHClientConfig(router)
}
Expand Down
265 changes: 265 additions & 0 deletions common/tls/ech_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
package tls

import (
"context"
"crypto/tls"
"encoding/pem"
"net"
"os"
"strings"

cftls "github.com/sagernet/cloudflare-tls"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"

"github.com/fsnotify/fsnotify"
)

type echServerConfig struct {
config *cftls.Config
logger log.Logger
acmeService adapter.Service
certificate []byte
key []byte
certificatePath string
keyPath string
watcher *fsnotify.Watcher
}

func (c *echServerConfig) ServerName() string {
return c.config.ServerName
}

func (c *echServerConfig) SetServerName(serverName string) {
c.config.ServerName = serverName
}

func (c *echServerConfig) NextProtos() []string {
return c.config.NextProtos
}

func (c *echServerConfig) SetNextProtos(nextProto []string) {
c.config.NextProtos = nextProto
}

func (c *echServerConfig) Config() (*STDConfig, error) {
return nil, E.New("unsupported usage for ECH")
}

func (c *echServerConfig) Client(conn net.Conn) (Conn, error) {
return &echConnWrapper{cftls.Client(conn, c.config)}, nil

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips64el, linux, mips64le)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Debug build (Go 1.20)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-arm64, freebsd, arm64)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv6, linux, arm, 6)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv7, linux, arm, 7)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips64, linux, mips64)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv5, linux, arm, 5)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-386, linux, 386)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (darwin-arm64, darwin, arm64)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-386, freebsd, 386)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-amd64-v3, linux, amd64, v3)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-arm64, linux, arm64)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (darwin-amd64-v3, darwin, amd64, v3)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-amd64-v3, freebsd, amd64, v3)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-amd64, freebsd, amd64, v1)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (darwin-amd64, darwin, amd64, v1)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-amd64, linux, amd64, v1)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mipsel-hardfloat, linux, mipsle, hardfloat)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Debug build

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mipsel-softfloat, linux, mipsle, softfloat)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-s390x, linux, s390x)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-amd64-v3, windows, amd64, v3)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-amd64, windows, amd64, v1)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips-hardfloat, linux, mips, hardfloat)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-arm32v7, windows, arm, 7)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips-softfloat, linux, mips, softfloat)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-386, windows, 386)

undefined: echConnWrapper

Check failure on line 52 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-arm64, windows, arm64)

undefined: echConnWrapper
}

func (c *echServerConfig) Server(conn net.Conn) (Conn, error) {
return &echConnWrapper{cftls.Server(conn, c.config)}, nil

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: echConnWrapper (typecheck)

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: echConnWrapper) (typecheck)

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Build

undefined: echConnWrapper) (typecheck)

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips64el, linux, mips64le)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Debug build (Go 1.20)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-arm64, freebsd, arm64)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv6, linux, arm, 6)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv7, linux, arm, 7)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips64, linux, mips64)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv5, linux, arm, 5)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-386, linux, 386)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (darwin-arm64, darwin, arm64)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-386, freebsd, 386)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-amd64-v3, linux, amd64, v3)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-arm64, linux, arm64)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (darwin-amd64-v3, darwin, amd64, v3)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-amd64-v3, freebsd, amd64, v3)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-amd64, freebsd, amd64, v1)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (darwin-amd64, darwin, amd64, v1)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-amd64, linux, amd64, v1)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mipsel-hardfloat, linux, mipsle, hardfloat)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / Debug build

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mipsel-softfloat, linux, mipsle, softfloat)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-s390x, linux, s390x)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-amd64-v3, windows, amd64, v3)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-amd64, windows, amd64, v1)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips-hardfloat, linux, mips, hardfloat)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-arm32v7, windows, arm, 7)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips-softfloat, linux, mips, softfloat)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-386, windows, 386)

undefined: echConnWrapper

Check failure on line 56 in common/tls/ech_server.go

View workflow job for this annotation

GitHub Actions / cross (windows-arm64, windows, arm64)

undefined: echConnWrapper
}

func (c *echServerConfig) Clone() Config {
return &echServerConfig{
config: c.config.Clone(),
}
}

func (c *echServerConfig) Start() error {
if c.acmeService != nil {
return c.acmeService.Start()
} else {
if c.certificatePath == "" && c.keyPath == "" {
return nil
}
err := c.startWatcher()
if err != nil {
c.logger.Warn("create fsnotify watcher: ", err)
}
return nil
}
}

func (c *echServerConfig) startWatcher() error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
if c.certificatePath != "" {
err = watcher.Add(c.certificatePath)
if err != nil {
return err
}
}
if c.keyPath != "" {
err = watcher.Add(c.keyPath)
if err != nil {
return err
}
}
c.watcher = watcher
go c.loopUpdate()
return nil
}

func (c *echServerConfig) loopUpdate() {
for {
select {
case event, ok := <-c.watcher.Events:
if !ok {
return
}
if event.Op&fsnotify.Write != fsnotify.Write {
continue
}
err := c.reloadKeyPair()
if err != nil {
c.logger.Error(E.Cause(err, "reload TLS key pair"))
}
case err, ok := <-c.watcher.Errors:
if !ok {
return
}
c.logger.Error(E.Cause(err, "fsnotify error"))
}
}
}

func (c *echServerConfig) reloadKeyPair() error {
if c.certificatePath != "" {
certificate, err := os.ReadFile(c.certificatePath)
if err != nil {
return E.Cause(err, "reload certificate from ", c.certificatePath)
}
c.certificate = certificate
}
if c.keyPath != "" {
key, err := os.ReadFile(c.keyPath)
if err != nil {
return E.Cause(err, "reload key from ", c.keyPath)
}
c.key = key
}
keyPair, err := cftls.X509KeyPair(c.certificate, c.key)
if err != nil {
return E.Cause(err, "reload key pair")
}
c.config.Certificates = []cftls.Certificate{keyPair}
c.logger.Info("reloaded TLS certificate")
return nil
}

func (c *echServerConfig) Close() error {
if c.acmeService != nil {
return c.acmeService.Close()
}
if c.watcher != nil {
return c.watcher.Close()
}
return nil
}

func NewECHServer(ctx context.Context, router adapter.Router, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
if !options.Enabled {
return nil, nil
}
var tlsConfig cftls.Config
var acmeService adapter.Service
if options.ACME != nil && len(options.ACME.Domain) > 0 {
return nil, E.New("acme is unavailable in ech")
}
tlsConfig.Time = router.TimeFunc()
if options.ServerName != "" {
tlsConfig.ServerName = options.ServerName
}
if len(options.ALPN) > 0 {
tlsConfig.NextProtos = append(options.ALPN, tlsConfig.NextProtos...)
}
if options.MinVersion != "" {
minVersion, err := ParseTLSVersion(options.MinVersion)
if err != nil {
return nil, E.Cause(err, "parse min_version")
}
tlsConfig.MinVersion = minVersion
}
if options.MaxVersion != "" {
maxVersion, err := ParseTLSVersion(options.MaxVersion)
if err != nil {
return nil, E.Cause(err, "parse max_version")
}
tlsConfig.MaxVersion = maxVersion
}
if options.CipherSuites != nil {
find:
for _, cipherSuite := range options.CipherSuites {
for _, tlsCipherSuite := range tls.CipherSuites() {
if cipherSuite == tlsCipherSuite.Name {
tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, tlsCipherSuite.ID)
continue find
}
}
return nil, E.New("unknown cipher_suite: ", cipherSuite)
}
}
var certificate []byte
var key []byte
if acmeService == nil {
if options.Certificate != "" {
certificate = []byte(options.Certificate)
} else if options.CertificatePath != "" {
content, err := os.ReadFile(options.CertificatePath)
if err != nil {
return nil, E.Cause(err, "read certificate")
}
certificate = content
}
if options.Key != "" {
key = []byte(options.Key)
} else if options.KeyPath != "" {
content, err := os.ReadFile(options.KeyPath)
if err != nil {
return nil, E.Cause(err, "read key")
}
key = content
}

if certificate == nil {
return nil, E.New("missing certificate")
} else if key == nil {
return nil, E.New("missing key")
}

keyPair, err := cftls.X509KeyPair(certificate, key)
if err != nil {
return nil, E.Cause(err, "parse x509 key pair")
}
tlsConfig.Certificates = []cftls.Certificate{keyPair}
}

block, rest := pem.Decode([]byte(strings.Join(options.ECH.Key, "\n")))
if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 {
return nil, E.New("invalid ECH keys pem")
}

echKeys, err := cftls.EXP_UnmarshalECHKeys(block.Bytes)
if err != nil {
return nil, E.Cause(err, "parse ECH keys")
}

echKeySet, err := cftls.EXP_NewECHKeySet(echKeys)
if err != nil {
return nil, E.Cause(err, "create ECH key set")
}

tlsConfig.ECHEnabled = true
tlsConfig.PQSignatureSchemesEnabled = options.ECH.PQSignatureSchemesEnabled
tlsConfig.DynamicRecordSizingDisabled = options.ECH.DynamicRecordSizingDisabled
tlsConfig.ServerECHProvider = echKeySet

return &echServerConfig{
config: &tlsConfig,
logger: logger,
acmeService: acmeService,
certificate: certificate,
key: key,
certificatePath: options.CertificatePath,
keyPath: options.KeyPath,
}, nil
}
4 changes: 3 additions & 1 deletion common/tls/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ func NewServer(ctx context.Context, router adapter.Router, logger log.Logger, op
if !options.Enabled {
return nil, nil
}
if options.Reality != nil && options.Reality.Enabled {
if options.ECH != nil && options.ECH.Enabled {
return NewECHServer(ctx, router, logger, options)
} else if options.Reality != nil && options.Reality.Enabled {
return NewRealityServer(ctx, router, logger, options)
} else {
return NewSTDServer(ctx, router, logger, options)
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
github.com/ooni/go-libtor v1.1.8
github.com/oschwald/maxminddb-golang v1.12.0
github.com/pires/go-proxyproto v0.7.0
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a
github.com/sagernet/gomobile v0.0.0-20230728014906-3de089147f59
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
github.com/sagernet/quic-go v0.0.0-20230825040534-0cd917b2ddda
Expand Down Expand Up @@ -50,6 +50,7 @@ require (
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
howett.net/plist v1.0.0
)

//replace github.com/sagernet/sing => ../sing
Expand All @@ -58,7 +59,7 @@ require (
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
Expand Down Expand Up @@ -93,6 +94,5 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c h1:K1VdSnBZiGapczwcUKnE1qcsMBclA84DUOD2NG/78VY=
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
Expand Down Expand Up @@ -98,8 +98,8 @@ github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1
github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt1Jtp5vW2ohNvstvQffTOQ/s5vENuGXzdA+TM=
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
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/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
github.com/sagernet/gomobile v0.0.0-20230728014906-3de089147f59 h1:vN4divY6LYHcYmiTsCHNPmGZtEsEKJzh81LyvgAQfEQ=
Expand Down
16 changes: 12 additions & 4 deletions option/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type InboundTLSOptions struct {
Key string `json:"key,omitempty"`
KeyPath string `json:"key_path,omitempty"`
ACME *InboundACMEOptions `json:"acme,omitempty"`
ECH *InboundECHOptions `json:"ech,omitempty"`
Reality *InboundRealityOptions `json:"reality,omitempty"`
}

Expand Down Expand Up @@ -45,11 +46,18 @@ type InboundRealityHandshakeOptions struct {
DialerOptions
}

type InboundECHOptions struct {
Enabled bool `json:"enabled,omitempty"`
PQSignatureSchemesEnabled bool `json:"pq_signature_schemes_enabled,omitempty"`
DynamicRecordSizingDisabled bool `json:"dynamic_record_sizing_disabled,omitempty"`
Key Listable[string] `json:"ech_keys,omitempty"`
}

type OutboundECHOptions struct {
Enabled bool `json:"enabled,omitempty"`
PQSignatureSchemesEnabled bool `json:"pq_signature_schemes_enabled,omitempty"`
DynamicRecordSizingDisabled bool `json:"dynamic_record_sizing_disabled,omitempty"`
Config string `json:"config,omitempty"`
Enabled bool `json:"enabled,omitempty"`
PQSignatureSchemesEnabled bool `json:"pq_signature_schemes_enabled,omitempty"`
DynamicRecordSizingDisabled bool `json:"dynamic_record_sizing_disabled,omitempty"`
Config Listable[string] `json:"config,omitempty"`
}

type OutboundUTLSOptions struct {
Expand Down
Loading

0 comments on commit f89889f

Please sign in to comment.