all: imp client resolving

This commit is contained in:
Ainar Garipov
2023-07-13 18:18:49 +03:00
parent f22d893845
commit 9f93a21bf6
9 changed files with 221 additions and 164 deletions

View File

@@ -17,10 +17,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
"github.com/AdguardTeam/AdGuardHome/internal/rdns"
"github.com/AdguardTeam/AdGuardHome/internal/stats"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
@@ -154,134 +151,32 @@ func initDNSServer(
Context.clients.dnsServer = Context.dnsServer
dnsConf, err := generateServerConfig(tlsConf, httpReg)
dnsConf, err := newServerConfig(tlsConf, httpReg)
if err != nil {
closeDNSServer()
return fmt.Errorf("generateServerConfig: %w", err)
return fmt.Errorf("newServerConfig: %w", err)
}
err = Context.dnsServer.Prepare(&dnsConf)
err = Context.dnsServer.Prepare(dnsConf)
if err != nil {
closeDNSServer()
return fmt.Errorf("dnsServer.Prepare: %w", err)
}
initRDNS()
initWHOIS()
clientIPs := dnsConf.ClientIPs
addrProc := newClientAddrProcessor(config.Clients.Sources)
go addrProc.process(clientIPs)
const topClientsNumber = 100
for _, ip := range Context.stats.TopClientsIP(topClientsNumber) {
clientIPs <- ip
}
return nil
}
const (
// defaultQueueSize is the size of queue of IPs for rDNS and WHOIS
// processing.
defaultQueueSize = 255
// defaultCacheSize is the maximum size of the cache for rDNS and WHOIS
// processing. It must be greater than zero.
defaultCacheSize = 10_000
// defaultIPTTL is the Time to Live duration for IP addresses cached by
// rDNS and WHOIS.
defaultIPTTL = 1 * time.Hour
)
// initRDNS initializes the rDNS.
func initRDNS() {
Context.rdnsCh = make(chan netip.Addr, defaultQueueSize)
// TODO(s.chzhen): Add ability to disable it on dns server configuration
// update in [dnsforward] package.
r := rdns.New(&rdns.Config{
Exchanger: Context.dnsServer,
CacheSize: defaultCacheSize,
CacheTTL: defaultIPTTL,
})
go processRDNS(r)
}
// processRDNS processes reverse DNS lookup queries. It is intended to be used
// as a goroutine.
func processRDNS(r rdns.Interface) {
defer log.OnPanic("rdns")
for ip := range Context.rdnsCh {
ok := Context.dnsServer.ShouldResolveClient(ip)
if !ok {
continue
}
host, changed := r.Process(ip)
if host == "" || !changed {
continue
}
ok = Context.clients.AddHost(ip, host, ClientSourceRDNS)
if ok {
continue
}
log.Debug(
"dns: can't set rdns info for client %q: already set with higher priority source",
ip,
)
}
}
// initWHOIS initializes the WHOIS.
//
// TODO(s.chzhen): Consider making configurable.
func initWHOIS() {
const (
// defaultTimeout is the timeout for WHOIS requests.
defaultTimeout = 5 * time.Second
// defaultMaxConnReadSize is an upper limit in bytes for reading from
// net.Conn.
defaultMaxConnReadSize = 64 * 1024
// defaultMaxRedirects is the maximum redirects count.
defaultMaxRedirects = 5
// defaultMaxInfoLen is the maximum length of whois.Info fields.
defaultMaxInfoLen = 250
)
Context.whoisCh = make(chan netip.Addr, defaultQueueSize)
var w whois.Interface
if config.Clients.Sources.WHOIS {
w = whois.New(&whois.Config{
DialContext: customDialContext,
ServerAddr: whois.DefaultServer,
Port: whois.DefaultPort,
Timeout: defaultTimeout,
CacheSize: defaultCacheSize,
MaxConnReadSize: defaultMaxConnReadSize,
MaxRedirects: defaultMaxRedirects,
MaxInfoLen: defaultMaxInfoLen,
CacheTTL: defaultIPTTL,
})
} else {
w = whois.Empty{}
}
go func() {
defer log.OnPanic("whois")
for ip := range Context.whoisCh {
info, changed := w.Process(context.Background(), ip)
if info != nil && changed {
Context.clients.setWHOISInfo(ip, info)
}
}
}()
}
// parseSubnetSet parses a slice of subnets. If the slice is empty, it returns
// a subnet set that matches all locally served networks, see
// [netutil.IsLocallyServed].
@@ -312,17 +207,6 @@ func isRunning() bool {
return Context.dnsServer != nil && Context.dnsServer.IsRunning()
}
func onDNSRequest(pctx *proxy.DNSContext) {
ip := netutil.NetAddrToAddrPort(pctx.Addr).Addr()
if ip == (netip.Addr{}) {
// This would be quite weird if we get here.
return
}
Context.rdnsCh <- ip
Context.whoisCh <- ip
}
func ipsToTCPAddrs(ips []netip.Addr, port int) (tcpAddrs []*net.TCPAddr) {
if ips == nil {
return nil
@@ -349,19 +233,20 @@ func ipsToUDPAddrs(ips []netip.Addr, port int) (udpAddrs []*net.UDPAddr) {
return udpAddrs
}
func generateServerConfig(
func newServerConfig(
tlsConf *tlsConfigSettings,
httpReg aghhttp.RegisterFunc,
) (newConf dnsforward.ServerConfig, err error) {
) (newConf *dnsforward.ServerConfig, err error) {
dnsConf := config.DNS
hosts := aghalg.CoalesceSlice(dnsConf.BindHosts, []netip.Addr{netutil.IPv4Localhost()})
newConf = dnsforward.ServerConfig{
clientIPs := make(chan netip.Addr, defaultQueueSize)
newConf = &dnsforward.ServerConfig{
UDPListenAddrs: ipsToUDPAddrs(hosts, dnsConf.Port),
TCPListenAddrs: ipsToTCPAddrs(hosts, dnsConf.Port),
FilteringConfig: dnsConf.FilteringConfig,
ConfigModified: onConfigModified,
HTTPRegister: httpReg,
OnDNSRequest: onDNSRequest,
ClientIPs: clientIPs,
UseDNS64: config.DNS.UseDNS64,
DNS64Prefixes: config.DNS.DNS64Prefixes,
}
@@ -385,9 +270,9 @@ func generateServerConfig(
if tlsConf.PortDNSCrypt != 0 {
newConf.DNSCryptConfig, err = newDNSCrypt(hosts, *tlsConf)
if err != nil {
// Don't wrap the error, because it's already
// wrapped by newDNSCrypt.
return dnsforward.ServerConfig{}, err
// Don't wrap the error, because it's already wrapped by
// newDNSCrypt.
return nil, err
}
}
}
@@ -556,31 +441,26 @@ func startDNSServer() error {
Context.stats.Start()
Context.queryLog.Start()
const topClientsNumber = 100 // the number of clients to get
for _, ip := range Context.stats.TopClientsIP(topClientsNumber) {
Context.rdnsCh <- ip
Context.whoisCh <- ip
}
return nil
}
func reconfigureDNSServer() (err error) {
var newConf dnsforward.ServerConfig
tlsConf := &tlsConfigSettings{}
Context.tls.WriteDiskConfig(tlsConf)
newConf, err = generateServerConfig(tlsConf, httpRegister)
newConf, err := newServerConfig(tlsConf, httpRegister)
if err != nil {
return fmt.Errorf("generating forwarding dns server config: %w", err)
}
err = Context.dnsServer.Reconfigure(&newConf)
err = Context.dnsServer.Reconfigure(newConf)
if err != nil {
return fmt.Errorf("starting forwarding dns server: %w", err)
}
addrProc := newClientAddrProcessor(config.Clients.Sources)
go addrProc.process(newConf.ClientIPs)
return nil
}