Add ECH support for NaiveProxy outbound and tls.ech.query_server_name option

- Enable ECH for NaiveProxy outbound with DNS resolver integration
- Add query_server_name option to override domain for ECH HTTPS record queries
- Update cronet-go dependency and remove windows_386 support
This commit is contained in:
世界
2025-12-17 21:45:18 +08:00
parent 8101a7b0bd
commit 0585f6d065
10 changed files with 167 additions and 90 deletions

View File

@@ -1 +1 @@
78951bf5e641fcb42bc82b73e70bd28d819e5e55
4f12714a37cc546cbd171765e44988a348ba77fa

View File

@@ -51,6 +51,7 @@ func parseECHClientConfig(ctx context.Context, clientConfig ECHCapableConfig, op
return &ECHClientConfig{
ECHCapableConfig: clientConfig,
dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
queryServerName: options.ECH.QueryServerName,
}, nil
}
}
@@ -108,10 +109,11 @@ func parseECHKeys(echKey []byte) ([]tls.EncryptedClientHelloKey, error) {
type ECHClientConfig struct {
ECHCapableConfig
access sync.Mutex
dnsRouter adapter.DNSRouter
lastTTL time.Duration
lastUpdate time.Time
access sync.Mutex
dnsRouter adapter.DNSRouter
queryServerName string
lastTTL time.Duration
lastUpdate time.Time
}
func (s *ECHClientConfig) ClientHandshake(ctx context.Context, conn net.Conn) (aTLS.Conn, error) {
@@ -130,13 +132,17 @@ func (s *ECHClientConfig) fetchAndHandshake(ctx context.Context, conn net.Conn)
s.access.Lock()
defer s.access.Unlock()
if len(s.ECHConfigList()) == 0 || s.lastTTL == 0 || time.Since(s.lastUpdate) > s.lastTTL {
queryServerName := s.queryServerName
if queryServerName == "" {
queryServerName = s.ServerName()
}
message := &mDNS.Msg{
MsgHdr: mDNS.MsgHdr{
RecursionDesired: true,
},
Question: []mDNS.Question{
{
Name: mDNS.Fqdn(s.ServerName()),
Name: mDNS.Fqdn(queryServerName),
Qtype: mDNS.TypeHTTPS,
Qclass: mDNS.ClassINET,
},
@@ -175,7 +181,12 @@ func (s *ECHClientConfig) fetchAndHandshake(ctx context.Context, conn net.Conn)
}
func (s *ECHClientConfig) Clone() Config {
return &ECHClientConfig{ECHCapableConfig: s.ECHCapableConfig.Clone().(ECHCapableConfig), dnsRouter: s.dnsRouter, lastUpdate: s.lastUpdate}
return &ECHClientConfig{
ECHCapableConfig: s.ECHCapableConfig.Clone().(ECHCapableConfig),
dnsRouter: s.dnsRouter,
queryServerName: s.queryServerName,
lastUpdate: s.lastUpdate,
}
}
func UnmarshalECHKeys(raw []byte) ([]tls.EncryptedClientHelloKey, error) {

View File

@@ -86,7 +86,7 @@ See [UDP Over TCP](/configuration/shared/udp-over-tcp/) for details.
TLS configuration, see [TLS](/configuration/shared/tls/#outbound).
Only `server_name`, `certificate`, `certificate_path` and `certificate_public_key_sha256` are supported.
Only `server_name`, `certificate`, `certificate_path`, `certificate_public_key_sha256` and `ech` are supported.
### Dial Fields

View File

@@ -86,7 +86,7 @@ UDP over TCP 配置。
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
只有 `server_name``certificate``certificate_path``certificate_public_key_sha256` 是被支持的。
只有 `server_name``certificate``certificate_path``certificate_public_key_sha256``ech` 是被支持的。
### 拨号字段

View File

@@ -14,6 +14,7 @@ icon: material/new-box
:material-plus: [client_key_path](#client_key_path)
:material-plus: [client_authentication](#client_authentication)
:material-plus: [client_certificate_public_key_sha256](#client_certificate_public_key_sha256)
:material-plus: [ech.query_server_name](#query_server_name)
!!! quote "Changes in sing-box 1.12.0"
@@ -118,6 +119,7 @@ icon: material/new-box
"enabled": false,
"config": [],
"config_path": "",
"query_server_name": "",
// Deprecated
"pq_signature_schemes_enabled": false,
@@ -514,6 +516,16 @@ The path to ECH configuration, in PEM format.
If empty, load from DNS will be attempted.
#### query_server_name
!!! question "Since sing-box 1.13.0"
==Client only==
Overrides the domain name used for ECH HTTPS record queries.
If empty, `server_name` is used for queries.
#### fragment
!!! question "Since sing-box 1.12.0"

View File

@@ -14,6 +14,7 @@ icon: material/new-box
:material-plus: [client_key_path](#client_key_path)
:material-plus: [client_authentication](#client_authentication)
:material-plus: [client_certificate_public_key_sha256](#client_certificate_public_key_sha256)
:material-plus: [ech.query_server_name](#query_server_name)
!!! quote "sing-box 1.12.0 中的更改"
@@ -118,6 +119,7 @@ icon: material/new-box
"enabled": false,
"config": [],
"config_path": "",
"query_server_name": "",
// 废弃的
"pq_signature_schemes_enabled": false,
@@ -510,6 +512,16 @@ ECH 配置路径PEM 格式。
如果为空,将尝试从 DNS 加载。
#### query_server_name
!!! question "自 sing-box 1.13.0 起"
==仅客户端==
覆盖用于 ECH HTTPS 记录查询的域名。
如果为空,使用 `server_name` 查询。
#### fragment
!!! question "自 sing-box 1.12.0 起"

49
go.mod
View File

@@ -26,8 +26,8 @@ require (
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/cors v1.2.1
github.com/sagernet/cronet-go v0.0.0-20251217073804-0aadbdd7485f
github.com/sagernet/cronet-go/all v0.0.0-20251217073804-0aadbdd7485f
github.com/sagernet/cronet-go v0.0.0-20251217133746-1955399f1585
github.com/sagernet/cronet-go/all v0.0.0-20251217133746-1955399f1585
github.com/sagernet/fswatch v0.1.1
github.com/sagernet/gomobile v0.1.10
github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
@@ -108,29 +108,28 @@ require (
github.com/prometheus-community/pro-bing v0.4.0 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/windows_386 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217073321-98bf559282b1 // indirect
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217133247-ea405ec61e5f // indirect
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
github.com/spf13/pflag v1.0.6 // indirect

98
go.sum
View File

@@ -153,56 +153,54 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
github.com/sagernet/cronet-go v0.0.0-20251217073804-0aadbdd7485f h1:VMlH3aVnoN0bDUUCXHRJ6o8pb3ZJe/XpRLZsUGljrJ0=
github.com/sagernet/cronet-go v0.0.0-20251217073804-0aadbdd7485f/go.mod h1:DzcRxPQdpy5y2bbabpFXotAzPfY2P4HKZ8rQj3dSClo=
github.com/sagernet/cronet-go/all v0.0.0-20251217073804-0aadbdd7485f h1:eZcIuGEbGT9Ldh4QP14UxVzWOeMpwltU8lWCthefaGw=
github.com/sagernet/cronet-go/all v0.0.0-20251217073804-0aadbdd7485f/go.mod h1:qt0I3+OORnNmYDKKg3sN2/JguaNNl3ckgdoYEMeMGSA=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217073321-98bf559282b1 h1:JPrpsOAMZL7WpRfRymdazS/LTguAJVTqTPgIM1hRGSk=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217073321-98bf559282b1/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217073321-98bf559282b1 h1:yKOa/aPDWyB8+Vw2bze3lczwA0T+Jp014F82bb04RZg=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217073321-98bf559282b1 h1:bFWOKRv1gadjBtcCj5eSMVITdM/nFAM9WRvHGrFkW2M=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217073321-98bf559282b1/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217073321-98bf559282b1 h1:rwk5kw6tggldlnYkufttjrLgNZ4m2oDj8VPVbUkMIj8=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217073321-98bf559282b1 h1:Kz7898MkdKck/F3KhpQ3iSbDvuMcBKgcIT9kblbEAag=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217073321-98bf559282b1 h1:Csm66Pf4aFnrKW9SQ7/QAD+ODxrXM1y/1tOsMeWJt2Q=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217073321-98bf559282b1 h1:xYt0vGrcBe5E/4S1AhZrXZKqzfyMVv2EJzms+hkyMwE=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217073321-98bf559282b1 h1:HUIwo+G+gp5xJO7oFLXE8wUBuAMSlZCff7x8BkGwrV8=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217073321-98bf559282b1 h1:aM0ZlZyaMsj+ckqffWuwQ/LvlEocp4+8jf0CS3Y7C08=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217073321-98bf559282b1 h1:vAFYo+d3JZauxyW2fL8Kqqzjx2CoMSNYwS3mj2O3vig=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217073321-98bf559282b1/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217073321-98bf559282b1 h1:vitvkHM3isRtAt6J/hJbi1YEkkmoJQYxCWFyWBzetK0=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217073321-98bf559282b1 h1:Y5OW7wtkGkAICo1c4TjsSVsRe0YY0rGXBZS3W4kWEMM=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217073321-98bf559282b1 h1:U4fj5bK6Bp/Fc3OaQT2+pXioRTC4NkWXD8M+kcJIXx0=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217073321-98bf559282b1 h1:6aMDLdA+GF0J6CPBAXh6yn8wCJHhmREIU8I/uCVl16w=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217073321-98bf559282b1/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217073321-98bf559282b1 h1:OvZQkFRfs5fhN1ZNEjBRj1foZfwP9EdYhLFzrF23TO4=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217073321-98bf559282b1 h1:HJYoVGlafnfo7qwsNgocIwqg/ScCWH3MwC7oqD4Hj3I=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217073321-98bf559282b1 h1:U/eE0HxhS6iJxBhvt2mmkxvAuwjGQ6SfGz0IZc0NWQE=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217073321-98bf559282b1/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217073321-98bf559282b1 h1:V8mKJHu2iMoHjXH2deNQAY+Itcn9mlTeLDqhrFXkwcY=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217073321-98bf559282b1 h1:uHy+Un5hEvONSH5+nWHLWisvfhPIAE0EWq8cLjJpAuU=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217073321-98bf559282b1 h1:IXNOyK596srcY+OtnrCrUdclKVL5lakKcO30H85Kryc=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217073321-98bf559282b1/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
github.com/sagernet/cronet-go/lib/windows_386 v0.0.0-20251217073321-98bf559282b1 h1:aPMCg3h46G8Mx5WIiYyPTr/1EQ8j4wgCI/HUPGm/occ=
github.com/sagernet/cronet-go/lib/windows_386 v0.0.0-20251217073321-98bf559282b1/go.mod h1:rnS7D+ULJX2PrP0Cy+05GS0mRZ2PP6+gVSroZKt8fjk=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217073321-98bf559282b1 h1:snfESeRYtwkOlfQyoxfHKVNj4N0cpIpxMfsM+y52rw4=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217073321-98bf559282b1 h1:weCViGxMO6iajrI1EjHH4hMT/cXwGc+HhXH24xUrVGE=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217073321-98bf559282b1/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
github.com/sagernet/cronet-go v0.0.0-20251217133746-1955399f1585 h1:fu/J7Z+umFy5JwIxo2/7ixvuMRouJx93VU0RUXQx8aI=
github.com/sagernet/cronet-go v0.0.0-20251217133746-1955399f1585/go.mod h1:hwFHBEjjthyEquDULbr4c4ucMedp8Drb6Jvm2kt/0Bw=
github.com/sagernet/cronet-go/all v0.0.0-20251217133746-1955399f1585 h1:QN3WvGKiBg9N5vrSVKJzNTmK/BfEVMJNbRZDOlOfUpo=
github.com/sagernet/cronet-go/all v0.0.0-20251217133746-1955399f1585/go.mod h1:JTqmHTkUqWDX5Hz+jnx8kdDKJ07U80QS1hN0Wfe7CTI=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217133247-ea405ec61e5f h1:hjyZ7QZWWxYEW13lBT3+yAk7yENgKBuqhiw5rl/oxng=
github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:RHPD2Opa4kGqlTtHyhtMWhzvr3F1PZsT6GW+IMBaMYs=
github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217133247-ea405ec61e5f h1:wPrD+ADgFZC7AFFqUDWaKdcElqGODX10WrNpmUywX00=
github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:MC0T2f2SXwai6hdmTkkulE7PlHA11lHp1re7alZCQLo=
github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:X3RxBK5D5P3fcb+j8HqiEwhXEGMZkCg9ecmGYHo2qpg=
github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:K/CJaXL1djRbHyoVHGNx9nacncZPKE0QkEoO12nWL4s=
github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:uN/ay0BtmWWPdaoAsK5yu+bbQfr6iujEUTo7zZhF3a4=
github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:vdDIjy2y8DQEu1tVkpS/WOx0fEbK4yjMQv7X1e7MbFU=
github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:BElLblhAfW8Yd5ehlI9xk1FhlsGnKIX6oVak3C8cCnc=
github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217133247-ea405ec61e5f h1:vALFH1gx8nLLiAqkTy7tgrT9uLWCPC4e+Ir1UvEQkRw=
github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217133247-ea405ec61e5f h1:vQ99pp3CGklVoUGO2x//xne3BkfzSmNKDOzB5V9BoaU=
github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:MqINoyziFNrN8t5d/XCu1z+BZs2CkRLLKKOdx0g6bJ4=
github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217133247-ea405ec61e5f h1:L7HQmTsLFI7nAzyi2RIkmkuraSY7LRivBYoflIjQcxk=
github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217133247-ea405ec61e5f h1:DAswotlvnP6zYlP2KleGfMUy4dIBNNYGg3sh1reS53I=
github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:b2OhFosX8oUEdOpYkDS4fkbotbEe9WRMCpYGAWWq4VI=
github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217133247-ea405ec61e5f h1:H+GUhGCYe/4wHi+XRw96AgFxETSE3yCDhyAH7G6GbQc=
github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217133247-ea405ec61e5f h1:ziXSJVeboo4ZiCulyMbbEgG9ArfP98hqN1pALA15XeM=
github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:X9FaZ28M35Hj23agNDRDCklSrR0zb8PZz4K4EBalILE=
github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:qKlncyWLNJ3YtJrF3hK5YPd2Tb66ZF1iQXjq1mEADhE=
github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f h1:qpBg3PtrVx4Tgv+AwwoRgPqYsfEZeZ3Jn+zHfqr7Z1A=
github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217133247-ea405ec61e5f h1:PvjxP4e6qosQrhkPrpW2ZnRm2OKZsvEXIADV29fKWeY=
github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217133247-ea405ec61e5f h1:l3+QN68ENC0KHCxHa0iUO0vMGiG00TJlHgH8+jVrDNU=
github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20251217133247-ea405ec61e5f/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw=
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
github.com/sagernet/gomobile v0.1.10 h1:ElqZ0OVDvyQlU91MU0C9cfU0FrILBbc65+NOKzZ1t0c=

View File

@@ -215,9 +215,10 @@ type InboundECHOptions struct {
}
type OutboundECHOptions struct {
Enabled bool `json:"enabled,omitempty"`
Config badoption.Listable[string] `json:"config,omitempty"`
ConfigPath string `json:"config_path,omitempty"`
Enabled bool `json:"enabled,omitempty"`
Config badoption.Listable[string] `json:"config,omitempty"`
ConfigPath string `json:"config_path,omitempty"`
QueryServerName string `json:"query_server_name,omitempty"`
// Deprecated: not supported by stdlib
PQSignatureSchemesEnabled bool `json:"pq_signature_schemes_enabled,omitempty"`

View File

@@ -4,6 +4,7 @@ package naive
import (
"context"
"encoding/pem"
"net"
"os"
"strings"
@@ -14,6 +15,7 @@ import (
"github.com/sagernet/sing-box/adapter/outbound"
"github.com/sagernet/sing-box/common/dialer"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
@@ -22,6 +24,9 @@ import (
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/uot"
"github.com/sagernet/sing/service"
mDNS "github.com/miekg/dns"
)
func RegisterOutbound(registry *outbound.Registry) {
@@ -73,9 +78,6 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
if options.TLS.KernelTx || options.TLS.KernelRx {
return nil, E.New("kernel TLS is not supported on naive outbound")
}
if options.TLS.ECH != nil && options.TLS.ECH.Enabled {
return nil, E.New("ECH is not currently supported on naive outbound")
}
if options.TLS.UTLS != nil && options.TLS.UTLS.Enabled {
return nil, E.New("uTLS is not supported on naive outbound")
}
@@ -121,6 +123,44 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
}
}
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
var dnsResolver cronet.DNSResolverFunc
if dnsRouter != nil {
dnsResolver = func(dnsContext context.Context, request *mDNS.Msg) *mDNS.Msg {
response, err := dnsRouter.Exchange(dnsContext, request, adapter.DNSQueryOptions{})
if err != nil {
logger.Error("DNS exchange failed: ", err)
return dns.FixedResponseStatus(request, mDNS.RcodeServerFailure)
}
return response
}
}
var echEnabled bool
var echConfigList []byte
var echQueryServerName string
if options.TLS.ECH != nil && options.TLS.ECH.Enabled {
echEnabled = true
echQueryServerName = options.TLS.ECH.QueryServerName
var echConfig []byte
if len(options.TLS.ECH.Config) > 0 {
echConfig = []byte(strings.Join(options.TLS.ECH.Config, "\n"))
} else if options.TLS.ECH.ConfigPath != "" {
content, err := os.ReadFile(options.TLS.ECH.ConfigPath)
if err != nil {
return nil, E.Cause(err, "read ECH config")
}
echConfig = content
}
if len(echConfig) > 0 {
block, rest := pem.Decode(echConfig)
if block == nil || block.Type != "ECH CONFIGS" || len(rest) > 0 {
return nil, E.New("invalid ECH configs pem")
}
echConfigList = block.Bytes
}
}
client, err := cronet.NewNaiveClient(cronet.NaiveClientConfig{
Context: ctx,
ServerAddress: serverAddress,
@@ -132,6 +172,10 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
TrustedRootCertificates: trustedRootCertificates,
TrustedCertificatePublicKeySHA256: options.TLS.CertificatePublicKeySHA256,
Dialer: outboundDialer,
DNSResolver: dnsResolver,
ECHEnabled: echEnabled,
ECHConfigList: echConfigList,
ECHQueryServerName: echQueryServerName,
})
if err != nil {
return nil, err