mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
255 lines
5.9 KiB
Go
255 lines
5.9 KiB
Go
package dnsmsg_test
|
|
|
|
import (
|
|
"net"
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
|
"github.com/AdguardTeam/urlfilter/rules"
|
|
"github.com/miekg/dns"
|
|
"github.com/quic-go/quic-go/http3"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestConstructor_NewAnswerHTTPS_andSVCB(t *testing.T) {
|
|
// Preconditions.
|
|
|
|
msgs := agdtest.NewConstructor(t)
|
|
|
|
req := &dns.Msg{
|
|
Question: []dns.Question{{
|
|
Name: "abcd",
|
|
}},
|
|
}
|
|
|
|
// Constants and helper values.
|
|
|
|
const prio = 32
|
|
|
|
// Helper functions.
|
|
|
|
dnssvcb := func(key, value string) (svcb *rules.DNSSVCB) {
|
|
svcb = &rules.DNSSVCB{
|
|
Target: testFQDN,
|
|
Priority: prio,
|
|
}
|
|
|
|
if key == "" {
|
|
return svcb
|
|
}
|
|
|
|
svcb.Params = map[string]string{
|
|
key: value,
|
|
}
|
|
|
|
return svcb
|
|
}
|
|
|
|
wantsvcb := func(kv dns.SVCBKeyValue) (want *dns.SVCB) {
|
|
want = &dns.SVCB{
|
|
Hdr: dns.RR_Header{
|
|
Name: req.Question[0].Name,
|
|
Rrtype: dns.TypeSVCB,
|
|
Ttl: agdtest.FilteredResponseTTLSec,
|
|
Class: dns.ClassINET,
|
|
},
|
|
Priority: prio,
|
|
Target: testFQDN,
|
|
}
|
|
|
|
if kv != nil {
|
|
want.Value = []dns.SVCBKeyValue{kv}
|
|
}
|
|
|
|
return want
|
|
}
|
|
|
|
// Tests.
|
|
|
|
testCases := []struct {
|
|
svcb *rules.DNSSVCB
|
|
want *dns.SVCB
|
|
name string
|
|
}{{
|
|
svcb: dnssvcb("", ""),
|
|
want: wantsvcb(nil),
|
|
name: "no_params",
|
|
}, {
|
|
svcb: dnssvcb("foo", "bar"),
|
|
want: wantsvcb(nil),
|
|
name: "invalid",
|
|
}, {
|
|
svcb: dnssvcb("alpn", http3.NextProtoH3),
|
|
want: wantsvcb(&dns.SVCBAlpn{Alpn: []string{http3.NextProtoH3}}),
|
|
name: "alpn",
|
|
}, {
|
|
svcb: dnssvcb("dohpath", "/some/url/path"),
|
|
want: wantsvcb(&dns.SVCBDoHPath{Template: "/some/url/path"}),
|
|
name: "dohpath",
|
|
}, {
|
|
svcb: dnssvcb("ech", "AAAA"),
|
|
want: wantsvcb(&dns.SVCBECHConfig{ECH: []byte{0, 0, 0}}),
|
|
name: "ech",
|
|
}, {
|
|
svcb: dnssvcb("ech", "%BAD%"),
|
|
want: wantsvcb(nil),
|
|
name: "ech_invalid",
|
|
}, {
|
|
svcb: dnssvcb("ipv4hint", testIPv4.String()),
|
|
want: wantsvcb(&dns.SVCBIPv4Hint{Hint: []net.IP{net.IP(testIPv4.AsSlice()).To16()}}),
|
|
name: "ipv4hint",
|
|
}, {
|
|
svcb: dnssvcb("ipv4hint", "1.2.3.04"),
|
|
want: wantsvcb(nil),
|
|
name: "ipv4hint_invalid",
|
|
}, {
|
|
svcb: dnssvcb("ipv6hint", testIPv6.String()),
|
|
want: wantsvcb(&dns.SVCBIPv6Hint{Hint: []net.IP{testIPv6.AsSlice()}}),
|
|
name: "ipv6hint",
|
|
}, {
|
|
svcb: dnssvcb("ipv6hint", ":::1"),
|
|
want: wantsvcb(nil),
|
|
name: "ipv6hint_invalid",
|
|
}, {
|
|
svcb: dnssvcb("mandatory", "alpn"),
|
|
want: wantsvcb(&dns.SVCBMandatory{Code: []dns.SVCBKey{dns.SVCB_ALPN}}),
|
|
name: "mandatory",
|
|
}, {
|
|
svcb: dnssvcb("mandatory", "invalid"),
|
|
want: wantsvcb(nil),
|
|
name: "mandatory_invalid",
|
|
}, {
|
|
svcb: dnssvcb("no-default-alpn", ""),
|
|
want: wantsvcb(&dns.SVCBNoDefaultAlpn{}),
|
|
name: "no_default_alpn",
|
|
}, {
|
|
svcb: dnssvcb("port", "8080"),
|
|
want: wantsvcb(&dns.SVCBPort{Port: 8080}),
|
|
name: "port",
|
|
}, {
|
|
svcb: dnssvcb("port", "1005008080"),
|
|
want: wantsvcb(nil),
|
|
name: "bad_port",
|
|
}}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name+"_https", func(t *testing.T) {
|
|
want := &dns.HTTPS{SVCB: *tc.want}
|
|
want.Hdr.Rrtype = dns.TypeHTTPS
|
|
|
|
got := msgs.NewAnswerHTTPS(req, tc.svcb)
|
|
assert.Equal(t, want, got)
|
|
})
|
|
|
|
t.Run(tc.name+"_svcb", func(t *testing.T) {
|
|
got := msgs.NewAnswerSVCB(req, tc.svcb)
|
|
assert.Equal(t, tc.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConstructor_NewDDR(t *testing.T) {
|
|
const (
|
|
port uint16 = 12345
|
|
prio uint16 = 123
|
|
target = "test.target"
|
|
targetFQDN = target + "."
|
|
dohPath = "/dns-query"
|
|
)
|
|
|
|
msgs := agdtest.NewConstructor(t)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
ipv4s []netip.Addr
|
|
ipv6s []netip.Addr
|
|
wantVals []dns.SVCBKeyValue
|
|
proto dnsserver.Protocol
|
|
}{{
|
|
name: "dot",
|
|
ipv4s: nil,
|
|
ipv6s: nil,
|
|
wantVals: []dns.SVCBKeyValue{
|
|
&dns.SVCBAlpn{Alpn: dnsserver.ProtoDoT.ALPN()},
|
|
&dns.SVCBPort{Port: port},
|
|
},
|
|
proto: dnsserver.ProtoDoT,
|
|
}, {
|
|
name: "doq",
|
|
ipv4s: nil,
|
|
ipv6s: nil,
|
|
wantVals: []dns.SVCBKeyValue{
|
|
&dns.SVCBAlpn{Alpn: dnsserver.ProtoDoQ.ALPN()},
|
|
&dns.SVCBPort{Port: port},
|
|
},
|
|
proto: dnsserver.ProtoDoQ,
|
|
}, {
|
|
name: "doh",
|
|
ipv4s: nil,
|
|
ipv6s: nil,
|
|
wantVals: []dns.SVCBKeyValue{
|
|
&dns.SVCBAlpn{Alpn: dnsserver.ProtoDoH.ALPN()},
|
|
&dns.SVCBPort{Port: port},
|
|
&dns.SVCBDoHPath{Template: dohPath},
|
|
},
|
|
proto: dnsserver.ProtoDoH,
|
|
}, {
|
|
name: "dot_ipv4_only",
|
|
ipv4s: []netip.Addr{testIPv4},
|
|
ipv6s: nil,
|
|
wantVals: []dns.SVCBKeyValue{
|
|
&dns.SVCBAlpn{Alpn: dnsserver.ProtoDoT.ALPN()},
|
|
&dns.SVCBPort{Port: port},
|
|
&dns.SVCBIPv4Hint{Hint: []net.IP{testIPv4.AsSlice()}},
|
|
},
|
|
proto: dnsserver.ProtoDoT,
|
|
}, {
|
|
name: "dot_ipv6_only",
|
|
ipv4s: nil,
|
|
ipv6s: []netip.Addr{testIPv6},
|
|
wantVals: []dns.SVCBKeyValue{
|
|
&dns.SVCBAlpn{Alpn: dnsserver.ProtoDoT.ALPN()},
|
|
&dns.SVCBPort{Port: port},
|
|
&dns.SVCBIPv6Hint{Hint: []net.IP{testIPv6.AsSlice()}},
|
|
},
|
|
proto: dnsserver.ProtoDoT,
|
|
}, {
|
|
name: "dot_ipv4_ipv6",
|
|
ipv4s: []netip.Addr{testIPv4},
|
|
ipv6s: []netip.Addr{testIPv6},
|
|
wantVals: []dns.SVCBKeyValue{
|
|
&dns.SVCBAlpn{Alpn: dnsserver.ProtoDoT.ALPN()},
|
|
&dns.SVCBPort{Port: port},
|
|
&dns.SVCBIPv4Hint{Hint: []net.IP{testIPv4.AsSlice()}},
|
|
&dns.SVCBIPv6Hint{Hint: []net.IP{testIPv6.AsSlice()}},
|
|
},
|
|
proto: dnsserver.ProtoDoT,
|
|
}}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
svcb := msgs.NewDDRTemplate(tc.proto, target, dohPath, tc.ipv4s, tc.ipv6s, port, prio)
|
|
require.NotNil(t, svcb)
|
|
|
|
assert.Equal(t, targetFQDN, svcb.Target)
|
|
assert.Equal(t, prio, svcb.Priority)
|
|
assert.Equal(t, uint32(agdtest.FilteredResponseTTLSec), svcb.Hdr.Ttl)
|
|
assert.ElementsMatch(t, tc.wantVals, svcb.Value)
|
|
})
|
|
}
|
|
|
|
for _, unsupProto := range []dnsserver.Protocol{
|
|
dnsserver.ProtoDNS,
|
|
dnsserver.ProtoDNSCrypt,
|
|
} {
|
|
t.Run(unsupProto.String(), func(t *testing.T) {
|
|
assert.Panics(t, func() {
|
|
_ = msgs.NewDDRTemplate(unsupProto, target, "", nil, nil, port, prio)
|
|
})
|
|
})
|
|
}
|
|
}
|