net/dnscache: add a bunch of synthetic failure knobs

This commit is contained in:
Andrew Dunham 2022-09-02 12:06:25 -04:00 committed by Andrew Dunham
parent 6f700925ce
commit a37032932f
2 changed files with 51 additions and 9 deletions

View File

@ -15,6 +15,7 @@
"fmt" "fmt"
"log" "log"
"net" "net"
"os"
"runtime" "runtime"
"sync" "sync"
"time" "time"
@ -108,6 +109,11 @@ func (r *Resolver) ttl() time.Duration {
// If err is nil, ip will be non-nil. The v6 address may be nil even // If err is nil, ip will be non-nil. The v6 address may be nil even
// with a nil error. // with a nil error.
func (r *Resolver) LookupIP(ctx context.Context, host string) (ip, v6 net.IP, allIPs []net.IPAddr, err error) { func (r *Resolver) LookupIP(ctx context.Context, host string) (ip, v6 net.IP, allIPs []net.IPAddr, err error) {
if fileExists("/tmp/dnscache-synthetic-resolve-failure.txt") {
log.Printf("dnscache: synthetic resolve failure for %s", host)
return nil, nil, nil, fmt.Errorf("synthetic resolve failure for %s", host)
}
if ip := net.ParseIP(host); ip != nil { if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil { if ip4 := ip.To4(); ip4 != nil {
return ip4, nil, []net.IPAddr{{IP: ip4}}, nil return ip4, nil, []net.IPAddr{{IP: ip4}}, nil
@ -266,6 +272,7 @@ func (r *Resolver) addIPCache(host string, ip, ip6 net.IP, allIPs []net.IPAddr,
if r.ipCache == nil { if r.ipCache == nil {
r.ipCache = make(map[string]ipCacheEntry) r.ipCache = make(map[string]ipCacheEntry)
} }
if false { // DEBUG DEBUG
r.ipCache[host] = ipCacheEntry{ r.ipCache[host] = ipCacheEntry{
ip: ip, ip: ip,
ip6: ip6, ip6: ip6,
@ -273,6 +280,7 @@ func (r *Resolver) addIPCache(host string, ip, ip6 net.IP, allIPs []net.IPAddr,
expires: time.Now().Add(d), expires: time.Now().Add(d),
} }
} }
}
type DialContextFunc func(ctx context.Context, network, address string) (net.Conn, error) type DialContextFunc func(ctx context.Context, network, address string) (net.Conn, error)
@ -369,12 +377,30 @@ type dialCall struct {
// dnsWasTrustworthy reports whether we think the IP address(es) we // dnsWasTrustworthy reports whether we think the IP address(es) we
// tried (and failed) to dial were probably the correct IPs. Currently // tried (and failed) to dial were probably the correct IPs. Currently
// the heuristic is whether they ever worked previously. // the heuristic is whether they ever worked previously.
func (dc *dialCall) dnsWasTrustworthy() bool { func (dc *dialCall) dnsWasTrustworthy() (ret bool) {
dc.d.mu.Lock() dc.d.mu.Lock()
defer dc.d.mu.Unlock() defer dc.d.mu.Unlock()
dc.mu.Lock() dc.mu.Lock()
defer dc.mu.Unlock() defer dc.mu.Unlock()
defer func() {
log.Printf("dnscache: dnsWasTrustworthy = %v", ret)
}()
// DEBUG DEBUG DEBUG
if fileExists("/tmp/dnscache-drop-fails.txt") {
log.Printf("dnscache: clearing failed list")
dc.fails = map[netaddr.IP]error{}
}
if fileExists("/tmp/dnscache-drop-pastconnect.txt") {
log.Printf("dnscache: clearing past connections list")
dc.d.pastConnect = map[netaddr.IP]time.Time{}
}
if debug {
log.Printf("dnscache: we have %d failures and %d past connections", len(dc.fails), len(dc.d.pastConnect))
}
if len(dc.fails) == 0 { if len(dc.fails) == 0 {
// No information. // No information.
return false return false
@ -384,14 +410,30 @@ func (dc *dialCall) dnsWasTrustworthy() bool {
// this dialer, assume the DNS is fine. // this dialer, assume the DNS is fine.
for ip := range dc.fails { for ip := range dc.fails {
if _, ok := dc.d.pastConnect[ip]; ok { if _, ok := dc.d.pastConnect[ip]; ok {
if debug {
log.Printf("dnscache: DNS trustworthy due to past connection to %v", ip)
}
return true return true
} }
} }
return false return false
} }
func (dc *dialCall) dialOne(ctx context.Context, ip netaddr.IP) (net.Conn, error) { func fileExists(path string) bool {
c, err := dc.d.fwd(ctx, dc.network, net.JoinHostPort(ip.String(), dc.port)) st, err := os.Stat(path)
if err != nil {
return false
}
return st.Mode().IsRegular()
}
func (dc *dialCall) dialOne(ctx context.Context, ip netaddr.IP) (c net.Conn, err error) {
if fileExists("/tmp/dnscache-synthetic-dial-failure.txt") {
log.Printf("dnscache: synthetic dial failure for %s", ip)
err = fmt.Errorf("synthetic dial failure for %s", ip)
} else {
c, err = dc.d.fwd(ctx, dc.network, net.JoinHostPort(ip.String(), dc.port))
}
dc.noteDialResult(ip, err) dc.noteDialResult(ip, err)
return c, err return c, err
} }

View File

@ -19,6 +19,6 @@ pkgs.mkShell {
# - gopls, the language server for Go to increase editor integration # - gopls, the language server for Go to increase editor integration
# - git, the version control program (used in some scripts) # - git, the version control program (used in some scripts)
buildInputs = with pkgs; [ buildInputs = with pkgs; [
go goimports gopls git go gopls git
]; ];
} }