Merge in DNS/adguard-home from AGDNS-2714-tls-config to master Squashed commit of the following: commit 073e5ec367db02690e9527602a1da6bfd29321a0 Merge: 18f38c9d44d258972dAuthor: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Apr 16 18:25:23 2025 +0300 Merge branch 'master' into AGDNS-2714-tls-config commit 18f38c9d44337752c6d0f09142658f374de0979f Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Fri Apr 11 15:02:00 2025 +0300 dnsforward: imp docs commit ed56d3c2bc239bdc9af000d847721c4c43d173a3 Merge: 3ef281ea21cc6c00e4Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Thu Apr 10 17:25:08 2025 +0300 Merge branch 'master' into AGDNS-2714-tls-config commit 3ef281ea28dc1fcab0a1291fb3221e6324077a10 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Thu Apr 10 17:24:29 2025 +0300 all: imp docs commit b75f2874a816d4814d218c3b062d532f02e26ca5 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Mon Apr 7 17:16:59 2025 +0300 dnsforward: imp code commit 8ab17b96bca957a172062faaa23b72d5c7ed4d0d Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Fri Apr 4 21:26:37 2025 +0300 all: imp code commit 1abce97b50fe0406dd1ec85b96a0f99b633325cc Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Apr 2 18:22:15 2025 +0300 home: imp code commit debf710f4ebbdfe3e4d2f15b1adcf6b86f8dfc0d Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Apr 1 14:52:21 2025 +0300 home: imp code commit 4aa26f15b721f2a3f32da29b3f664a02bc5a8608 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Tue Apr 1 14:16:16 2025 +0300 all: imp code commit 1a3e72f7a1276f9f797caf9b615f8a552cc9e988 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Mon Mar 31 21:22:40 2025 +0300 all: imp code commit 776ab824aef18ea27b59c02ebfc8620c715a867e Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Thu Mar 27 14:00:33 2025 +0300 home: tls config mu commit 9ebf912f530181043df5c583e82291484996429a Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Wed Mar 26 18:58:47 2025 +0300 all: tls config
117 lines
3.1 KiB
Go
117 lines
3.1 KiB
Go
package dnsforward
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
|
|
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
|
"github.com/AdguardTeam/dnsproxy/proxy"
|
|
"github.com/AdguardTeam/golibs/errors"
|
|
"github.com/AdguardTeam/golibs/log"
|
|
"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) {
|
|
clientID, err := s.clientIDFromDNSContext(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) {
|
|
log.Debug("access: request %s %s is in access blocklist", dns.Type(qt), 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(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(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),
|
|
}
|
|
}
|