{"id":951,"date":"2019-08-25T18:13:58","date_gmt":"2019-08-25T16:13:58","guid":{"rendered":"https:\/\/sven-seeberg.de\/wp\/?p=951"},"modified":"2024-07-31T09:28:32","modified_gmt":"2024-07-31T07:28:32","slug":"debian-router-with-ipv6-prefix-delegation-dmz-and-dynamic-dns","status":"publish","type":"post","link":"https:\/\/sven-seeberg.de\/wp\/?p=951","title":{"rendered":"Debian router with IPv6 prefix delegation, DMZ and dynamic DNS"},"content":{"rendered":"\n<p>Recently, I started to set up a Debian Buster based router with IPv6 prefix delegation and two \/64 subnets. One subnet is used for desktop clients, the other serves as a demilitarized zone (DMZ) for servers. The Debian router is located behind Fritz.Box home router, which serves as the DSL modem and forwards all external ports to the Debian router. Of course, traditional IPv4 with NAT is also configured. I&#8217;m using a dynamic DNS service to access the IPv6 addresses in the DMZ from the Internet. It took me quite some time to figure everything out, therefore I want to share my findings. Of course, this requires that your ISP provides you with more than just one \/64 subnet. My ISP provides a \/56.<\/p>\n\n\n\n<p>The following diagram illustrates the setup, including interface names on the router:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"656\" height=\"356\" src=\"https:\/\/sven-seeberg.de\/wp\/wp-content\/uploads\/2019\/08\/Diagram.jpg\" alt=\"\" class=\"wp-image-953\" srcset=\"https:\/\/sven-seeberg.de\/wp\/wp-content\/uploads\/2019\/08\/Diagram.jpg 656w, https:\/\/sven-seeberg.de\/wp\/wp-content\/uploads\/2019\/08\/Diagram-300x163.jpg 300w\" sizes=\"auto, (max-width: 656px) 100vw, 656px\" \/><\/figure>\n\n\n\n<p>Regarding IPv4, <code>enp1s0<\/code> has the address <code>192.168.0.2\/24<\/code>, <code>enp2s0<\/code> has <code>192.168.1.1\/24<\/code> and <code>enp3s0<\/code> has <code>192.168.2.1\/24<\/code>.<\/p>\n\n\n\n<p>First, I had to enable prefix delegation in my Fritz.Box. Coming from the IPv4 NAT world this was something new.<\/p>\n\n\n\n<p>Now with prefix delegation enabled in the Fritz.Box, the Debian router needs to set these prefixes to its DMZ and client network interfaces (enp2s0, enp3s0). This can be achieved with the WIDE DHCPv6 client. (<a href=\"https:\/\/superuser.com\/questions\/742792\/how-do-i-deploy-ipv6-within-a-lan-using-a-debian-based-router-and-prefix-delegat\">https:\/\/superuser.com\/questions\/742792\/how-do-i-deploy-ipv6-within-a-lan-using-a-debian-based-router-and-prefix-delegat<\/a> was very helpful for me.)<\/p>\n\n\n\n<p>On the router, install it (and all other required packages) with<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>sudo apt install wide-dhcpv6-client dnsmasq iptables-persistent<\/code><\/pre>\n\n\n\n<p>Then edit<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>\/etc\/wide-dhcpv6\/dhcp6c.conf<\/code><\/pre>\n\n\n\n<p>and set its content to<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">profile default\n{\n  information-only;\n  request domain-name-servers;\n  request domain-name;\n  script \"\/etc\/wide-dhcpv6\/dhcp6c-script\";\n};\n\ninterface enp1s0 {\n    send rapid-commit;\n    send ia-na 0;\n    send ia-pd 0;\n};\n\nid-assoc na 0 {\n};\n\nid-assoc pd 0 {\n    prefix ::\/60 infinity;\n    prefix-interface enp2s0 {\n        sla-len 4;\n        sla-id 0;\n        ifid 1;\n    };\n    prefix-interface enp3s0 {\n        sla-len 4;\n        sla-id 1;\n        ifid 1;\n    };\n};<\/pre>\n\n\n\n<p>Also configure the <code>\/etc\/network\/interfaces<\/code> like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">source \/etc\/network\/interfaces.d\/*\n\nauto lo\niface lo inet loopback\n\nallow-hotplug enp1s0\niface enp1s0 inet dhcp\niface enp1s0 inet6 auto\n    # Important to accept delegated prefixes\n    post-up sysctl -w net.ipv6.conf.enp1s0.accept_ra=2\n\nallow-hotplug enp2s0\niface enp2s0 inet static\n    address 192.168.1.1\n    network 192.168.1.0\n    netmask 255.255.255.0\n\nallow-hotplug enp3s0\niface enp3s0 inet static\n     address 192.168.2.1\n     network 192.168.2.0\n     netmask 255.255.255.0<\/pre>\n\n\n\n<p>Now when connecting enp1s0, the delegated prefixes will automatically be set to the internal facing interfaces. The internal interfaces will receive the addresses $PREFIX::1.<\/p>\n\n\n\n<p>Next, I&#8217;m using Dnsmasq on the internal interfaces to provide DNS and IPv6 router advertisements. Add the following lines to the <code>\/etc\/dnsmasq.conf<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># IPv4<br>dhcp-range=192.168.1.50,192.168.1.150,12h<br>dhcp-range=192.168.2.50,192.168.2.150,12h<br># IPv6<br>enable-ra<br>dhcp-range = ::1,constructor:enp2s0,   ra-stateless, ra-names, 4h<br>dhcp-range = ::1,constructor:enp3s0,   ra-stateless, ra-names, 4h<\/pre>\n\n\n\n<p>To manage inbound and outbound traffic between the different network segments. As is common, the green zone only allows outbound traffic, while the DMZ allows inbound traffic to specified hosts. The following configuration demonstrates how to allow inbound IPv6 traffic to specific hosts. The rule can be extended to specific ports as well. To restore Iptables during boot, I&#8217;m using the iptables-persistent package. My <code>\/etc\/iptables\/rules.v4<\/code> and <code>\/etc\/iptables\/rules.v6<\/code> contain the following lines:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># \/etc\/iptables\/rules.v4\n*filter\n:INPUT DROP [0:0]\n:FORWARD DROP [0:0]\n:OUTPUT ACCEPT [81:8253]\n-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n-A INPUT -i enp2s0 -j ACCEPT\n-A INPUT -i enp3s0 -j ACCEPT\n-A INPUT -i lo -j ACCEPT\n-A FORWARD -i enp2s0 -j ACCEPT\n-A FORWARD -i enp3s0 -j ACCEPT\n-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\nCOMMIT\n*nat\n:PREROUTING ACCEPT [44:2803]\n:INPUT ACCEPT [23:1484]\n:POSTROUTING ACCEPT [0:0]\n:OUTPUT ACCEPT [24:1535]\n-A POSTROUTING -o enp1s0 -j MASQUERADE\nCOMMIT<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\"># \/etc\/iptables\/rules.v6\n*filter\n:INPUT DROP [0:0]\n:FORWARD DROP [0:0]\n:OUTPUT ACCEPT [175:15496]\n-A INPUT -p ipv6-icmp -j ACCEPT\n-A INPUT -s fe80::\/10 -j ACCEPT\n-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n-A INPUT -i enp2s0 -j ACCEPT\n-A INPUT -i enp3s0 -j ACCEPT\n-A INPUT -i lo -j ACCEPT\n-A FORWARD -i enp2s0 -j ACCEPT\n-A FORWARD -i enp3s0 -j ACCEPT\n-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n-A FORWARD -d ::2\/::ffff:ffff:ffff:ffff -o enp2s0 -p tcp -j ACCEPT\nCOMMIT<\/pre>\n\n\n\n<p>Notice the rule <code>-A FORWARD -d ::2\/::ffff:ffff:ffff:ffff -o enp2s0 -p tcp -j ACCEPT<\/code>. This allows accessing the host in the DMZ from the internet. Now we need to take care that the server in the DMZ always gets the $PREFIX::3 address. This can be done by setting a token with ip. To do this every time the interface is being activated, for example on boot, add the following lines to the \/etc\/network\/interfaces configuration of the server in the DMZ:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">iface enp0s31f6 inet6 auto\n    pre-up \/sbin\/ip token set ::2 dev enp0s31f6<\/pre>\n\n\n\n<p>To publish the IPv6 address of the server on freedns.afraid.org, I&#8217;m using the following crontab line (replace $TOKEN with your private token):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">* *    * * *   (IP=$(ip -6 a list dev enp0s31f6 | grep global | awk '{print $2}' | sed 's\/\\\/64\/\/') &amp;&amp; wget --no-check-certificate -O - \"https:\/\/freedns.afraid.org\/dynamic\/update.php?$TOKEN&amp;address=$IP\" &gt;&gt; \/tmp\/freedns_$HOSTNAME.log 2&gt;&amp;1)<\/pre>\n\n\n\n<p>I hope I did not forget any important part. Feel free to ping me if your setup according to this post does not work.<\/p>\n\n\n\n<p>Update 2024: some information about nft suffix matches can be found on <a href=\"https:\/\/github.com\/opnsense\/core\/issues\/2544#issuecomment-769811809\">https:\/\/github.com\/opnsense\/core\/issues\/2544#issuecomment-769811809<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, I started to set up a Debian Buster based router with IPv6 prefix delegation and two \/64 subnets. One subnet is used for desktop clients, the other serves as a demilitarized zone (DMZ) for servers. The Debian router is &hellip; <a href=\"https:\/\/sven-seeberg.de\/wp\/?p=951\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,13],"tags":[],"class_list":["post-951","post","type-post","status-publish","format-standard","hentry","category-software","category-ubuntu"],"_links":{"self":[{"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=\/wp\/v2\/posts\/951","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=951"}],"version-history":[{"count":20,"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=\/wp\/v2\/posts\/951\/revisions"}],"predecessor-version":[{"id":1206,"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=\/wp\/v2\/posts\/951\/revisions\/1206"}],"wp:attachment":[{"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=951"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=951"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sven-seeberg.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=951"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}