Pull request: AGDNS-2848-upd-dnsproxy-doh

Squashed commit of the following:

commit e06d9abfe4de16507d8a87e98b376a241729c010
Merge: 566afb9bf 806855dc1
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Mar 12 08:35:39 2026 +0700

    Merge remote-tracking branch 'origin/master' into AGDNS-2848-upd-dnsproxy-doh

commit 566afb9bf03d282fbe4f150e2db8664c6a0de23b
Merge: 39688da82 354ce04a5
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Mar 11 17:58:44 2026 +0700

    Merge remote-tracking branch 'origin/master' into AGDNS-2848-upd-dnsproxy-doh

commit 39688da82e6f11e1c5e81fd6c0e0f1354bba0970
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Mar 11 08:17:37 2026 +0700

    all: upd dnsproxy

commit 168847c56ceabbf1afdff3ffe0a90102fb53643b
Merge: 7463c0733 a15c72493
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Mar 11 08:09:55 2026 +0700

    Merge remote-tracking branch 'origin/master' into AGDNS-2848-upd-dnsproxy-doh

commit 7463c07339bd6c96ab3d8dd922ee6233aec50a88
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Mar 10 16:32:02 2026 +0700

    all: upd dnsproxy

commit c605ec946588cc2271d2ba83e71986917798c752
Merge: 07da0bbe5 ad9cb3e8d
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Mar 10 08:56:14 2026 +0700

    Merge remote-tracking branch 'origin/master' into AGDNS-2848-upd-dnsproxy-doh

commit 07da0bbe57b3a2836c870d522363f9233ee5dc75
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Mar 9 12:36:11 2026 +0700

    all: imp code

commit bfdf4a4467893ae4b445e8c947e0f60d12675e40
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 6 15:58:20 2026 +0700

    all: upd dnsproxy

commit 097b64b450a2a89b09d8ff066a191fe7122e8de0
Merge: bff075daf 01dd10e49
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 6 12:36:56 2026 +0700

    Merge branch 'master' into AGDNS-2848-upd-dnsproxy-doh
    
    # Conflicts:
    #	go.mod
    #	go.sum
    #	internal/dnsforward/config.go

commit bff075dafbd8dc3482a5cf9d8eb24584713b109b
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 6 12:34:48 2026 +0700

    all: upd dnsproxy

commit 5956d01b0d87a84a6b1155608258dd37949eee4f
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 6 11:59:26 2026 +0700

    all: upd dnsproxy

commit 2e2091e3db9b0309faa476961d136fb1c9bd39e9
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Feb 25 11:31:12 2026 +0700

    all: upd dnsproxy, rm beforerequest

commit 44e5f1207e5201c6527f2f316ceafac2b3593868
Merge: d474280e9 82f2ac68a
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Feb 20 10:38:45 2026 +0700

    Merge remote-tracking branch 'origin/master' into AGDNS-3523-upd-dnsproxy

commit d474280e944ecfab6bfd877089fc7ad79f3ecfed
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Feb 19 20:07:13 2026 +0700

    all: upd dnsproxy

commit b19a7cd851c62fafafed340825e7ad269f5a578a
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Feb 19 13:50:05 2026 +0700

    all: upd dnsproxy

commit 56b67426e0ff804880ac74536f01cdbc4db3605b
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Feb 19 10:06:42 2026 +0700

    all: imp code

commit 716f8186bd5e74152b0677d57a26ca4fc2f991a9
Merge: 96c178bb3 94a3a4fa6
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Feb 19 09:21:49 2026 +0700

    Merge remote-tracking branch 'origin/master' into AGDNS-3523-upd-dnsproxy
    
    # Conflicts:
    #	go.mod
    #	go.sum

commit 96c178bb3d2b6cfcd1cb9377b71c3c23987eab6e
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Feb 17 10:27:27 2026 +0700

    next: dnssvc todos

commit f84834f68f399e6ce841c7c5765f3180acb3c417
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Feb 17 09:11:54 2026 +0700

    all: upd dnsproxy

