Skip to content

Commit cf60f76

Browse files
committed
Fix Cloudflared edge discovery ignoring configured resolver
1 parent 5f6e5a8 commit cf60f76

4 files changed

Lines changed: 79 additions & 14 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ require (
4141
github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
4242
github.com/sagernet/quic-go v0.59.0-sing-box-mod.4
4343
github.com/sagernet/sing v0.8.11-0.20260514110501-905ad103a4df
44-
github.com/sagernet/sing-cloudflared v0.1.0
44+
github.com/sagernet/sing-cloudflared v0.1.1-0.20260620151903-a1d6358fe953
4545
github.com/sagernet/sing-mux v0.3.5
4646
github.com/sagernet/sing-quic v0.6.2-0.20260525051024-9467ede27fb7
4747
github.com/sagernet/sing-shadowsocks v0.2.8

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@ github.com/sagernet/quic-go v0.59.0-sing-box-mod.4 h1:6qvrUW79S+CrPwWz6cMePXohgj
254254
github.com/sagernet/quic-go v0.59.0-sing-box-mod.4/go.mod h1:OqILvS182CyOol5zNNo6bguvOGgXzV459+chpRaUC+4=
255255
github.com/sagernet/sing v0.8.11-0.20260514110501-905ad103a4df h1:zSDw1g1JhIEqE/XPC3hW1wMdFPzbVgVJZiV86FAJoNQ=
256256
github.com/sagernet/sing v0.8.11-0.20260514110501-905ad103a4df/go.mod h1:olXxWQNqRW/l2Q6JI3b2Qmz8iQnIFlOeeH8bx6JhgUA=
257-
github.com/sagernet/sing-cloudflared v0.1.0 h1:to+2fcCx8zu4X/DirRw9Ihc+FrEZ7oEyIqeCoJiwIpw=
258-
github.com/sagernet/sing-cloudflared v0.1.0/go.mod h1:bH2NKX+NpDTY1Zkxfboxw6MXB/ZywaNLmrDJYgKMJ2Y=
257+
github.com/sagernet/sing-cloudflared v0.1.1-0.20260620151903-a1d6358fe953 h1:bqZWzc7mVO+V6Z07PAwav1TnlAlNltr/e1J2z8sZn4o=
258+
github.com/sagernet/sing-cloudflared v0.1.1-0.20260620151903-a1d6358fe953/go.mod h1:bH2NKX+NpDTY1Zkxfboxw6MXB/ZywaNLmrDJYgKMJ2Y=
259259
github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
260260
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
261261
github.com/sagernet/sing-quic v0.6.2-0.20260525051024-9467ede27fb7 h1:hFLPJ21uNZSbRnzhOKz4Zv0b4F93mpDorWyN93BeRcM=

protocol/cloudflare/inbound.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,55 @@ import (
99

1010
"github.com/sagernet/sing-box/adapter"
1111
"github.com/sagernet/sing-box/adapter/inbound"
12-
boxDialer "github.com/sagernet/sing-box/common/dialer"
12+
"github.com/sagernet/sing-box/common/dialer"
1313
C "github.com/sagernet/sing-box/constant"
1414
"github.com/sagernet/sing-box/log"
1515
"github.com/sagernet/sing-box/option"
1616
"github.com/sagernet/sing-box/route/rule"
17-
cloudflared "github.com/sagernet/sing-cloudflared"
18-
tun "github.com/sagernet/sing-tun"
17+
"github.com/sagernet/sing-cloudflared"
18+
"github.com/sagernet/sing-tun"
1919
"github.com/sagernet/sing/common/bufio"
2020
E "github.com/sagernet/sing/common/exceptions"
2121
M "github.com/sagernet/sing/common/metadata"
2222
N "github.com/sagernet/sing/common/network"
2323
"github.com/sagernet/sing/common/pipe"
24+
"github.com/sagernet/sing/service"
2425
)
2526

2627
func RegisterInbound(registry *inbound.Registry) {
2728
inbound.Register[option.CloudflaredInboundOptions](registry, C.TypeCloudflared, NewInbound)
2829
}
2930

3031
func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.CloudflaredInboundOptions) (adapter.Inbound, error) {
31-
controlDialer, err := boxDialer.NewWithOptions(boxDialer.Options{
32-
Context: ctx,
33-
Options: options.ControlDialer,
34-
RemoteIsDomain: true,
32+
controlDialer, err := dialer.NewWithOptions(dialer.Options{
33+
Context: ctx,
34+
Options: options.ControlDialer,
35+
RemoteIsDomain: true,
36+
ResolverOnDetour: true,
3537
})
3638
if err != nil {
3739
return nil, E.Cause(err, "build cloudflared control dialer")
3840
}
39-
tunnelDialer, err := boxDialer.NewWithOptions(boxDialer.Options{
40-
Context: ctx,
41-
Options: options.TunnelDialer,
42-
RemoteIsDomain: true,
41+
tunnelDialer, err := dialer.NewWithOptions(dialer.Options{
42+
Context: ctx,
43+
Options: options.TunnelDialer,
44+
RemoteIsDomain: true,
45+
ResolverOnDetour: true,
4346
})
4447
if err != nil {
4548
return nil, E.Cause(err, "build cloudflared tunnel dialer")
4649
}
50+
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
51+
controlResolver := newRouterResolver(dnsRouter, controlDialer.(dialer.ResolveDialer).QueryOptions())
52+
tunnelResolver := newRouterResolver(dnsRouter, tunnelDialer.(dialer.ResolveDialer).QueryOptions())
4753

4854
service, err := cloudflared.NewService(cloudflared.ServiceOptions{
4955
Logger: logger,
5056
ConnectionDialer: &routerDialer{router: router, tag: tag},
5157
ControlDialer: controlDialer,
5258
TunnelDialer: tunnelDialer,
59+
ControlResolver: controlResolver,
60+
TunnelResolver: tunnelResolver,
5361
ICMPHandler: &icmpRouterHandler{router: router, logger: logger, tag: tag},
5462
ConnContext: func(connCtx context.Context) context.Context {
5563
return adapter.WithContext(connCtx, &adapter.InboundContext{

protocol/cloudflare/resolver.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//go:build with_cloudflared
2+
3+
package cloudflare
4+
5+
import (
6+
"context"
7+
"net"
8+
"net/netip"
9+
"sort"
10+
"strings"
11+
12+
"github.com/sagernet/sing-box/adapter"
13+
14+
mDNS "github.com/miekg/dns"
15+
)
16+
17+
type routerResolver struct {
18+
dnsRouter adapter.DNSRouter
19+
queryOptions adapter.DNSQueryOptions
20+
}
21+
22+
func newRouterResolver(dnsRouter adapter.DNSRouter, queryOptions adapter.DNSQueryOptions) *routerResolver {
23+
return &routerResolver{dnsRouter: dnsRouter, queryOptions: queryOptions}
24+
}
25+
26+
func (r *routerResolver) LookupNetIP(ctx context.Context, host string) ([]netip.Addr, error) {
27+
return r.dnsRouter.Lookup(ctx, strings.TrimSuffix(host, "."), r.queryOptions)
28+
}
29+
30+
func (r *routerResolver) LookupSRV(ctx context.Context, service, proto, name string) ([]*net.SRV, error) {
31+
message := &mDNS.Msg{}
32+
message.SetQuestion(mDNS.Fqdn("_"+service+"._"+proto+"."+name), mDNS.TypeSRV)
33+
response, err := r.dnsRouter.Exchange(ctx, message, r.queryOptions)
34+
if err != nil {
35+
return nil, err
36+
}
37+
var records []*net.SRV
38+
for _, answer := range response.Answer {
39+
record, isSRV := answer.(*mDNS.SRV)
40+
if !isSRV {
41+
continue
42+
}
43+
records = append(records, &net.SRV{
44+
Target: record.Target,
45+
Port: record.Port,
46+
Priority: record.Priority,
47+
Weight: record.Weight,
48+
})
49+
}
50+
sort.SliceStable(records, func(i, j int) bool {
51+
if records[i].Priority != records[j].Priority {
52+
return records[i].Priority < records[j].Priority
53+
}
54+
return records[i].Weight > records[j].Weight
55+
})
56+
return records, nil
57+
}

0 commit comments

Comments
 (0)