Keep the DNS interception hooks installed when the firewall is disabled

This commit is contained in:
Viktor Liu
2026-09-09 11:14:35 +02:00
parent d2e62e358a
commit 6c8e0764b8
5 changed files with 89 additions and 6 deletions
+3 -3
View File
@@ -68,11 +68,11 @@ func NewFirewall(iface IFaceMapper, stateManager *statemanager.Manager, flowLogg
case err == nil && !iface.IsUserspaceBind():
// Nothing to do, fall through
case err == nil && iface.IsUserspaceBind():
// Native firewall handles packet filtering, but the userspace WireGuard bind
// Native firewall handles packet filtering, but the userspace bind
// needs a device filter for DNS interception hooks. Install a minimal
// hooks-only filter that passes all traffic through to the kernel firewall.
if err := iface.SetFilter(&uspfilter.HooksFilter{}); err != nil {
log.Warnf("failed to set hooks filter, DNS via memory hooks will not work: %v", err)
if err := InstallDNSHooksFilter(iface); err != nil {
log.Errorf("failed to set hooks filter, DNS via memory hooks will not work: %v", err)
}
case err != nil && !iface.IsUserspaceBind():
// Kernel cannot fall back to anything else, need to return error
+21
View File
@@ -0,0 +1,21 @@
package firewall
import (
"github.com/netbirdio/netbird/client/firewall/uspfilter"
)
// InstallDNSHooksFilter installs a device filter that carries nothing but the
// DNS interception hooks, for setups that run no firewall manager. The
// in-process resolver receives queries through hooks on the interface's device
// filter, so without a filter it never sees a query; the filter passes all
// other traffic through untouched.
//
// It is a no-op when the interface has no device filter to install on, which
// is the case for a kernel bind.
func InstallDNSHooksFilter(iface IFaceMapper) error {
if !iface.IsUserspaceBind() {
return nil
}
return iface.SetFilter(&uspfilter.HooksFilter{})
}
+4 -3
View File
@@ -21,9 +21,10 @@ const (
)
// HooksFilter is a minimal packet filter that only handles outbound DNS hooks.
// It is installed on the WireGuard interface when the userspace bind is active
// but a full firewall filter (Manager) is not needed because a native kernel
// firewall (nftables/iptables) handles packet filtering.
// It is installed on the interface when the userspace bind is active but a full
// filter (Manager) is not: either because a native kernel firewall
// (nftables/iptables) handles packet filtering, or because no firewall manager
// runs at all.
type HooksFilter struct {
udpHook atomic.Pointer[common.PacketHook]
tcpHook atomic.Pointer[common.PacketHook]