From 4c516c22490c51a07cec125ae429a13a06ebe3c0 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 3 Nov 2024 12:08:37 -0800 Subject: [PATCH] cmd/lopower: refactor in prep for DNS filtering Change-Id: I4a4c2d8331fbc2a7aaab4e75c27b29afaaeb0300 Signed-off-by: Brad Fitzpatrick --- cmd/lopower/lopower.go | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/cmd/lopower/lopower.go b/cmd/lopower/lopower.go index 9dd829982..82c66ec66 100644 --- a/cmd/lopower/lopower.go +++ b/cmd/lopower/lopower.go @@ -640,6 +640,28 @@ func (lp *lpServer) startTSNet(ctx context.Context) { } } +// filteredDNSQuery wraps the MagicDNS server response but filters out A record responses +// for *.ts.net if IPv4 is not enabled. This is so the e.g. a phone on a CGNAT-using +// network doesn't prefer the "A" record over AAAA when dialing and dial into the +// the carrier's CGNAT range into of the AAAA record into the Tailscale IPv6 ULA range. +func (lp *lpServer) filteredDNSQuery(ctx context.Context, q []byte, family string, from netip.AddrPort) ([]byte, error) { + m, ok := lp.tsnet.Sys().DNSManager.GetOK() + if !ok { + return nil, errors.New("DNSManager not ready") + } + res, err := m.Query(ctx, q, family, from) + if err != nil { + return nil, err + } + if *includeV4 { + return res, nil + } + + // TODO(bradfitz): filter out *.ts.net A records. + + return res, nil +} + // caller owns the raw memory. func (lp *lpServer) handleDNSUDPQuery(raw []byte) { var pkt packet.Parsed @@ -647,12 +669,8 @@ func (lp *lpServer) handleDNSUDPQuery(raw []byte) { if pkt.IPProto != ipproto.UDP || pkt.Dst.Port() != 53 || !lp.c.IsLocalIP(pkt.Dst.Addr()) { panic("caller error") } - m, ok := lp.tsnet.Sys().DNSManager.GetOK() - if !ok { - log.Printf("DNSManager.Get: not ready") - return - } - dnsRes, err := m.Query(context.Background(), pkt.Payload(), "udp", pkt.Src) + + dnsRes, err := lp.filteredDNSQuery(context.Background(), pkt.Payload(), "udp", pkt.Src) if err != nil { log.Printf("DNS query error: %v", err) return