mirror of
https://github.com/safing/portmaster
synced 2025-09-02 02:29:12 +00:00
Update DNS resolver, reset resolvers if all failed
This commit is contained in:
parent
1f13af8f75
commit
ad7a1024d7
2 changed files with 75 additions and 32 deletions
|
@ -9,7 +9,6 @@ import (
|
|||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
|
@ -248,11 +247,12 @@ func intelligentResolve(ctx context.Context, fqdn string, qtype dns.Type, securi
|
|||
}
|
||||
|
||||
log.Tracer(ctx).Warningf("intel: failed to resolve %s%s: all resolvers failed (or were skipped to fulfill the security level)", fqdn, qtype.String())
|
||||
log.Criticalf("intel: failed to resolve %s%s: all resolvers failed (or were skipped to fulfill the security level)", fqdn, qtype.String())
|
||||
log.Criticalf("intel: failed to resolve %s%s: all resolvers failed (or were skipped to fulfill the security level), resetting servers...", fqdn, qtype.String())
|
||||
go resetResolverFailStatus()
|
||||
|
||||
return nil
|
||||
|
||||
// TODO: check if there would be resolvers available in lower security modes and alert user
|
||||
|
||||
}
|
||||
|
||||
func tryResolver(ctx context.Context, resolver *Resolver, lastFailBoundary int64, fqdn string, qtype dns.Type, securityLevel uint8) (*RRCache, bool) {
|
||||
|
@ -270,7 +270,7 @@ func tryResolver(ctx context.Context, resolver *Resolver, lastFailBoundary int64
|
|||
return nil, false
|
||||
}
|
||||
// check if failed recently
|
||||
if atomic.LoadInt64(resolver.LastFail) > lastFailBoundary {
|
||||
if resolver.LastFail() > lastFailBoundary {
|
||||
log.Tracer(ctx).Tracef("intel: skipping resolver %s, because it failed recently", resolver)
|
||||
return nil, false
|
||||
}
|
||||
|
@ -281,10 +281,10 @@ func tryResolver(ctx context.Context, resolver *Resolver, lastFailBoundary int64
|
|||
return nil, false
|
||||
}
|
||||
// check if resolver is already initialized
|
||||
if !resolver.Initialized.IsSet() {
|
||||
if !resolver.Initialized() {
|
||||
// first should init, others wait
|
||||
resolver.InitLock.Lock()
|
||||
if resolver.Initialized.IsSet() {
|
||||
if resolver.Initialized() {
|
||||
// unlock immediately if resolver was initialized
|
||||
resolver.InitLock.Unlock()
|
||||
} else {
|
||||
|
@ -292,7 +292,7 @@ func tryResolver(ctx context.Context, resolver *Resolver, lastFailBoundary int64
|
|||
defer resolver.InitLock.Unlock()
|
||||
}
|
||||
// check if previous init failed
|
||||
if atomic.LoadInt64(resolver.LastFail) > lastFailBoundary {
|
||||
if resolver.LastFail() > lastFailBoundary {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
@ -300,21 +300,23 @@ func tryResolver(ctx context.Context, resolver *Resolver, lastFailBoundary int64
|
|||
rrCache, err := query(ctx, resolver, fqdn, qtype)
|
||||
if err != nil {
|
||||
// check if failing is disabled
|
||||
if atomic.LoadInt64(resolver.LastFail) == -1 {
|
||||
if resolver.LastFail() == -1 {
|
||||
log.Tracer(ctx).Tracef("intel: non-failing resolver %s failed, moving to next: %s", resolver, err)
|
||||
// log.Tracef("intel: non-failing resolver %s failed (%s), moving to next", resolver, err)
|
||||
return nil, false
|
||||
}
|
||||
log.Tracer(ctx).Warningf("intel: resolver %s failed, moving to next: %s", resolver, err)
|
||||
log.Warningf("intel: resolver %s failed, moving to next: %s", resolver, err)
|
||||
resolver.LockReason.Lock()
|
||||
resolver.FailReason = err.Error()
|
||||
resolver.LockReason.Unlock()
|
||||
atomic.StoreInt64(resolver.LastFail, time.Now().Unix())
|
||||
resolver.Initialized.UnSet()
|
||||
resolver.Lock()
|
||||
resolver.failReason = err.Error()
|
||||
resolver.lastFail = time.Now().Unix()
|
||||
resolver.initialized = false
|
||||
resolver.Unlock()
|
||||
return nil, false
|
||||
}
|
||||
resolver.Initialized.SetToIf(false, true)
|
||||
resolver.Lock()
|
||||
resolver.initialized = true
|
||||
resolver.Unlock()
|
||||
|
||||
return rrCache, true
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/tevino/abool"
|
||||
|
||||
"github.com/Safing/portbase/log"
|
||||
|
||||
|
@ -20,6 +19,8 @@ import (
|
|||
|
||||
// Resolver holds information about an active resolver.
|
||||
type Resolver struct {
|
||||
sync.Mutex
|
||||
|
||||
// static
|
||||
Server string
|
||||
ServerType string
|
||||
|
@ -34,20 +35,51 @@ type Resolver struct {
|
|||
Search *[]string
|
||||
SkipFqdnBeforeInit string
|
||||
|
||||
// atomic
|
||||
Initialized *abool.AtomicBool
|
||||
InitLock sync.Mutex
|
||||
LastFail *int64
|
||||
Expires *int64
|
||||
InitLock sync.Mutex
|
||||
|
||||
// must be locked
|
||||
LockReason sync.Mutex
|
||||
FailReason string
|
||||
initialized bool
|
||||
lastFail int64
|
||||
failReason string
|
||||
fails int
|
||||
expires int64
|
||||
|
||||
// TODO: add:
|
||||
// Expiration (for server got from DHCP / ICMPv6)
|
||||
// bootstrapping (first query is already sent, wait for it to either succeed or fail - think about http bootstrapping here!)
|
||||
// expanded server info: type, server address, server port, options - so we do not have to parse this every time!
|
||||
// TODO: add Expiration (for server got from DHCP / ICMPv6)
|
||||
}
|
||||
|
||||
// Initialized returns the internal initialized value while locking the Resolver.
|
||||
func (r *Resolver) Initialized() bool {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.initialized
|
||||
}
|
||||
|
||||
// LastFail returns the internal lastfail value while locking the Resolver.
|
||||
func (r *Resolver) LastFail() int64 {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.lastFail
|
||||
}
|
||||
|
||||
// FailReason returns the internal failreason value while locking the Resolver.
|
||||
func (r *Resolver) FailReason() string {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.failReason
|
||||
}
|
||||
|
||||
// Fails returns the internal fails value while locking the Resolver.
|
||||
func (r *Resolver) Fails() int {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.fails
|
||||
}
|
||||
|
||||
// Expires returns the internal expires value while locking the Resolver.
|
||||
func (r *Resolver) Expires() int64 {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.expires
|
||||
}
|
||||
|
||||
func (r *Resolver) String() string {
|
||||
|
@ -144,7 +176,6 @@ configuredServersLoop:
|
|||
continue configuredServersLoop
|
||||
}
|
||||
|
||||
var lastFail int64
|
||||
new := &Resolver{
|
||||
Server: server,
|
||||
ServerType: strings.ToLower(parts[0]),
|
||||
|
@ -152,9 +183,7 @@ configuredServersLoop:
|
|||
ServerIP: ip,
|
||||
ServerIPScope: netutils.ClassifyIP(ip),
|
||||
ServerPort: port,
|
||||
LastFail: &lastFail,
|
||||
Source: "config",
|
||||
Initialized: abool.NewBool(false),
|
||||
}
|
||||
|
||||
switch new.ServerType {
|
||||
|
@ -197,7 +226,6 @@ assignedServersLoop:
|
|||
key = indexOfResolver(server, globalResolvers)
|
||||
if resetResolvers || key == -1 {
|
||||
|
||||
var lastFail int64
|
||||
new := &Resolver{
|
||||
Server: server,
|
||||
ServerType: "dns",
|
||||
|
@ -205,9 +233,7 @@ assignedServersLoop:
|
|||
ServerIP: nameserver.IP,
|
||||
ServerIPScope: netutils.ClassifyIP(nameserver.IP),
|
||||
ServerPort: 53,
|
||||
LastFail: &lastFail,
|
||||
Source: "dhcp",
|
||||
Initialized: abool.NewBool(false),
|
||||
}
|
||||
new.clientManager = newDNSClientManager(new)
|
||||
|
||||
|
@ -288,3 +314,18 @@ assignedServersLoop:
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// resetResolverFailStatus resets all resolver failures.
|
||||
func resetResolverFailStatus() {
|
||||
resolversLock.Lock()
|
||||
defer resolversLock.Unlock()
|
||||
|
||||
log.Tracef("old: %+v %+v, ", globalResolvers, localResolvers)
|
||||
for _, resolver := range append(globalResolvers, localResolvers...) {
|
||||
resolver.Lock()
|
||||
resolver.failReason = ""
|
||||
resolver.lastFail = 0
|
||||
resolver.Unlock()
|
||||
}
|
||||
log.Tracef("new: %+v %+v, ", globalResolvers, localResolvers)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue