]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dns-delegates: add support for setting a firewall mark
authorr-vdp <ramses@well-founded.dev>
Thu, 12 Feb 2026 21:52:54 +0000 (23:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 16 Feb 2026 10:09:48 +0000 (11:09 +0100)
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.

man/systemd.dns-delegate.xml
src/resolve/resolved-dns-delegate-gperf.gperf
src/resolve/resolved-dns-delegate.h
src/resolve/resolved-dns-scope.c
test/units/TEST-75-RESOLVED.sh

index a06ccad529a255d5675ef011b0dfd5e81e109cca..0ef36d2bf5db6f80b2c0a73652571b763fc3aa45 100644 (file)
             <xi:include href="version-info.xml" xpointer="v258"/>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>FirewallMark=</varname></term>
+          <listitem>
+            <para>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 <constant>SO_MARK</constant> socket option. See <citerefentry
+            project='die-net'><refentrytitle>iptables</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
+            details.</para>
+            <xi:include href="version-info.xml" xpointer="v260"/>
+          </listitem>
+        </varlistentry>
       </variablelist>
 
   </refsect1>
       <programlisting># /etc/systemd/dns-delegate.d/foobar.dns-delegate
 [Delegate]
 DNS=203.0.113.47
-Domains=foobar.com</programlisting>
+Domains=foobar.com
+FirewallMark=42</programlisting>
 
       <para>This ensures lookups of <literal>foobar.com</literal> and any domains below it are directed to
-      DNS server 203.0.113.47.</para>
+      DNS server 203.0.113.47 and any packets related to this lookup have a firewall mark set to 42.</para>
     </example>
   </refsect1>
 
index 3040770f3ade6a292359f3c03949ce0a8fb2c21f..27dfe4336639a1d6c1071037a7586d890af52993 100644 (file)
@@ -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)
index dfb8429de21c6b8e4238e73e4116152fd129a49a..5ec070db37dfd0e48b38db82aad1ba380d3d4029 100644 (file)
@@ -23,6 +23,8 @@ typedef struct DnsDelegate {
 
         int default_route;
 
+        uint32_t fwmark;
+
         DnsScope *scope;
 
         LIST_FIELDS(DnsDelegate, delegates);
index c6c6bdc86695002398a9d618ab6850aba9221d7d..8fe0a8bc5f01adb9ee70b763f08decdfc1da971e 100644 (file)
@@ -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;
index e6ef9214a3a4c21b85b48aa1a40cbf465de5ee35..b3656da94043adc8fc457ae098a9a1eaf091adaa 100755 (executable)
@@ -1452,6 +1452,7 @@ testcase_delegate() {
 [Delegate]
 DNS=192.168.77.78
 Domains=exercise.test
+FirewallMark=42
 EOF
     systemctl reload systemd-resolved
     resolvectl status