commit 6ad1a30c087256374882b6e24f5c879121c34834
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Feb 16 13:17:09 2026 +0700

    scripts: fix

commit cc7c6d3181a427f4e79f4af686d3363f5c341001
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Feb 16 13:11:24 2026 +0700

    all: upd golibs

commit cd2662cf6bc52216c9b2ec55ffd34a8ade434170
Merge: d3d2bd6f2 a165cdb68
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Feb 16 11:49:19 2026 +0700

    Merge remote-tracking branch 'refs/remotes/origin/master' into AGDNS-3523-upd-dnsproxy

commit d3d2bd6f27de6b721f73a48e1c4c8e1187d51046
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Feb 6 12:23:43 2026 +0700

    all: todo

commit e16df07e1062e67cc3d085048c4399cf375997bf
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Feb 6 12:06:37 2026 +0700

    dnsforward: upd dnsproxy
This commit is contained in:
Dimitry Kolyshev 2026-03-12 01:41:49 +00:00
parent 806855dc1c
commit 5558089e7b
10 changed files with 188 additions and 153 deletions

2
go.mod
View file

@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome
go 1.25.7
require (
github.com/AdguardTeam/dnsproxy v0.79.0
github.com/AdguardTeam/dnsproxy v0.80.0
github.com/AdguardTeam/golibs v0.35.8
github.com/AdguardTeam/urlfilter v0.23.2
github.com/NYTimes/gziphandler v1.1.1

6
go.sum
View file

@ -4,12 +4,10 @@ cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs=
cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
github.com/AdguardTeam/dnsproxy v0.79.0 h1:wvNTny4u6x95bWGRyyqr1PVkHbYyAhPsv4EvnqVlmf4=
github.com/AdguardTeam/dnsproxy v0.79.0/go.mod h1:gwr+7Dc0e7QddQLC9JLGjL5NSKcqw0ESsNMRI5Q67Ps=
github.com/AdguardTeam/dnsproxy v0.80.0 h1:PttgkZfnAe9itH8vGVhpOTS9FLGZq8A49Qa7l4+/11Q=
github.com/AdguardTeam/dnsproxy v0.80.0/go.mod h1:gwr+7Dc0e7QddQLC9JLGjL5NSKcqw0ESsNMRI5Q67Ps=
github.com/AdguardTeam/golibs v0.35.8 h1:KsyF3SWwj05Ey4GiAWU6FGD9oJTDNMp1ixVdS+Nw50M=
github.com/AdguardTeam/golibs v0.35.8/go.mod h1:kuLQ0yNRTl0Em2FmmXtSri7ZdVT7p62oojyc51RvP38=
github.com/AdguardTeam/urlfilter v0.23.2-0.20260226112426-a60617ec1594 h1:VoT4UKSgRcbIpsCGLuVenMWFFdi1834SUkc9+hp5Ivs=
github.com/AdguardTeam/urlfilter v0.23.2-0.20260226112426-a60617ec1594/go.mod h1:JteAKoeka1Yr2oZ3P94dqYBfPOHWyFaOcu3uZa9Yl+I=
github.com/AdguardTeam/urlfilter v0.23.2 h1:EiS/PQZO/X2S6cduFW6BBoRLyjd6SqZj1ZiFbU1KaFE=
github.com/AdguardTeam/urlfilter v0.23.2/go.mod h1:JteAKoeka1Yr2oZ3P94dqYBfPOHWyFaOcu3uZa9Yl+I=
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=

View file

@ -1,127 +0,0 @@
package dnsforward
import (
"context"
"encoding/binary"
"fmt"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/errors"
"github.com/miekg/dns"
)
// type check
var _ proxy.BeforeRequestHandler = (*Server)(nil)
// HandleBefore is the handler that is called before any other processing,
// including logs. It performs access checks and puts the ClientID, if there
// is one, into the server's cache.
//
// TODO(d.kolyshev): Extract to separate package.
func (s *Server) HandleBefore(
_ *proxy.Proxy,
pctx *proxy.DNSContext,
) (err error) {
// TODO(f.setrakov): Obtain context from arguments.
ctx := context.TODO()
clientID, err := s.clientIDFromDNSContext(ctx, pctx)
if err != nil {
return &proxy.BeforeRequestError{
Err: fmt.Errorf("getting clientid: %w", err),
Response: s.NewMsgSERVFAIL(pctx.Req),
}
}
blocked, _ := s.IsBlockedClient(pctx.Addr.Addr(), clientID)
if blocked {
return s.preBlockedResponse(pctx)
}
if len(pctx.Req.Question) == 1 {
q := pctx.Req.Question[0]
qt := q.Qtype
host := aghnet.NormalizeDomain(q.Name)
if s.access.isBlockedHost(host, qt) {
// TODO(s.chzhen): Pass context.
s.logger.DebugContext(
context.TODO(),
"request is in access blocklist",
"dns_type", dns.Type(qt),
"host", host,
)
return s.preBlockedResponse(pctx)
}
}
if clientID != "" {
key := [8]byte{}
binary.BigEndian.PutUint64(key[:], pctx.RequestID)
s.clientIDCache.Set(key[:], []byte(clientID))
}
return nil
}
// clientIDFromDNSContext extracts the client's ID from the server name of the
// client's DoT or DoQ request or the path of the client's DoH. If the protocol
// is not one of these, clientID is an empty string and err is nil.
func (s *Server) clientIDFromDNSContext(
ctx context.Context,
pctx *proxy.DNSContext,
) (clientID string, err error) {
proto := pctx.Proto
if proto == proxy.ProtoHTTPS {
clientID, err = clientIDFromDNSContextHTTPS(pctx)
if err != nil {
return "", fmt.Errorf("checking url: %w", err)
} else if clientID != "" {
return clientID, nil
}
// Go on and check the domain name as well.
} else if proto != proxy.ProtoTLS && proto != proxy.ProtoQUIC {
return "", nil
}
hostSrvName := s.conf.TLSConf.ServerName
if hostSrvName == "" {
return "", nil
}
cliSrvName, err := clientServerName(ctx, s.logger, pctx, proto)
if err != nil {
return "", fmt.Errorf("getting client server-name: %w", err)
}
clientID, err = clientIDFromClientServerName(
hostSrvName,
cliSrvName,
s.conf.TLSConf.StrictSNICheck,
)
if err != nil {
return "", fmt.Errorf("clientid check: %w", err)
}
return clientID, nil
}
// errAccessBlocked is a sentinel error returned when a request is blocked by
// access settings.
var errAccessBlocked errors.Error = "blocked by access settings"
// preBlockedResponse returns a protocol-appropriate response for a request that
// was blocked by access settings.
func (s *Server) preBlockedResponse(pctx *proxy.DNSContext) (err error) {
if pctx.Proto == proxy.ProtoUDP || pctx.Proto == proxy.ProtoDNSCrypt {
// Return nil so that dnsproxy drops the connection and thus
// prevent DNS amplification attacks.
return errAccessBlocked
}
return &proxy.BeforeRequestError{
Err: errAccessBlocked,
Response: s.makeResponseREFUSED(pctx.Req),
}
}

View file

@ -205,7 +205,7 @@ type TLSConfig struct {
// HTTPSListenAddrs should be the addresses AdGuard Home is listening on for
// DoH connections. These addresses are announced with DDR. Each item in
// the list must be non-nil.
HTTPSListenAddrs []*net.TCPAddr
HTTPSListenAddrs []netip.AddrPort
// ServerName is the hostname of the server. Currently, it is only being
// used for ClientID checking and Discovery of Designated Resolvers (DDR).
@ -322,6 +322,8 @@ const (
)
// newProxyConfig creates and validates configuration for the main proxy.
//
// TODO(d.kolyshev): Improve maintainability.
func (s *Server) newProxyConfig(ctx context.Context) (conf *proxy.Config, err error) {
srvConf := s.conf
trustedPrefixes := netutil.UnembedPrefixes(srvConf.TrustedProxies)
@ -331,9 +333,13 @@ func (s *Server) newProxyConfig(ctx context.Context) (conf *proxy.Config, err er
return nil, fmt.Errorf("ratelimit middleware: %w", err)
}
httpConf := &proxy.HTTPConfig{
ServerHeader: aghhttp.UserAgent(),
InsecureEnabled: s.conf.TLSAllowUnencryptedDoH,
}
conf = &proxy.Config{
Logger: s.baseLogger.With(slogutil.KeyPrefix, aghslog.PrefixDNSProxy),
HTTP3: srvConf.ServeHTTP3,
RefuseAny: srvConf.RefuseAny,
TrustedProxies: netutil.SliceSubnetSet(trustedPrefixes),
CacheMinTTL: srvConf.CacheMinTTL,
@ -343,9 +349,7 @@ func (s *Server) newProxyConfig(ctx context.Context) (conf *proxy.Config, err er
CacheOptimisticMaxAge: time.Duration(srvConf.CacheOptimisticMaxAge),
UpstreamConfig: srvConf.UpstreamConfig,
PrivateRDNSUpstreamConfig: srvConf.PrivateRDNSUpstreamConfig,
BeforeRequestHandler: s,
RequestHandler: ratelimitMw.Wrap(s),
HTTPSServerName: aghhttp.UserAgent(),
RequestHandler: ratelimitMw.Wrap(s.Wrap(s)),
EnableEDNSClientSubnet: srvConf.EDNSClientSubnet.Enabled,
MaxGoroutines: srvConf.MaxGoroutines,
UseDNS64: srvConf.UseDNS64,
@ -356,6 +360,7 @@ func (s *Server) newProxyConfig(ctx context.Context) (conf *proxy.Config, err er
PendingRequests: &proxy.PendingRequestsConfig{
Enabled: srvConf.PendingRequestsEnabled,
},
HTTPConfig: httpConf,
}
if srvConf.EDNSClientSubnet.UseCustom {
@ -798,7 +803,7 @@ func (s *Server) preparePlain(ctx context.Context, proxyConf *proxy.Config) (err
lenEncrypted := len(proxyConf.DNSCryptTCPListenAddr) +
len(proxyConf.DNSCryptUDPListenAddr) +
len(proxyConf.HTTPSListenAddr) +
len(proxyConf.HTTPConfig.ListenAddresses) +
len(proxyConf.QUICListenAddr) +
len(proxyConf.TLSListenAddr)
if lenEncrypted == 0 {

View file

@ -0,0 +1,137 @@
package dnsforward
import (
"context"
"encoding/binary"
"fmt"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/miekg/dns"
)
// type check
var _ proxy.Middleware = (*Server)(nil)
// Wrap implements the [proxy.Middleware] interface for *Server.
//
// TODO(d.kolyshev): Move to a dedicated package.
func (s *Server) Wrap(h proxy.Handler) (wrapped proxy.Handler) {
f := func(p *proxy.Proxy, pctx *proxy.DNSContext) (err error) {
// TODO(f.setrakov): Obtain context from arguments.
ctx := context.TODO()
clientID, err := s.clientIDFromDNSContext(ctx, pctx)
if err != nil {
s.logger.WarnContext(ctx, "resolving client id", slogutil.KeyError, err)
pctx.Res = s.NewMsgSERVFAIL(pctx.Req)
pctx.Res.Compress = true
return nil
}
blocked, _ := s.IsBlockedClient(pctx.Addr.Addr(), clientID)
if blocked {
return s.serveBlockedResponse(pctx)
}
blocked = s.isBlockedHost(ctx, pctx.Req.Question)
if blocked {
return s.serveBlockedResponse(pctx)
}
if clientID != "" {
key := [8]byte{}
binary.BigEndian.PutUint64(key[:], pctx.RequestID)
s.clientIDCache.Set(key[:], []byte(clientID))
}
return h.ServeDNS(p, pctx)
}
return proxy.HandlerFunc(f)
}
// serveBlockedResponse sets a protocol-appropriate response for a request that
// was blocked by access settings.
func (s *Server) serveBlockedResponse(pctx *proxy.DNSContext) (err error) {
if pctx.Proto == proxy.ProtoUDP || pctx.Proto == proxy.ProtoDNSCrypt {
// Return nil so that dnsproxy drops the connection and thus prevent DNS
// amplification attacks.
return proxy.ErrDrop
}
pctx.Res = s.makeResponseREFUSED(pctx.Req)
pctx.Res.Compress = true
return nil
}
// isBlockedHost checks if the request is in the access blocklist.
func (s *Server) isBlockedHost(ctx context.Context, question []dns.Question) (blocked bool) {
if len(question) != 1 {
return false
}
q := question[0]
qt := q.Qtype
host := aghnet.NormalizeDomain(q.Name)
if s.access.isBlockedHost(host, qt) {
s.logger.DebugContext(
ctx,
"request is in access blocklist",
"dns_type", dns.Type(qt),
"host", host,
)
return true
}
return false
}
// clientIDFromDNSContext extracts the client's ID from the server name of the
// client's DoT or DoQ request or the path of the client's DoH. If the protocol
// is not one of these, clientID is an empty string and err is nil.
func (s *Server) clientIDFromDNSContext(
ctx context.Context,
pctx *proxy.DNSContext,
) (clientID string, err error) {
proto := pctx.Proto
if proto == proxy.ProtoHTTPS {
clientID, err = clientIDFromDNSContextHTTPS(pctx)
if err != nil {
return "", fmt.Errorf("checking url: %w", err)
} else if clientID != "" {
return clientID, nil
}
// Go on and check the domain name as well.
} else if proto != proxy.ProtoTLS && proto != proxy.ProtoQUIC {
return "", nil
}
hostSrvName := s.conf.TLSConf.ServerName
if hostSrvName == "" {
return "", nil
}
cliSrvName, err := clientServerName(ctx, s.logger, pctx, proto)
if err != nil {
return "", fmt.Errorf("getting client server-name: %w", err)
}
clientID, err = clientIDFromClientServerName(
hostSrvName,
cliSrvName,
s.conf.TLSConf.StrictSNICheck,
)
if err != nil {
return "", fmt.Errorf("clientid check: %w", err)
}
return clientID, nil
}

View file

@ -15,13 +15,15 @@ import (
"github.com/stretchr/testify/require"
)
// Common constants for tests.
const (
blockedHost = "blockedhost.org"
testFQDN = "example.org."
blockedHost = "blockedhost.org"
testFQDN = "example.org."
dnsClientTimeout = 200 * time.Millisecond
)
func TestServer_HandleBefore_tls(t *testing.T) {
func TestServer_middlewareTLS(t *testing.T) {
t.Parallel()
const clientID = "client-1"
@ -165,7 +167,7 @@ func TestServer_HandleBefore_tls(t *testing.T) {
}
}
func TestServer_HandleBefore_udp(t *testing.T) {
func TestServer_middlewareUDP(t *testing.T) {
t.Parallel()
const (

View file

@ -201,7 +201,7 @@ func (s *Server) makeDDRResponse(req *dns.Msg) (resp *dns.Msg) {
for _, addr := range s.conf.TLSConf.HTTPSListenAddrs {
values := []dns.SVCBKeyValue{
&dns.SVCBAlpn{Alpn: []string{"h2"}},
&dns.SVCBPort{Port: uint16(addr.Port)},
&dns.SVCBPort{Port: addr.Port()},
&dns.SVCBDoHPath{Template: "/dns-query{?dns}"},
}

View file

@ -244,12 +244,16 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
},
}
addrsDoH := []netip.AddrPort{netip.AddrPortFrom(netutil.IPv4Localhost(), 8044)}
addrsDoT := []*net.TCPAddr{{Port: 8043}}
addrsDoQ := []*net.UDPAddr{{Port: 8042}}
testCases := []struct {
name string
host string
want []*dns.SVCB
wantRes resultCode
addrsDoH []*net.TCPAddr
addrsDoH []netip.AddrPort
addrsDoT []*net.TCPAddr
addrsDoQ []*net.UDPAddr
qtype uint16
@ -260,14 +264,14 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
host: testQuestionTarget,
qtype: dns.TypeSVCB,
ddrEnabled: true,
addrsDoH: []*net.TCPAddr{{Port: 8043}},
addrsDoH: addrsDoH,
}, {
name: "pass_qtype",
wantRes: resultCodeFinish,
host: ddrHostFQDN,
qtype: dns.TypeA,
ddrEnabled: true,
addrsDoH: []*net.TCPAddr{{Port: 8043}},
addrsDoH: addrsDoH,
}, {
name: "pass_disabled_tls",
wantRes: resultCodeFinish,
@ -280,7 +284,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
host: ddrHostFQDN,
qtype: dns.TypeSVCB,
ddrEnabled: false,
addrsDoH: []*net.TCPAddr{{Port: 8043}},
addrsDoH: addrsDoH,
}, {
name: "dot",
wantRes: resultCodeFinish,
@ -288,7 +292,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
host: ddrHostFQDN,
qtype: dns.TypeSVCB,
ddrEnabled: true,
addrsDoT: []*net.TCPAddr{{Port: 8043}},
addrsDoT: addrsDoT,
}, {
name: "doh",
wantRes: resultCodeFinish,
@ -296,7 +300,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
host: ddrHostFQDN,
qtype: dns.TypeSVCB,
ddrEnabled: true,
addrsDoH: []*net.TCPAddr{{Port: 8044}},
addrsDoH: addrsDoH,
}, {
name: "doq",
wantRes: resultCodeFinish,
@ -304,7 +308,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
host: ddrHostFQDN,
qtype: dns.TypeSVCB,
ddrEnabled: true,
addrsDoQ: []*net.UDPAddr{{Port: 8042}},
addrsDoQ: addrsDoQ,
}, {
name: "dot_doh",
wantRes: resultCodeFinish,
@ -312,8 +316,8 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
host: ddrHostFQDN,
qtype: dns.TypeSVCB,
ddrEnabled: true,
addrsDoT: []*net.TCPAddr{{Port: 8043}},
addrsDoH: []*net.TCPAddr{{Port: 8044}},
addrsDoT: addrsDoT,
addrsDoH: addrsDoH,
}}
_, certPem, keyPem := createServerTLSConfig(t)

View file

@ -222,6 +222,21 @@ func ipsToTCPAddrs(ips []netip.Addr, port uint16) (tcpAddrs []*net.TCPAddr) {
return tcpAddrs
}
// ipsToAddrPorts converts a slice of [netip.Addr] into a slice of
// [netip.AddrPort] with the given port.
func ipsToAddrPorts(ips []netip.Addr, port uint16) (addrs []netip.AddrPort) {
if ips == nil {
return nil
}
addrs = make([]netip.AddrPort, 0, len(ips))
for _, ip := range ips {
addrs = append(addrs, netip.AddrPortFrom(ip, port))
}
return addrs
}
func ipsToUDPAddrs(ips []netip.Addr, port uint16) (udpAddrs []*net.UDPAddr) {
if ips == nil {
return nil
@ -323,7 +338,7 @@ func newDNSTLSConfig(
}
if conf.PortHTTPS != 0 {
dnsConf.HTTPSListenAddrs = ipsToTCPAddrs(addrs, conf.PortHTTPS)
dnsConf.HTTPSListenAddrs = ipsToAddrPorts(addrs, conf.PortHTTPS)
}
if conf.PortDNSOverTLS != 0 {

View file

@ -635,6 +635,7 @@ func TestTLSManager_HandleTLSConfigure(t *testing.T) {
res := &tlsConfig{
tlsConfigStatus: &tlsConfigStatus{},
}
err = json.NewDecoder(w.Body).Decode(res)
require.NoError(t, err)