mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 13:05:46 +00:00
net/dns/resolver: add envknob to debug exit node DNS queries on on Windows
Add the envknob TS_DEBUG_EXIT_NODE_DNS_NET_PKG, which enables more verbose debug logging when calling the handleExitNodeDNSQueryWithNetPkg function. This function is currently only called on Windows and Android. Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Ieb3ca7b98837d7dc69cd9ca47609c1c52e3afd7b
This commit is contained in:
parent
d2301db49c
commit
880a41bfcc
@ -23,6 +23,7 @@
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
dns "golang.org/x/net/dns/dnsmessage"
|
dns "golang.org/x/net/dns/dnsmessage"
|
||||||
|
"tailscale.com/envknob"
|
||||||
"tailscale.com/net/dns/resolvconffile"
|
"tailscale.com/net/dns/resolvconffile"
|
||||||
"tailscale.com/net/netaddr"
|
"tailscale.com/net/netaddr"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
@ -341,7 +342,7 @@ func (r *Resolver) HandleExitNodeDNSQuery(ctx context.Context, q []byte, from ne
|
|||||||
default:
|
default:
|
||||||
return nil, errors.New("unsupported exit node OS")
|
return nil, errors.New("unsupported exit node OS")
|
||||||
case "windows", "android":
|
case "windows", "android":
|
||||||
return handleExitNodeDNSQueryWithNetPkg(ctx, nil, resp)
|
return handleExitNodeDNSQueryWithNetPkg(ctx, r.logf, nil, resp)
|
||||||
case "darwin":
|
case "darwin":
|
||||||
// /etc/resolv.conf is a lie and only says one upstream DNS
|
// /etc/resolv.conf is a lie and only says one upstream DNS
|
||||||
// but for now that's probably good enough. Later we'll
|
// but for now that's probably good enough. Later we'll
|
||||||
@ -385,6 +386,8 @@ func (r *Resolver) HandleExitNodeDNSQuery(ctx context.Context, q []byte, from ne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var debugExitNodeDNSNetPkg = envknob.RegisterBool("TS_DEBUG_EXIT_NODE_DNS_NET_PKG")
|
||||||
|
|
||||||
// handleExitNodeDNSQueryWithNetPkg takes a DNS query message in q and
|
// handleExitNodeDNSQueryWithNetPkg takes a DNS query message in q and
|
||||||
// return a reply (for the ExitDNS DoH service) using the net package's
|
// return a reply (for the ExitDNS DoH service) using the net package's
|
||||||
// native APIs. This is only used on Windows for now.
|
// native APIs. This is only used on Windows for now.
|
||||||
@ -393,7 +396,8 @@ func (r *Resolver) HandleExitNodeDNSQuery(ctx context.Context, q []byte, from ne
|
|||||||
//
|
//
|
||||||
// response contains the pre-serialized response, which notably
|
// response contains the pre-serialized response, which notably
|
||||||
// includes the original question and its header.
|
// includes the original question and its header.
|
||||||
func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolver, resp *response) (res []byte, err error) {
|
func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, logf logger.Logf, resolver *net.Resolver, resp *response) (res []byte, err error) {
|
||||||
|
logf = logger.WithPrefix(logf, "exitNodeDNSQueryWithNetPkg: ")
|
||||||
if resp.Question.Class != dns.ClassINET {
|
if resp.Question.Class != dns.ClassINET {
|
||||||
return nil, errors.New("unsupported class")
|
return nil, errors.New("unsupported class")
|
||||||
}
|
}
|
||||||
@ -406,9 +410,16 @@ func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolve
|
|||||||
|
|
||||||
handleError := func(err error) (res []byte, _ error) {
|
handleError := func(err error) (res []byte, _ error) {
|
||||||
if isGoNoSuchHostError(err) {
|
if isGoNoSuchHostError(err) {
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf(`converting Go "no such host" error to a NXDOMAIN: %v`, err)
|
||||||
|
}
|
||||||
resp.Header.RCode = dns.RCodeNameError
|
resp.Header.RCode = dns.RCodeNameError
|
||||||
return marshalResponse(resp)
|
return marshalResponse(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("returning error: %v", err)
|
||||||
|
}
|
||||||
// TODO: map other errors to RCodeServerFailure?
|
// TODO: map other errors to RCodeServerFailure?
|
||||||
// Or I guess our caller should do that?
|
// Or I guess our caller should do that?
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -422,6 +433,9 @@ func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolve
|
|||||||
if resp.Question.Type == dns.TypeAAAA {
|
if resp.Question.Type == dns.TypeAAAA {
|
||||||
network = "ip6"
|
network = "ip6"
|
||||||
}
|
}
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("resolving %s %q", network, name)
|
||||||
|
}
|
||||||
ips, err := r.LookupIP(ctx, network, name)
|
ips, err := r.LookupIP(ctx, network, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
@ -432,6 +446,9 @@ func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case dns.TypeTXT:
|
case dns.TypeTXT:
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("resolving TXT %q", name)
|
||||||
|
}
|
||||||
strs, err := r.LookupTXT(ctx, name)
|
strs, err := r.LookupTXT(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
@ -443,6 +460,9 @@ func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolve
|
|||||||
// TODO: is this RCodeFormatError?
|
// TODO: is this RCodeFormatError?
|
||||||
return nil, errors.New("bogus PTR name")
|
return nil, errors.New("bogus PTR name")
|
||||||
}
|
}
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("resolving PTR %q", ipStr)
|
||||||
|
}
|
||||||
addrs, err := r.LookupAddr(ctx, ipStr)
|
addrs, err := r.LookupAddr(ctx, ipStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
@ -451,12 +471,18 @@ func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolve
|
|||||||
resp.Name, _ = dnsname.ToFQDN(addrs[0])
|
resp.Name, _ = dnsname.ToFQDN(addrs[0])
|
||||||
}
|
}
|
||||||
case dns.TypeCNAME:
|
case dns.TypeCNAME:
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("resolving CNAME %q", name)
|
||||||
|
}
|
||||||
cname, err := r.LookupCNAME(ctx, name)
|
cname, err := r.LookupCNAME(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
}
|
}
|
||||||
resp.CNAME = cname
|
resp.CNAME = cname
|
||||||
case dns.TypeSRV:
|
case dns.TypeSRV:
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("resolving SRV %q", name)
|
||||||
|
}
|
||||||
// Thanks, Go: "To accommodate services publishing SRV
|
// Thanks, Go: "To accommodate services publishing SRV
|
||||||
// records under non-standard names, if both service
|
// records under non-standard names, if both service
|
||||||
// and proto are empty strings, LookupSRV looks up
|
// and proto are empty strings, LookupSRV looks up
|
||||||
@ -467,6 +493,9 @@ func handleExitNodeDNSQueryWithNetPkg(ctx context.Context, resolver *net.Resolve
|
|||||||
}
|
}
|
||||||
resp.SRVs = srvs
|
resp.SRVs = srvs
|
||||||
case dns.TypeNS:
|
case dns.TypeNS:
|
||||||
|
if debugExitNodeDNSNetPkg() {
|
||||||
|
logf("resolving NS %q", name)
|
||||||
|
}
|
||||||
nss, err := r.LookupNS(ctx, name)
|
nss, err := r.LookupNS(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@ -1122,7 +1123,7 @@ func TestHandleExitNodeDNSQueryWithNetPkg(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("no_such_host", func(t *testing.T) {
|
t.Run("no_such_host", func(t *testing.T) {
|
||||||
res, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), backResolver, &response{
|
res, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), t.Logf, backResolver, &response{
|
||||||
Header: dnsmessage.Header{
|
Header: dnsmessage.Header{
|
||||||
ID: 123,
|
ID: 123,
|
||||||
Response: true,
|
Response: true,
|
||||||
@ -1233,7 +1234,7 @@ func TestHandleExitNodeDNSQueryWithNetPkg(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(fmt.Sprintf("%v_%v", tt.Type, strings.Trim(tt.Name, ".")), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%v_%v", tt.Type, strings.Trim(tt.Name, ".")), func(t *testing.T) {
|
||||||
got, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), backResolver, &response{
|
got, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), t.Logf, backResolver, &response{
|
||||||
Header: dnsmessage.Header{
|
Header: dnsmessage.Header{
|
||||||
ID: 123,
|
ID: 123,
|
||||||
Response: true,
|
Response: true,
|
||||||
@ -1395,7 +1396,7 @@ func (a *wrapResolverConn) WriteTo(q []byte, _ net.Addr) (n int, err error) {
|
|||||||
if resp == nil {
|
if resp == nil {
|
||||||
return 0, errors.New("bad query")
|
return 0, errors.New("bad query")
|
||||||
}
|
}
|
||||||
res, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), a.r, resp)
|
res, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), log.Printf, a.r, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user