net/dns/resolver: add metric for number of truncated dns packets

Updates #2067

This should help us determine if more robust control of edns parameters
+ implementing answer truncation is warranted, given its likely complexity.

Signed-off-by: Tom DNetto <tom@tailscale.com>
This commit is contained in:
Tom DNetto 2022-04-22 15:01:55 -07:00 committed by Tom
parent 80ba161c40
commit 5fb8e01a8b
2 changed files with 28 additions and 2 deletions

View File

@ -41,6 +41,19 @@
// headerBytes is the number of bytes in a DNS message header. // headerBytes is the number of bytes in a DNS message header.
const headerBytes = 12 const headerBytes = 12
// dnsFlagTruncated is set in the flags word when the packet is truncated.
const dnsFlagTruncated = 0x200
// truncatedFlagSet returns true if the DNS packet signals that it has
// been truncated. False is also returned if the packet was too small
// to be valid.
func truncatedFlagSet(pkt []byte) bool {
if len(pkt) < headerBytes {
return false
}
return (binary.BigEndian.Uint16(pkt[2:4]) & dnsFlagTruncated) != 0
}
const ( const (
// responseTimeout is the maximal amount of time to wait for a DNS response. // responseTimeout is the maximal amount of time to wait for a DNS response.
responseTimeout = 5 * time.Second responseTimeout = 5 * time.Second
@ -420,6 +433,9 @@ func (f *forwarder) sendDoH(ctx context.Context, urlBase string, c *http.Client,
if err != nil { if err != nil {
metricDNSFwdDoHErrorBody.Add(1) metricDNSFwdDoHErrorBody.Add(1)
} }
if truncatedFlagSet(res) {
metricDNSFwdTruncated.Add(1)
}
return res, err return res, err
} }
@ -456,13 +472,18 @@ func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDe
metricDNSFwdErrorType.Add(1) metricDNSFwdErrorType.Add(1)
return nil, fmt.Errorf("tls:// resolvers not supported yet") return nil, fmt.Errorf("tls:// resolvers not supported yet")
} }
return f.sendUDP(ctx, fq, rr)
}
func (f *forwarder) sendUDP(ctx context.Context, fq *forwardQuery, rr resolverAndDelay) (ret []byte, err error) {
ipp, ok := rr.name.IPPort() ipp, ok := rr.name.IPPort()
if !ok { if !ok {
metricDNSFwdErrorType.Add(1) metricDNSFwdErrorType.Add(1)
return nil, fmt.Errorf("unrecognized resolver type %q", rr.name.Addr) return nil, fmt.Errorf("unrecognized resolver type %q", rr.name.Addr)
} }
metricDNSFwdUDP.Add(1) metricDNSFwdUDP.Add(1)
ln, err := f.packetListener(ipp.IP()) ln, err := f.packetListener(ipp.IP())
if err != nil { if err != nil {
return nil, err return nil, err
@ -522,7 +543,7 @@ func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDe
} }
if truncated { if truncated {
const dnsFlagTruncated = 0x200 // Set the truncated bit if it wasn't already.
flags := binary.BigEndian.Uint16(out[2:4]) flags := binary.BigEndian.Uint16(out[2:4])
flags |= dnsFlagTruncated flags |= dnsFlagTruncated
binary.BigEndian.PutUint16(out[2:4], flags) binary.BigEndian.PutUint16(out[2:4], flags)
@ -534,6 +555,10 @@ func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDe
// best we can do. // best we can do.
} }
if truncatedFlagSet(out) {
metricDNSFwdTruncated.Add(1)
}
clampEDNSSize(out, maxResponseBytes) clampEDNSSize(out, maxResponseBytes)
metricDNSFwdUDPSuccess.Add(1) metricDNSFwdUDPSuccess.Add(1)
return out, nil return out, nil

View File

@ -1340,6 +1340,7 @@ func unARPA(a string) (ipStr string, ok bool) {
metricDNSFwdErrorType = clientmetric.NewCounter("dns_query_fwd_error_type") metricDNSFwdErrorType = clientmetric.NewCounter("dns_query_fwd_error_type")
metricDNSFwdErrorParseAddr = clientmetric.NewCounter("dns_query_fwd_error_parse_addr") metricDNSFwdErrorParseAddr = clientmetric.NewCounter("dns_query_fwd_error_parse_addr")
metricDNSFwdTruncated = clientmetric.NewCounter("dns_query_fwd_truncated")
metricDNSFwdUDP = clientmetric.NewCounter("dns_query_fwd_udp") // on entry metricDNSFwdUDP = clientmetric.NewCounter("dns_query_fwd_udp") // on entry
metricDNSFwdUDPWrote = clientmetric.NewCounter("dns_query_fwd_udp_wrote") // sent UDP packet metricDNSFwdUDPWrote = clientmetric.NewCounter("dns_query_fwd_udp_wrote") // sent UDP packet