Pull request: dnsforward: imp ipset caching, logging, and eperm handling

Merge in DNS/adguard-home from ipset-fix to master

Updates #2619.

Squashed commit of the following:

commit 6939c823598b1e74cb3d991aad1b928547fd26a9
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Feb 1 16:55:14 2021 +0300

    dnsforward: imp code

commit 99e3a7c30b79d7929ddd9b700d7dd3d2683ec6d2
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Feb 1 15:52:12 2021 +0300

    dnsforward: imp ipset caching, logging, and eperm handling
This commit is contained in:
Ainar Garipov 2021-02-01 17:06:09 +03:00
parent adb76aa9b8
commit 3e0238aa99
2 changed files with 37 additions and 5 deletions

View File

@ -2,9 +2,11 @@
package dnsforward package dnsforward
import ( import (
"errors"
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"os"
"runtime" "runtime"
"sync" "sync"
"time" "time"
@ -198,10 +200,16 @@ func (s *Server) Prepare(config *ServerConfig) error {
// -- // --
err := s.ipset.init(s.conf.IPSETList) err := s.ipset.init(s.conf.IPSETList)
if err != nil { if err != nil {
// ipset cannot be initialized in a Snap version (and maybe - without root) if !errors.Is(err, os.ErrPermission) {
// this needs to be handled properly return fmt.Errorf("cannot initialize ipset: %w", err)
// TODO: Handle this properly }
log.Info("Cannot initialize ipset module due to %v", err)
// ipset cannot currently be initialized if the server was
// installed from Snap or when the user or the binary doesn't
// have the required permissions.
//
// Log and go on.
log.Error("cannot initialize ipset: %s", err)
} }
// Prepare DNS servers settings // Prepare DNS servers settings

View File

@ -37,6 +37,11 @@ type ipsetCtx struct {
nameToIpset map[string]ipsetProps nameToIpset map[string]ipsetProps
domainToIpsets map[string][]ipsetProps domainToIpsets map[string][]ipsetProps
// TODO(a.garipov): Currently, the ipset list is static, and we don't
// read the IPs already in sets, so we can assume that all incoming IPs
// are either added to all corresponding ipsets or not. When that stops
// being the case, for example if we add dynamic reconfiguration of
// ipsets, this map will need to become a per-ipset-name one.
addedIPs map[[16]byte]struct{} addedIPs map[[16]byte]struct{}
ipv4Conn *ipset.Conn ipv4Conn *ipset.Conn
@ -289,10 +294,14 @@ func (c *ipsetCtx) skipIpsetProcessing(ctx *dnsContext) (ok bool) {
// process adds the resolved IP addresses to the domain's ipsets, if any. // process adds the resolved IP addresses to the domain's ipsets, if any.
func (c *ipsetCtx) process(ctx *dnsContext) (rc resultCode) { func (c *ipsetCtx) process(ctx *dnsContext) (rc resultCode) {
var err error
if c == nil { if c == nil {
return resultCodeSuccess return resultCodeSuccess
} }
log.Debug("ipset: starting processing")
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -308,6 +317,8 @@ func (c *ipsetCtx) process(ctx *dnsContext) (rc resultCode) {
host = strings.ToLower(host) host = strings.ToLower(host)
sets := c.lookupHost(host) sets := c.lookupHost(host)
if len(sets) == 0 { if len(sets) == 0 {
log.Debug("ipset: no ipsets for host %s", host)
return resultCodeSuccess return resultCodeSuccess
} }
@ -342,7 +353,6 @@ func (c *ipsetCtx) process(ctx *dnsContext) (rc resultCode) {
v4s = append(v4s, ip) v4s = append(v4s, ip)
} }
var err error
setLoop: setLoop:
for _, set := range sets { for _, set := range sets {
switch set.family { switch set.family {
@ -363,6 +373,20 @@ setLoop:
} }
if err != nil { if err != nil {
log.Error("ipset: adding host ips: %s", err) log.Error("ipset: adding host ips: %s", err)
} else {
log.Debug("ipset: processed %d new ips", len(v4s)+len(v6s))
}
for _, ip := range v4s {
var iparr [16]byte
copy(iparr[:], ip.To16())
c.addedIPs[iparr] = struct{}{}
}
for _, ip := range v6s {
var iparr [16]byte
copy(iparr[:], ip.To16())
c.addedIPs[iparr] = struct{}{}
} }
return resultCodeSuccess return resultCodeSuccess