From: r-vdp Date: Thu, 12 Feb 2026 21:52:54 +0000 (+0200) Subject: dns-delegates: add support for setting a firewall mark X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e271497d97acf54bd35fd7f859859b2dac97418e;p=thirdparty%2Fsystemd.git dns-delegates: add support for setting a firewall mark This makes it possible to have DNS requests for certain domains routed differently than normal requests, which is for instance useful when using policy routing to route traffic over a VPN but DNS requests for the VPN endpoint itself, should be routed differently. It doesn't make much sense to configure a firewall mark at the level of a network interface, but at the level of a DNS delegate it can be very useful. --- diff --git a/man/systemd.dns-delegate.xml b/man/systemd.dns-delegate.xml index a06ccad529a..0ef36d2bf5d 100644 --- a/man/systemd.dns-delegate.xml +++ b/man/systemd.dns-delegate.xml @@ -69,6 +69,18 @@ + + FirewallMark= + + Takes a 32 bit unsigned integer value. Controls the firewall mark of packets generated by the + socket used to make DNS requests for this DNS delegate. This can be used in the firewall logic to + filter packets from this socket. + This sets the SO_MARK socket option. See iptables8 for + details. + + + @@ -79,10 +91,11 @@ # /etc/systemd/dns-delegate.d/foobar.dns-delegate [Delegate] DNS=203.0.113.47 -Domains=foobar.com +Domains=foobar.com +FirewallMark=42 This ensures lookups of foobar.com and any domains below it are directed to - DNS server 203.0.113.47. + DNS server 203.0.113.47 and any packets related to this lookup have a firewall mark set to 42. diff --git a/src/resolve/resolved-dns-delegate-gperf.gperf b/src/resolve/resolved-dns-delegate-gperf.gperf index 3040770f3ad..27dfe433663 100644 --- a/src/resolve/resolved-dns-delegate-gperf.gperf +++ b/src/resolve/resolved-dns-delegate-gperf.gperf @@ -21,3 +21,4 @@ struct ConfigPerfItem; Delegate.DNS, config_parse_delegate_dns_servers, 0, 0 Delegate.Domains, config_parse_delegate_domains, 0, 0 Delegate.DefaultRoute, config_parse_tristate, 0, offsetof(DnsDelegate, default_route) +Delegate.FirewallMark, config_parse_unsigned, 0, offsetof(DnsDelegate, fwmark) diff --git a/src/resolve/resolved-dns-delegate.h b/src/resolve/resolved-dns-delegate.h index dfb8429de21..5ec070db37d 100644 --- a/src/resolve/resolved-dns-delegate.h +++ b/src/resolve/resolved-dns-delegate.h @@ -23,6 +23,8 @@ typedef struct DnsDelegate { int default_route; + uint32_t fwmark; + DnsScope *scope; LIST_FIELDS(DnsDelegate, delegates); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index c6c6bdc8669..8fe0a8bc5f0 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -475,6 +475,12 @@ static int dns_scope_socket( return r; } + if (s->delegate && s->delegate->fwmark > 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_MARK, s->delegate->fwmark); + if (r < 0) + return log_debug_errno(r, "Failed to set firewall mark on DNS socket: %m)"); + } + bool addr_is_nonlocal = s->link && !manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) && in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0; diff --git a/test/units/TEST-75-RESOLVED.sh b/test/units/TEST-75-RESOLVED.sh index e6ef9214a3a..b3656da9404 100755 --- a/test/units/TEST-75-RESOLVED.sh +++ b/test/units/TEST-75-RESOLVED.sh @@ -1452,6 +1452,7 @@ testcase_delegate() { [Delegate] DNS=192.168.77.78 Domains=exercise.test +FirewallMark=42 EOF systemctl reload systemd-resolved resolvectl status