Resolve conflict
This commit is contained in:
@@ -122,7 +122,7 @@ func (a *accessCtx) IsBlockedIP(ip string) bool {
|
||||
// IsBlockedDomain - return TRUE if this domain should be blocked
|
||||
func (a *accessCtx) IsBlockedDomain(host string) bool {
|
||||
a.lock.Lock()
|
||||
_, ok := a.blockedHostsEngine.Match(host, nil)
|
||||
_, ok := a.blockedHostsEngine.Match(host)
|
||||
a.lock.Unlock()
|
||||
return ok
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/dnsfilter"
|
||||
"github.com/AdguardTeam/AdGuardHome/querylog"
|
||||
"github.com/AdguardTeam/AdGuardHome/stats"
|
||||
@@ -43,11 +44,15 @@ var webRegistered bool
|
||||
//
|
||||
// The zero Server is empty and ready for use.
|
||||
type Server struct {
|
||||
dnsProxy *proxy.Proxy // DNS proxy instance
|
||||
dnsFilter *dnsfilter.Dnsfilter // DNS filter instance
|
||||
queryLog querylog.QueryLog // Query log instance
|
||||
stats stats.Stats
|
||||
access *accessCtx
|
||||
dnsProxy *proxy.Proxy // DNS proxy instance
|
||||
dnsFilter *dnsfilter.Dnsfilter // DNS filter instance
|
||||
dhcpServer *dhcpd.Server // DHCP server instance (optional)
|
||||
queryLog querylog.QueryLog // Query log instance
|
||||
stats stats.Stats
|
||||
access *accessCtx
|
||||
|
||||
tablePTR map[string]string // "IP -> hostname" table for reverse lookup
|
||||
tablePTRLock sync.Mutex
|
||||
|
||||
// DNS proxy instance for internal usage
|
||||
// We don't Start() it and so no listen port is required.
|
||||
@@ -59,13 +64,27 @@ type Server struct {
|
||||
conf ServerConfig
|
||||
}
|
||||
|
||||
// DNSCreateParams - parameters for NewServer()
|
||||
type DNSCreateParams struct {
|
||||
DNSFilter *dnsfilter.Dnsfilter
|
||||
Stats stats.Stats
|
||||
QueryLog querylog.QueryLog
|
||||
DHCPServer *dhcpd.Server
|
||||
}
|
||||
|
||||
// NewServer creates a new instance of the dnsforward.Server
|
||||
// Note: this function must be called only once
|
||||
func NewServer(dnsFilter *dnsfilter.Dnsfilter, stats stats.Stats, queryLog querylog.QueryLog) *Server {
|
||||
func NewServer(p DNSCreateParams) *Server {
|
||||
s := &Server{}
|
||||
s.dnsFilter = dnsFilter
|
||||
s.stats = stats
|
||||
s.queryLog = queryLog
|
||||
s.dnsFilter = p.DNSFilter
|
||||
s.stats = p.Stats
|
||||
s.queryLog = p.QueryLog
|
||||
s.dhcpServer = p.DHCPServer
|
||||
|
||||
if s.dhcpServer != nil {
|
||||
s.dhcpServer.SetOnLeaseChanged(s.onDHCPLeaseChanged)
|
||||
s.onDHCPLeaseChanged(dhcpd.LeaseChangedAdded)
|
||||
}
|
||||
|
||||
if runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" {
|
||||
// Use plain DNS on MIPS, encryption is too slow
|
||||
|
||||
@@ -426,6 +426,11 @@ func checkDNS(input string, bootstrap []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Control flow:
|
||||
// web
|
||||
// -> dnsforward.handleDOH -> dnsforward.ServeHTTP
|
||||
// -> proxy.ServeHTTP -> proxy.handleDNSRequest
|
||||
// -> dnsforward.handleDNSRequest
|
||||
func (s *Server) handleDOH(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.conf.TLSAllowUnencryptedDOH && r.TLS == nil {
|
||||
httpError(r, w, http.StatusNotFound, "Not Found")
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/dnsfilter"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
@@ -496,7 +497,7 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||
c := dnsfilter.Config{}
|
||||
|
||||
f := dnsfilter.New(&c, filters)
|
||||
s := NewServer(f, nil, nil)
|
||||
s := NewServer(DNSCreateParams{DNSFilter: f})
|
||||
conf := ServerConfig{}
|
||||
conf.UDPListenAddr = &net.UDPAddr{Port: 0}
|
||||
conf.TCPListenAddr = &net.TCPAddr{Port: 0}
|
||||
@@ -648,7 +649,7 @@ func TestRewrite(t *testing.T) {
|
||||
}
|
||||
|
||||
f := dnsfilter.New(&c, nil)
|
||||
s := NewServer(f, nil, nil)
|
||||
s := NewServer(DNSCreateParams{DNSFilter: f})
|
||||
conf := ServerConfig{}
|
||||
conf.UDPListenAddr = &net.UDPAddr{Port: 0}
|
||||
conf.TCPListenAddr = &net.TCPAddr{Port: 0}
|
||||
@@ -705,7 +706,7 @@ func createTestServer(t *testing.T) *Server {
|
||||
c.CacheTime = 30
|
||||
|
||||
f := dnsfilter.New(&c, filters)
|
||||
s := NewServer(f, nil, nil)
|
||||
s := NewServer(DNSCreateParams{DNSFilter: f})
|
||||
s.conf.UDPListenAddr = &net.UDPAddr{Port: 0}
|
||||
s.conf.TCPListenAddr = &net.TCPAddr{Port: 0}
|
||||
s.conf.UpstreamDNS = []string{"8.8.8.8:53", "8.8.4.4:53"}
|
||||
@@ -1012,3 +1013,39 @@ func TestMatchDNSName(t *testing.T) {
|
||||
assert.True(t, !matchDNSName(dnsNames, ""))
|
||||
assert.True(t, !matchDNSName(dnsNames, "*.host2"))
|
||||
}
|
||||
|
||||
func TestPTRResponse(t *testing.T) {
|
||||
dhcp := &dhcpd.Server{}
|
||||
dhcp.IPpool = make(map[[4]byte]net.HardwareAddr)
|
||||
|
||||
c := dnsfilter.Config{}
|
||||
f := dnsfilter.New(&c, nil)
|
||||
s := NewServer(DNSCreateParams{DNSFilter: f, DHCPServer: dhcp})
|
||||
s.conf.UDPListenAddr = &net.UDPAddr{Port: 0}
|
||||
s.conf.TCPListenAddr = &net.TCPAddr{Port: 0}
|
||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||
s.conf.FilteringConfig.ProtectionEnabled = true
|
||||
err := s.Prepare(nil)
|
||||
assert.True(t, err == nil)
|
||||
assert.Nil(t, s.Start())
|
||||
|
||||
l := dhcpd.Lease{}
|
||||
l.IP = net.ParseIP("127.0.0.1").To4()
|
||||
l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa")
|
||||
l.Hostname = "localhost"
|
||||
dhcp.AddStaticLease(l)
|
||||
|
||||
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
||||
req := createTestMessage("1.0.0.127.in-addr.arpa.")
|
||||
req.Question[0].Qtype = dns.TypePTR
|
||||
|
||||
resp, err := dns.Exchange(req, addr.String())
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, len(resp.Answer))
|
||||
assert.Equal(t, dns.TypePTR, resp.Answer[0].Header().Rrtype)
|
||||
assert.Equal(t, "1.0.0.127.in-addr.arpa.", resp.Answer[0].Header().Name)
|
||||
ptr := resp.Answer[0].(*dns.PTR)
|
||||
assert.Equal(t, "localhost.", ptr.Ptr)
|
||||
|
||||
s.Close()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package dnsforward
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/dnsfilter"
|
||||
"github.com/AdguardTeam/AdGuardHome/util"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/miekg/dns"
|
||||
@@ -39,6 +42,7 @@ func (s *Server) handleDNSRequest(_ *proxy.Proxy, d *proxy.DNSContext) error {
|
||||
type modProcessFunc func(ctx *dnsContext) int
|
||||
mods := []modProcessFunc{
|
||||
processInitial,
|
||||
processInternalIPAddrs,
|
||||
processFilteringBeforeRequest,
|
||||
processUpstream,
|
||||
processDNSSECAfterResponse,
|
||||
@@ -88,11 +92,82 @@ func processInitial(ctx *dnsContext) int {
|
||||
return resultDone
|
||||
}
|
||||
|
||||
func (s *Server) onDHCPLeaseChanged(flags int) {
|
||||
switch flags {
|
||||
case dhcpd.LeaseChangedAdded,
|
||||
dhcpd.LeaseChangedAddedStatic,
|
||||
dhcpd.LeaseChangedRemovedStatic:
|
||||
//
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
m := make(map[string]string)
|
||||
ll := s.dhcpServer.Leases(dhcpd.LeasesAll)
|
||||
for _, l := range ll {
|
||||
if len(l.Hostname) == 0 {
|
||||
continue
|
||||
}
|
||||
m[l.IP.String()] = l.Hostname
|
||||
}
|
||||
log.Debug("DNS: added %d PTR entries from DHCP", len(m))
|
||||
s.tablePTRLock.Lock()
|
||||
s.tablePTR = m
|
||||
s.tablePTRLock.Unlock()
|
||||
}
|
||||
|
||||
// Respond to PTR requests if the target IP address is leased by our DHCP server
|
||||
func processInternalIPAddrs(ctx *dnsContext) int {
|
||||
s := ctx.srv
|
||||
req := ctx.proxyCtx.Req
|
||||
if req.Question[0].Qtype != dns.TypePTR {
|
||||
return resultDone
|
||||
}
|
||||
|
||||
arpa := req.Question[0].Name
|
||||
arpa = strings.TrimSuffix(arpa, ".")
|
||||
arpa = strings.ToLower(arpa)
|
||||
ip := util.DNSUnreverseAddr(arpa)
|
||||
if ip == nil {
|
||||
return resultDone
|
||||
}
|
||||
|
||||
s.tablePTRLock.Lock()
|
||||
if s.tablePTR == nil {
|
||||
s.tablePTRLock.Unlock()
|
||||
return resultDone
|
||||
}
|
||||
host, ok := s.tablePTR[ip.String()]
|
||||
s.tablePTRLock.Unlock()
|
||||
if !ok {
|
||||
return resultDone
|
||||
}
|
||||
|
||||
log.Debug("DNS: reverse-lookup: %s -> %s", arpa, host)
|
||||
|
||||
resp := s.makeResponse(req)
|
||||
ptr := &dns.PTR{}
|
||||
ptr.Hdr = dns.RR_Header{
|
||||
Name: req.Question[0].Name,
|
||||
Rrtype: dns.TypePTR,
|
||||
Ttl: s.conf.BlockedResponseTTL,
|
||||
Class: dns.ClassINET,
|
||||
}
|
||||
ptr.Ptr = host + "."
|
||||
resp.Answer = append(resp.Answer, ptr)
|
||||
ctx.proxyCtx.Res = resp
|
||||
return resultDone
|
||||
}
|
||||
|
||||
// Apply filtering logic
|
||||
func processFilteringBeforeRequest(ctx *dnsContext) int {
|
||||
s := ctx.srv
|
||||
d := ctx.proxyCtx
|
||||
|
||||
if d.Res != nil {
|
||||
return resultDone // response is already set - nothing to do
|
||||
}
|
||||
|
||||
s.RLock()
|
||||
// Synchronize access to s.dnsFilter so it won't be suddenly uninitialized while in use.
|
||||
// This could happen after proxy server has been stopped, but its workers are not yet exited.
|
||||
|
||||
@@ -39,6 +39,13 @@ func processQueryLogsAndStats(ctx *dnsContext) int {
|
||||
Elapsed: elapsed,
|
||||
ClientIP: getIP(d.Addr),
|
||||
}
|
||||
|
||||
if d.Proto == "https" {
|
||||
p.ClientProto = "doh"
|
||||
} else if d.Proto == "tls" {
|
||||
p.ClientProto = "dot"
|
||||
}
|
||||
|
||||
if d.Upstream != nil {
|
||||
p.Upstream = d.Upstream.Address()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user