Skip to content

Commit

Permalink
Merge branch 'master' into 6312-client-ipv6-zone
Browse files Browse the repository at this point in the history
  • Loading branch information
schzhn committed Apr 24, 2024
2 parents 58d2fd9 + 856cc40 commit bd9146e
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ NOTE: Add new changes BELOW THIS COMMENT.

- Support for link-local subnets, i.e. `fe80::/16`, as client identifiers
([#6312]).
- Issues with QUIC and HTTP/3 upstreams on older Linux kernel versions
([#6422]).
- YouTube restricted mode is not enforced by HTTPS queries on Firefox.
- Support for link-local subnets, i.e. `fe80::/16`, in the access settings
([#6192]).
Expand All @@ -52,6 +54,7 @@ NOTE: Add new changes BELOW THIS COMMENT.
[#5812]: https://github.com/AdguardTeam/AdGuardHome/issues/5812
[#6192]: https://github.com/AdguardTeam/AdGuardHome/issues/6192
[#6312]: https://github.com/AdguardTeam/AdGuardHome/issues/6312
[#6422]: https://github.com/AdguardTeam/AdGuardHome/issues/6422
[#6854]: https://github.com/AdguardTeam/AdGuardHome/issues/6854
[#6875]: https://github.com/AdguardTeam/AdGuardHome/issues/6875
[#6882]: https://github.com/AdguardTeam/AdGuardHome/issues/6882
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module github.com/AdguardTeam/AdGuardHome
go 1.22.2

require (
github.com/AdguardTeam/dnsproxy v0.70.0
// TODO(a.garipov): Use a tagged version once released.
github.com/AdguardTeam/dnsproxy v0.70.1-0.20240424112457-69feed2dd25e
github.com/AdguardTeam/golibs v0.23.2
github.com/AdguardTeam/urlfilter v0.18.0
github.com/NYTimes/gziphandler v1.1.1
Expand All @@ -28,7 +29,8 @@ require (
// own code for that. Perhaps, use gopacket.
github.com/mdlayher/raw v0.1.0
github.com/miekg/dns v1.1.58
github.com/quic-go/quic-go v0.42.0
// TODO(a.garipov): Use a tagged version once released.
github.com/quic-go/quic-go v0.42.1-0.20240424132812-713525777535
github.com/stretchr/testify v1.9.0
github.com/ti-mo/netfilter v0.5.1
go.etcd.io/bbolt v1.3.9
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/AdguardTeam/dnsproxy v0.70.0 h1:lwPQ+pfyCuorrP6RS90K628bRn8uvvTlnRyQuLKnf2o=
github.com/AdguardTeam/dnsproxy v0.70.0/go.mod h1:zpA9eBxakSyjKC/bUac+UPSYTp/Q43aOmNlBV2/D6ug=
github.com/AdguardTeam/dnsproxy v0.70.1-0.20240424112457-69feed2dd25e h1:ju0wprmCakjAOIuvKrmLU+hUFiStIsreWVk4JWmQPm0=
github.com/AdguardTeam/dnsproxy v0.70.1-0.20240424112457-69feed2dd25e/go.mod h1:eWyFj9zVMdJ4tjHULulfFIXiu6GID/aVvewLVVXLXWE=
github.com/AdguardTeam/golibs v0.23.2 h1:rMjYantwtQ39e8G4zBQ6ZLlm4s3XH30Bc9VxhoOHwao=
github.com/AdguardTeam/golibs v0.23.2/go.mod h1:o9i55Sx6v7qogRQeqaBfmLbC/pZqeMBWi015U5PTDY0=
github.com/AdguardTeam/urlfilter v0.18.0 h1:ZZzwODC/ADpjJSODxySrrUnt/fvOCfGFaCW6j+wsGfQ=
Expand Down Expand Up @@ -101,8 +101,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/quic-go/quic-go v0.42.1-0.20240424132812-713525777535 h1:63/XLGwhqZUU0L4DPWihJH9tyqwmvfaxNPjU9I/Av/M=
github.com/quic-go/quic-go v0.42.1-0.20240424132812-713525777535/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
github.com/shirou/gopsutil/v3 v3.23.7/go.mod h1:c4gnmoRC0hQuaLqvxnx1//VXQ0Ms/X9UnJF8pddY5z4=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
Expand Down
2 changes: 1 addition & 1 deletion internal/dnsforward/beforerequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var _ proxy.BeforeRequestHandler = (*Server)(nil)
// including logs. It performs access checks and puts the client ID, if there
// is one, into the server's cache.
//
// TODO(e.burkov): Write tests.
// TODO(d.kolyshev): Extract to separate package.
func (s *Server) HandleBefore(
_ *proxy.Proxy,
pctx *proxy.DNSContext,
Expand Down
299 changes: 299 additions & 0 deletions internal/dnsforward/beforerequest_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
package dnsforward

import (
"crypto/tls"
"net"
"testing"
"time"

"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const (
blockedHost = "blockedhost.org"
testFQDN = "example.org."
dnsClientTimeout = 200 * time.Millisecond
)

func TestServer_HandleBefore_tls(t *testing.T) {
t.Parallel()

const clientID = "client-1"

testCases := []struct {
clientSrvName string
name string
host string
allowedClients []string
disallowedClients []string
blockedHosts []string
wantRCode int
}{{
clientSrvName: tlsServerName,
name: "allow_all",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{},
wantRCode: dns.RcodeSuccess,
}, {
clientSrvName: "%" + "." + tlsServerName,
name: "invalid_client_id",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{},
wantRCode: dns.RcodeServerFailure,
}, {
clientSrvName: clientID + "." + tlsServerName,
name: "allowed_client_allowed",
host: testFQDN,
allowedClients: []string{clientID},
disallowedClients: []string{},
blockedHosts: []string{},
wantRCode: dns.RcodeSuccess,
}, {
clientSrvName: "client-2." + tlsServerName,
name: "allowed_client_rejected",
host: testFQDN,
allowedClients: []string{clientID},
disallowedClients: []string{},
blockedHosts: []string{},
wantRCode: dns.RcodeRefused,
}, {
clientSrvName: tlsServerName,
name: "disallowed_client_allowed",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{clientID},
blockedHosts: []string{},
wantRCode: dns.RcodeSuccess,
}, {
clientSrvName: clientID + "." + tlsServerName,
name: "disallowed_client_rejected",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{clientID},
blockedHosts: []string{},
wantRCode: dns.RcodeRefused,
}, {
clientSrvName: tlsServerName,
name: "blocked_hosts_allowed",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{blockedHost},
wantRCode: dns.RcodeSuccess,
}, {
clientSrvName: tlsServerName,
name: "blocked_hosts_rejected",
host: dns.Fqdn(blockedHost),
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{blockedHost},
wantRCode: dns.RcodeRefused,
}}

localAns := []dns.RR{&dns.A{
Hdr: dns.RR_Header{
Name: testFQDN,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 3600,
Rdlength: 4,
},
A: net.IP{1, 2, 3, 4},
}}
localUpsHdlr := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) {
resp := (&dns.Msg{}).SetReply(req)
resp.Answer = localAns

require.NoError(t, w.WriteMsg(resp))
})
localUpsAddr := aghtest.StartLocalhostUpstream(t, localUpsHdlr).String()

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

s, _ := createTestTLS(t, TLSConfig{
TLSListenAddrs: []*net.TCPAddr{{}},
ServerName: tlsServerName,
})

s.conf.UpstreamDNS = []string{localUpsAddr}

s.conf.AllowedClients = tc.allowedClients
s.conf.DisallowedClients = tc.disallowedClients
s.conf.BlockedHosts = tc.blockedHosts

err := s.Prepare(&s.conf)
require.NoError(t, err)

startDeferStop(t, s)

tlsConfig := &tls.Config{
InsecureSkipVerify: true,
ServerName: tc.clientSrvName,
}

client := &dns.Client{
Net: "tcp-tls",
TLSConfig: tlsConfig,
Timeout: dnsClientTimeout,
}

req := createTestMessage(tc.host)
addr := s.dnsProxy.Addr(proxy.ProtoTLS).String()

reply, _, err := client.Exchange(req, addr)
require.NoError(t, err)

assert.Equal(t, tc.wantRCode, reply.Rcode)
if tc.wantRCode == dns.RcodeSuccess {
assert.Equal(t, localAns, reply.Answer)
} else {
assert.Empty(t, reply.Answer)
}
})
}
}

func TestServer_HandleBefore_udp(t *testing.T) {
t.Parallel()

const (
clientIPv4 = "127.0.0.1"
clientIPv6 = "::1"
)

clientIPs := []string{clientIPv4, clientIPv6}

testCases := []struct {
name string
host string
allowedClients []string
disallowedClients []string
blockedHosts []string
wantTimeout bool
}{{
name: "allow_all",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{},
wantTimeout: false,
}, {
name: "allowed_client_allowed",
host: testFQDN,
allowedClients: clientIPs,
disallowedClients: []string{},
blockedHosts: []string{},
wantTimeout: false,
}, {
name: "allowed_client_rejected",
host: testFQDN,
allowedClients: []string{"1:2:3::4"},
disallowedClients: []string{},
blockedHosts: []string{},
wantTimeout: true,
}, {
name: "disallowed_client_allowed",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{"1:2:3::4"},
blockedHosts: []string{},
wantTimeout: false,
}, {
name: "disallowed_client_rejected",
host: testFQDN,
allowedClients: []string{},
disallowedClients: clientIPs,
blockedHosts: []string{},
wantTimeout: true,
}, {
name: "blocked_hosts_allowed",
host: testFQDN,
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{blockedHost},
wantTimeout: false,
}, {
name: "blocked_hosts_rejected",
host: dns.Fqdn(blockedHost),
allowedClients: []string{},
disallowedClients: []string{},
blockedHosts: []string{blockedHost},
wantTimeout: true,
}}

localAns := []dns.RR{&dns.A{
Hdr: dns.RR_Header{
Name: testFQDN,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 3600,
Rdlength: 4,
},
A: net.IP{1, 2, 3, 4},
}}
localUpsHdlr := dns.HandlerFunc(func(w dns.ResponseWriter, req *dns.Msg) {
resp := (&dns.Msg{}).SetReply(req)
resp.Answer = localAns

require.NoError(t, w.WriteMsg(resp))
})
localUpsAddr := aghtest.StartLocalhostUpstream(t, localUpsHdlr).String()

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

s := createTestServer(t, &filtering.Config{
BlockingMode: filtering.BlockingModeDefault,
}, ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
Config: Config{
AllowedClients: tc.allowedClients,
DisallowedClients: tc.disallowedClients,
BlockedHosts: tc.blockedHosts,
UpstreamDNS: []string{localUpsAddr},
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
},
ServePlainDNS: true,
})

startDeferStop(t, s)

client := &dns.Client{
Net: "udp",
Timeout: dnsClientTimeout,
}

req := createTestMessage(tc.host)
addr := s.dnsProxy.Addr(proxy.ProtoUDP).String()

reply, _, err := client.Exchange(req, addr)
if tc.wantTimeout {
wantErr := &net.OpError{}
require.ErrorAs(t, err, &wantErr)
assert.True(t, wantErr.Timeout())

assert.Nil(t, reply)
} else {
require.NoError(t, err)
require.NotNil(t, reply)

assert.Equal(t, dns.RcodeSuccess, reply.Rcode)
assert.Equal(t, localAns, reply.Answer)
}
})
}
}

0 comments on commit bd9146e

Please sign in to comment.