tailscale: Fix handle peer DNS query
This commit is contained in:
@@ -47,7 +47,7 @@ require (
|
||||
github.com/sagernet/sing-tun v0.8.11-0.20260603045801-6e76db79f94a
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7.0.20260520083128-cbb28480e2d5
|
||||
github.com/sagernet/wireguard-go v0.0.3
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||
github.com/spf13/cobra v1.10.2
|
||||
|
||||
@@ -262,8 +262,8 @@ github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkV
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478=
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1/go.mod h1:NjhsCEWedJm7eFLyhuBgIEzwfhRmytrUoiLluxs5Sk8=
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7 h1:8zc1Aph1+ElqF9/7aSPkO0o4vTd+AfQC+CO324mLWGg=
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7/go.mod h1:m87GAn4UcesHQF3leaPFEINZETO5za1LGn1GJdNDgNc=
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7.0.20260520083128-cbb28480e2d5 h1:QPLC5oJWzqHhxLobokFM7Utnqbr5OkLT/Kjc0od6qJs=
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7.0.20260520083128-cbb28480e2d5/go.mod h1:m87GAn4UcesHQF3leaPFEINZETO5za1LGn1GJdNDgNc=
|
||||
github.com/sagernet/wireguard-go v0.0.3 h1:6ebmwj/SFQRnYv6/nRCnwUzf+KFepF8tIBd57IAq1jE=
|
||||
github.com/sagernet/wireguard-go v0.0.3/go.mod h1:hEqi4y5czEg6LYtX2Bpjg+lV0b/J1n+5rA885Z66Mx0=
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
|
||||
|
||||
@@ -28,9 +28,10 @@ import (
|
||||
"github.com/sagernet/sing-box/adapter/endpoint"
|
||||
"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-box/route/rule"
|
||||
R "github.com/sagernet/sing-box/route/rule"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing-tun/ping"
|
||||
"github.com/sagernet/sing/common"
|
||||
@@ -61,6 +62,7 @@ import (
|
||||
"github.com/sagernet/tailscale/wgengine/router"
|
||||
"github.com/sagernet/tailscale/wgengine/wgcfg"
|
||||
|
||||
mDNS "github.com/miekg/dns"
|
||||
"go4.org/netipx"
|
||||
)
|
||||
|
||||
@@ -170,47 +172,47 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dialerQueryOptions := outboundDialer.(dialer.ResolveDialer).QueryOptions()
|
||||
dnsRouter := service.FromContext[adapter.DNSRouter](ctx)
|
||||
server := &tsnet.Server{
|
||||
Dir: stateDirectory,
|
||||
Hostname: hostname,
|
||||
Logf: func(format string, args ...any) {
|
||||
logger.Trace(fmt.Sprintf(format, args...))
|
||||
},
|
||||
UserLogf: func(format string, args ...any) {
|
||||
logger.Debug(fmt.Sprintf(format, args...))
|
||||
},
|
||||
Ephemeral: options.Ephemeral,
|
||||
AuthKey: options.AuthKey,
|
||||
ControlURL: options.ControlURL,
|
||||
AdvertiseTags: options.AdvertiseTags,
|
||||
Dialer: &endpointDialer{Dialer: outboundDialer, logger: logger},
|
||||
LookupHook: func(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
return dnsRouter.Lookup(ctx, host, outboundDialer.(dialer.ResolveDialer).QueryOptions())
|
||||
},
|
||||
DNS: &dnsConfigurtor{},
|
||||
HTTPClient: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return outboundDialer.DialContext(ctx, network, M.ParseSocksaddr(address))
|
||||
},
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: adapter.RootPoolFromContext(ctx),
|
||||
Time: ntp.TimeFuncFromContext(ctx),
|
||||
return &Endpoint{
|
||||
Adapter: endpoint.NewAdapter(C.TypeTailscale, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMP}, nil),
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logger,
|
||||
dnsRouter: dnsRouter,
|
||||
network: service.FromContext[adapter.NetworkManager](ctx),
|
||||
platformInterface: service.FromContext[adapter.PlatformInterface](ctx),
|
||||
server: &tsnet.Server{
|
||||
Dir: stateDirectory,
|
||||
Hostname: hostname,
|
||||
Logf: func(format string, args ...any) {
|
||||
logger.Trace(fmt.Sprintf(format, args...))
|
||||
},
|
||||
UserLogf: func(format string, args ...any) {
|
||||
logger.Debug(fmt.Sprintf(format, args...))
|
||||
},
|
||||
Ephemeral: options.Ephemeral,
|
||||
AuthKey: options.AuthKey,
|
||||
ControlURL: options.ControlURL,
|
||||
AdvertiseTags: options.AdvertiseTags,
|
||||
Dialer: &endpointDialer{Dialer: outboundDialer, logger: logger},
|
||||
LookupHook: func(ctx context.Context, host string) ([]netip.Addr, error) {
|
||||
return dnsRouter.Lookup(ctx, host, dialerQueryOptions)
|
||||
},
|
||||
DNS: &dnsConfigurtor{},
|
||||
HTTPClient: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return outboundDialer.DialContext(ctx, network, M.ParseSocksaddr(address))
|
||||
},
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: adapter.RootPoolFromContext(ctx),
|
||||
Time: ntp.TimeFuncFromContext(ctx),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return &Endpoint{
|
||||
Adapter: endpoint.NewAdapter(C.TypeTailscale, tag, []string{N.NetworkTCP, N.NetworkUDP, N.NetworkICMP}, nil),
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logger,
|
||||
dnsRouter: dnsRouter,
|
||||
network: service.FromContext[adapter.NetworkManager](ctx),
|
||||
platformInterface: service.FromContext[adapter.PlatformInterface](ctx),
|
||||
server: server,
|
||||
acceptRoutes: options.AcceptRoutes,
|
||||
exitNode: options.ExitNode,
|
||||
exitNodeAllowLANAccess: options.ExitNodeAllowLANAccess,
|
||||
@@ -229,6 +231,8 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
|
||||
func (t *Endpoint) Start(stage adapter.StartStage) error {
|
||||
switch stage {
|
||||
case adapter.StartStateInitialize:
|
||||
t.server.PeerDNSQueryHandler = (*peerDNSQueryHandler)(t)
|
||||
case adapter.StartStateStart:
|
||||
return t.start()
|
||||
case adapter.StartStatePostStart:
|
||||
@@ -681,9 +685,9 @@ func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destina
|
||||
}, routeContext, timeout, false)
|
||||
if err != nil {
|
||||
switch {
|
||||
case rule.IsBypassed(err):
|
||||
case R.IsBypassed(err):
|
||||
err = nil
|
||||
case rule.IsRejected(err):
|
||||
case R.IsRejected(err):
|
||||
t.logger.Trace("reject ", network, " connection from ", source.AddrString(), " to ", destination.AddrString())
|
||||
default:
|
||||
if network == N.NetworkICMP {
|
||||
@@ -877,3 +881,30 @@ func (c *dnsConfigurtor) GetBaseConfig() (tsDNS.OSConfig, error) {
|
||||
func (c *dnsConfigurtor) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type peerDNSQueryHandler Endpoint
|
||||
|
||||
func (t *peerDNSQueryHandler) HandlePeerDNSQuery(ctx context.Context, query []byte, sourceAddress netip.AddrPort, allowName func(name string) bool) ([]byte, error) {
|
||||
var message mDNS.Msg
|
||||
err := message.Unpack(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, question := range message.Question {
|
||||
if allowName != nil && !allowName(question.Name) {
|
||||
return dns.FixedResponseStatus(&message, mDNS.RcodeRefused).Pack()
|
||||
}
|
||||
}
|
||||
var metadata adapter.InboundContext
|
||||
metadata.Inbound = t.Tag()
|
||||
metadata.InboundType = t.Type()
|
||||
metadata.Source = M.SocksaddrFromNetIP(sourceAddress)
|
||||
response, err := t.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), &message, adapter.DNSQueryOptions{})
|
||||
if err != nil {
|
||||
if !R.IsRejected(err) && !E.IsClosedOrCanceled(err) {
|
||||
t.logger.ErrorContext(ctx, E.Cause(err, "process peer DNS query"))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return response.Pack()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user