{"id":381,"date":"2020-07-09T10:47:59","date_gmt":"2020-07-09T00:47:59","guid":{"rendered":"https:\/\/www.ubermotive.com\/?p=381"},"modified":"2022-06-21T22:14:21","modified_gmt":"2022-06-21T12:14:21","slug":"configuring-a-dual-stacked-ubuntu-router-on-aussie-broadband-nbn","status":"publish","type":"post","link":"https:\/\/www.ubermotive.com\/?p=381","title":{"rendered":"Configuring a Dual-Stacked Ubuntu Router on Aussie Broadband NBN"},"content":{"rendered":"\n<p>The NBN connection that was scheduled to arrive on my street in 2013 finally arrived last week. IPv4 worked straight out of the box, but IPv6 took considerably longer to get working. This is mostly caused by shortcomings in netplan (Ubuntu&#8217;s new network config renderer introduced in 18.04) and ISC DHCP Server when combined with ABB&#8217;s DHCPv6-PD system. My router is running Ubuntu 20.04, which doesn&#8217;t appear to be any different.<\/p>\n\n\n\n<p>Even though Aussie Broadband provide you with a somewhat-fixed \/48 prefix delegation, it will drop all traffic unless that prefix is currently leased through DHCPv6-PD. You must request it from DHCPv6, not statically define it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sign up to the IPv6 Beta<\/h2>\n\n\n\n<p><br>Firstly, IPv6 is opt-in. You can opt into the IPv6 beta <a rel=\"noreferrer noopener\" href=\"https:\/\/www.aussiebroadband.com.au\/help-centre\/nbn\/tech-support\/ipv6\/\" target=\"_blank\">here<\/a>. You will be assigned two addresses. One is an IA-NA (a single \/128 address from a \/64 block for the router), the other is an IA-PD (\/48 prefix delegation to use on your network).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configure Network Interfaces with Netplan<\/h2>\n\n\n\n<p>Here&#8217;s how to set up <code>\/etc\/netplan\/01-netcfg.yaml<\/code> for the LAN interface. Ensure that &#8220;fdxx:xxxx&#8221; is changed to a suitable ULA prefix. I use ULAs as it provides a guaranteed static IP for internal services which cannot leak to the outside internet. It provides a failover for the local network when the internet is down. Subtitute the MAC address of the LAN interface.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># This file describes the network interfaces available on your system\n# For more information, see netplan(5).\nnetwork:\n  version: 2\n  renderer: networkd\n  ethernets:\n    enp1s0f0:\n      match:\n        macaddress: xx:xx:xx:xx:xx:xx\n      addresses: [\"fdxx:xxxx::1\/64\", 192.168.1.1\/24]\n      dhcp4: false\n      dhcp6: false\n      accept-ra: false\n      set-name: lan<\/pre>\n\n\n\n<p>Here&#8217;s how to set up <code>\/etc\/netplan\/02-wancfg.yaml<\/code> for the WAN interface. Again, set the correct MAC address.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># This file describes the network interfaces available on your system\n# For more information, see netplan(5).\nnetwork:\n  version: 2\n  renderer: networkd\n  ethernets:\n    enp1s0f2:\n      match:\n        macaddress: xx:xx:xx:xx:xx:xx\n      dhcp4: true\n      dhcp6: false\n      accept-ra: false\n      set-name: wan<\/pre>\n\n\n\n<p>You will notice that <code>dhcp6<\/code> and <code>accept-ra<\/code> are disabled. This is intentional, as enabling either of these will invoke ISC dhcp client for IPv6, which prevents the <code>wide-dhcp6-client<\/code> service from functioning.<br>Run <code>sudo netplan generate<\/code> when done. This will render a network config that will be applied the next time the system boots.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Allow DHCPv6 through the firewall<\/h2>\n\n\n\n<p>DHCPv6 communicates through UDP port 546. Traffic on this port must be explicitly allowed in order to receive an address allocation through DHCPv6.<br><br>Add the following line to <code>\/etc\/iptables\/rules.v6<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">-A INPUT -d fe80::\/64 -i wan -p udp -m state --state NEW -m udp --dport 546 -j ACCEPT<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Enable forwarding and router advertisements<\/h2>\n\n\n\n<p>Uncomment the following line in <code>\/etc\/sysctl.conf<\/code> to enable forwarding:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">net.ipv6.conf.all.forwarding=1<\/pre>\n\n\n\n<p>Because enabling forwarding disables router advertisements (RA), it must be manually enabled on the WAN interface. Because netplan needs accept-ra set to &#8216;false&#8217; to prevent ISC from blocking the interface, we need to enable it through <code>\/etc\/rc.local<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#!\/bin\/sh -e\n\n#Enable router advertisements on WAN\nsysctl -w net.ipv6.conf.wan.accept_ra=2\nsysctl -p\n\nexit 0<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Install WIDE DHCPv6 Client<\/h2>\n\n\n\n<p>Install the <code>wide-dhcpv6-client<\/code> apt package, then modify <code>\/etc\/wide-dhcpv6\/dhcp6c.conf<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># Default dhpc6c configuration: it assumes the address is autoconfigured using \n# router advertisements.\nprofile default\n{\n  information-only;\n  request domain-name-servers;\n  request domain-name;\n  script \"\/etc\/wide-dhcpv6\/dhcp6c-script\";\n};\ninterface wan {\n  send ia-na 1;\n  send ia-pd 0;\n};\nid-assoc na 1 {\n};\nid-assoc pd 0 {\n  prefix-interface lan {\n    sla-id 1;\n    sla-len 16;\n  };\n};<\/pre>\n\n\n\n<p>This enables both IA-NA and IA-PD (something netplan + ISC <a rel=\"noreferrer noopener\" href=\"https:\/\/bugs.launchpad.net\/netplan\/+bug\/1771886\" target=\"_blank\">cannot do right now<\/a>). The &#8220;sla-id 1&#8221; will assign the second \/64 prefix to the LAN interface. We&#8217;re saving the first \/64 (sla-id 0) for the WAN interface. &#8220;sla-len&#8221; is set to 16 because we&#8217;re allocating a \/64 from a \/48 prefix (16 bits difference).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">RADVD Configuration<\/h2>\n\n\n\n<p>RADVD provides router advertisements to your local network. You must use the same prefix assigned to your LAN interface by wide-dhcp6-client (sla-id 01), hence the &#8220;01&#8221; at the end of the prefix.<\/p>\n\n\n\n<p>Here is <code>\/etc\/radvd.conf<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">interface lan\n{\n  AdvSendAdvert on;\n  AdvOtherConfigFlag on;\n  prefix fd<strong>xx<\/strong>:<strong>xxxx<\/strong>::\/64\n  {\n    AdvOnLink on;\n    AdvAutonomous on;\n  };\n  prefix 2403:58<strong>xx<\/strong>:<strong>xxxx<\/strong>:01::\/64\n  {\n    AdvOnLink on;\n    AdvAutonomous on;\n  };\n  RDNSS fd<strong>xx<\/strong>:<strong>xxxx<\/strong>::1 { };\n};<\/pre>\n\n\n\n<p>Only add the RDNSS line if you are running a local DNS server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Final steps<\/h2>\n\n\n\n<p>This should be enough for the router to provide IPv6 to your network. Reboot the router and see how it works. However, the \/128 address assigned to the router doesn&#8217;t appear to give the router itself IPv6 access. You need to give it an IP address from within your assigned \/48 delegated prefix.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo ip addr add 2403:58xx:xxxx::1\/64 dev wan<\/pre>\n\n\n\n<p>Unfortunately, it appears you need to do this manually <em>after<\/em> the interface has come up, which means this is a manual process to be done on each boot. I&#8217;ll update here if I find a reliable way to trigger it automatically.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Debugging<\/h2>\n\n\n\n<p>If things go wrong, it&#8217;s necessary to see what DHCPv6 is doing.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo tcpdump -i wan -vv -n port 546<\/pre>\n\n\n\n<p>Run this command from one terminal and run <code>sudo service wide-dhcpv6-client restart<\/code> from another. I&#8217;ve found ABB&#8217;s DHCP server will respond with UnspecFail quite a lot, and when this happens, I find it&#8217;s necessary to reboot everything, including the modem. It&#8217;s also worth checking that you have a default route:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>$ ip -6 route | grep default<\/strong>\ndefault via fe80::2a2:ff:feb2:c2 dev wan proto ra metric 1024 expires 1702sec hoplimit 64 pref high<\/pre>\n\n\n\n<p>If you don&#8217;t have a default route, chances are that <code>net.ipv6.conf.wan.accept_ra<\/code> is not set to &#8216;2&#8217;. The default route is only configured if RAs are accepted by the interface. Lastly, make sure you have an actual \/128 on the WAN, \/64 global IP addresses on the WAN and LAN interfaces:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>$ ip addr show lan<\/strong>\n2: lan: mtu 1500 qdisc mq state UP group default qlen 1000\n    link\/ether a0:36:9f:71:f1:58 brd ff:ff:ff:ff:ff:ff\n    inet 192.168.1.1\/24 brd 192.168.1.255 scope global lan\n       valid_lft forever preferred_lft forever\n    inet6 2403:58xx:xxxx:xx01:xxxx:xxxx:xxxx:xxxx<strong>\/64<\/strong> scope global\n    valid_lft forever preferred_lft forever\n    inet6 fdxx:xxxx::1\/64 scope global\n       valid_lft forever preferred_lft forever\n    inet6 fe80::a236:9fff:fe71:f158\/64 scope link\n       valid_lft forever preferred_lft forever\n\n<strong>$ ip addr show wan<\/strong>\n3: wan: mtu 1500 qdisc mq state UP group default qlen 1000\n    link\/ether a0:36:9f:71:f1:5a brd ff:ff:ff:ff:ff:ff\n    inet 119.18.xxx.xxx\/22 brd 119.18.27.255 scope global dynamic wan\n       valid_lft 1235sec preferred_lft 1235sec\n    inet6 2403:58xx:xxxx:xx00::1<strong>\/64<\/strong> scope global\n       valid_lft forever preferred_lft forever\n    inet6 2403:58xx:xxxx:xx:xxxx:xxxx:xxxx:xxxx<strong>\/128<\/strong> scope global\n       valid_lft forever preferred_lft forever\n    inet6 fe80::a236:9fff:fe71:f15a\/64 scope link\n       valid_lft forever preferred_lft forever<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The NBN connection that was scheduled to arrive on my street in 2013 finally arrived last week. IPv4 worked straight out of the box, but IPv6 took considerably longer to get working. This is mostly caused by shortcomings in netplan (Ubuntu&#8217;s new network config renderer introduced in 18.04) and ISC DHCP Server when combined with [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-381","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=\/wp\/v2\/posts\/381","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=381"}],"version-history":[{"count":15,"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=\/wp\/v2\/posts\/381\/revisions"}],"predecessor-version":[{"id":449,"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=\/wp\/v2\/posts\/381\/revisions\/449"}],"wp:attachment":[{"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ubermotive.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}