Fix Cloudflared edge discovery ignoring configured resolver

This commit is contained in:
世界
2026-06-20 23:32:03 +08:00
parent 5f6e5a8ed0
commit cf60f76562
4 changed files with 79 additions and 14 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ require (
github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
github.com/sagernet/quic-go v0.59.0-sing-box-mod.4
github.com/sagernet/sing v0.8.11-0.20260514110501-905ad103a4df
github.com/sagernet/sing-cloudflared v0.1.0
github.com/sagernet/sing-cloudflared v0.1.1-0.20260620151903-a1d6358fe953
github.com/sagernet/sing-mux v0.3.5
github.com/sagernet/sing-quic v0.6.2-0.20260525051024-9467ede27fb7
github.com/sagernet/sing-shadowsocks v0.2.8
+2 -2
View File
@@ -254,8 +254,8 @@ github.com/sagernet/quic-go v0.59.0-sing-box-mod.4 h1:6qvrUW79S+CrPwWz6cMePXohgj
github.com/sagernet/quic-go v0.59.0-sing-box-mod.4/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4=
github.com/sagernet/sing v0.8.11-0.20260514110501-905ad103a4df h1:zSDw1g1JhIEqE/XPC3hW1wMdFPzbVgVJZiV86FAJoNQ=
github.com/sagernet/sing v0.8.11-0.20260514110501-905ad103a4df/go.mod h1:olXxWQNqRW/l2Q6JI3b2Qmz8iQnIFlOeeH8bx6JhgUA=
github.com/sagernet/sing-cloudflared v0.1.0 h1:to+2fcCx8zu4X/DirRw9Ihc+FrEZ7oEyIqeCoJiwIpw=
github.com/sagernet/sing-cloudflared v0.1.0/go.mod h1:bH2NKX+NpDTY1Zkxfboxw6MXB/ZywaNLmrDJYgKMJ2Y=
github.com/sagernet/sing-cloudflared v0.1.1-0.20260620151903-a1d6358fe953 h1:bqZWzc7mVO+V6Z07PAwav1TnlAlNltr/e1J2z8sZn4o=
github.com/sagernet/sing-cloudflared v0.1.1-0.20260620151903-a1d6358fe953/go.mod h1:bH2NKX+NpDTY1Zkxfboxw6MXB/ZywaNLmrDJYgKMJ2Y=
github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
github.com/sagernet/sing-quic v0.6.2-0.20260525051024-9467ede27fb7 h1:hFLPJ21uNZSbRnzhOKz4Zv0b4F93mpDorWyN93BeRcM=
+19 -11
View File
@@ -9,18 +9,19 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/inbound"
boxDialer "github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/dialer"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route/rule"
cloudflared "github.com/sagernet/sing-cloudflared"
tun "github.com/sagernet/sing-tun"
"github.com/sagernet/sing-cloudflared"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/pipe"
"github.com/sagernet/sing/service"
)
func RegisterInbound(registry *inbound.Registry) {
@@ -28,28 +29,35 @@ func RegisterInbound(registry *inbound.Registry) {
}
func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.CloudflaredInboundOptions) (adapter.Inbound, error) {
controlDialer, err := boxDialer.NewWithOptions(boxDialer.Options{
Context: ctx,
Options: options.ControlDialer,
RemoteIsDomain: true,
controlDialer, err := dialer.NewWithOptions(dialer.Options{
Context: ctx,
Options: options.ControlDialer,
RemoteIsDomain: true,
ResolverOnDetour: true,
})
if err != nil {
return nil, E.Cause(err, "build cloudflared control dialer")
}
tunnelDialer, err := boxDialer.NewWithOptions(boxDialer.Options{
Context: ctx,
Options: options.TunnelDialer,
RemoteIsDomain: true,
tunnelDialer, err := dialer.NewWithOptions(dialer.Options{
Context: ctx,
Options: options.TunnelDialer,
RemoteIsDomain: true,
ResolverOnDetour: true,
})
if err != nil {
return nil, E.Cause(err, "build cloudflared tunnel dialer")
}
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
controlResolver := newRouterResolver(dnsRouter, controlDialer.(dialer.ResolveDialer).QueryOptions())
tunnelResolver := newRouterResolver(dnsRouter, tunnelDialer.(dialer.ResolveDialer).QueryOptions())
service, err := cloudflared.NewService(cloudflared.ServiceOptions{
Logger: logger,
ConnectionDialer: &routerDialer{router: router, tag: tag},
ControlDialer: controlDialer,
TunnelDialer: tunnelDialer,
ControlResolver: controlResolver,
TunnelResolver: tunnelResolver,
ICMPHandler: &icmpRouterHandler{router: router, logger: logger, tag: tag},
ConnContext: func(connCtx context.Context) context.Context {
return adapter.WithContext(connCtx, &adapter.InboundContext{
+57
View File
@@ -0,0 +1,57 @@
//go:build with_cloudflared
package cloudflare
import (
"context"
"net"
"net/netip"
"sort"
"strings"
"github.com/sagernet/sing-box/adapter"
mDNS "github.com/miekg/dns"
)
type routerResolver struct {
dnsRouter adapter.DNSRouter
queryOptions adapter.DNSQueryOptions
}
func newRouterResolver(dnsRouter adapter.DNSRouter, queryOptions adapter.DNSQueryOptions) *routerResolver {
return &routerResolver{dnsRouter: dnsRouter, queryOptions: queryOptions}
}
func (r *routerResolver) LookupNetIP(ctx context.Context, host string) ([]netip.Addr, error) {
return r.dnsRouter.Lookup(ctx, strings.TrimSuffix(host, "."), r.queryOptions)
}
func (r *routerResolver) LookupSRV(ctx context.Context, service, proto, name string) ([]*net.SRV, error) {
message := &mDNS.Msg{}
message.SetQuestion(mDNS.Fqdn("_"+service+"._"+proto+"."+name), mDNS.TypeSRV)
response, err := r.dnsRouter.Exchange(ctx, message, r.queryOptions)
if err != nil {
return nil, err
}
var records []*net.SRV
for _, answer := range response.Answer {
record, isSRV := answer.(*mDNS.SRV)
if !isSRV {
continue
}
records = append(records, &net.SRV{
Target: record.Target,
Port: record.Port,
Priority: record.Priority,
Weight: record.Weight,
})
}
sort.SliceStable(records, func(i, j int) bool {
if records[i].Priority != records[j].Priority {
return records[i].Priority < records[j].Priority
}
return records[i].Weight > records[j].Weight
})
return records, nil
}