Configuring IPv6 on EdgeRouter for Fiber7 and PiHole


Problem statement

Since I need properly functioning IPv6 at home1 to play with VPP, I decided to set it up yesterday.

I have a firm grasp of IPv4 configuration. But only a basic understanding of all the mechanisms in IPv6. So those are my notes on how to get it up on an EdgeRouter2. With the DNS server pointed to my PiHole server.

Background

My ports are:

I will only focus on WAN + LAN in this article.

The road (to a solution)

I started with stapelberg@’s Configuring a Ubiquiti EdgeRouter Lite (Erlite-3) for Fiber7:

configure
set interfaces ethernet eth0 dhcpv6-pd pd 0 prefix-length /48
set interfaces ethernet eth0 dhcpv6-pd pd 0 interface eth1 service slaac
set interfaces ethernet eth0 dhcpv6-pd pd 0 interface eth1 prefix-id :0
commit
save
exit

but that brought several problems:

  1. the LAN IP (last 64 bits) were autoconfigured
  2. there is no firewall on inbound
  3. DNS server announced was what my provider offers (RDNSS 2001:1620:2777:1::10 2001:1620:2777:2::20 { AdvRDNSSLifetime 30; })

So my next iterations are to fix the problems. One by one.

Lan IP

Turns out, that’s a one-liner:

#configure
set interfaces ethernet eth0 dhcpv6-pd pd 0 interface eth1 host-address ::1
#commit
#save
#exit

which (together with prefix-id) fixes the eth1 (gateway) address as ${ispprefix}:0::1.

Rapid commit

During investigation of the various config options I have also found out that “rapid commit3 is a thing. So why not:

#configure
set interfaces ethernet eth0 dhcpv6-pd rapid-commit enable
#commit
#save
#exit

Firewall on inbound

I’m molded by the pervasive IPv4 NAT. So the thought that any random “rust” in our home network would be immediately accessible from outside is not thrilling.

Unfortunately the EdgeRouter UI doesn’t support any IPv6 firewall manipulation.

So I have to take the matter into my hands; shamelessly stolen from Bradley Heilbrun’s IPv6 on the EdgeRouter Lite:

# WAN → LAN
edit firewall ipv6-name WAN6_IN
set default-action drop

set rule 10 action accept
set rule 10 description "allow established"
set rule 10 protocol all
set rule 10 state established enable
set rule 10 state related enable

set rule 20 action drop
set rule 20 description "drop invalid packets"
set rule 20 protocol all
set rule 20 state invalid enable

set rule 30 action accept
set rule 30 description "allow ICMPv6"
set rule 30 protocol icmpv6

top

# WAN → local
edit firewall ipv6-name WAN6_LOCAL
set default-action drop

set rule 10 action accept
set rule 10 description "allow established"
set rule 10 protocol all
set rule 10 state established enable
set rule 10 state related enable

set rule 20 action drop
set rule 20 description "drop invalid packets"
set rule 20 protocol all
set rule 20 state invalid enable

set rule 30 action accept
set rule 30 description "allow ICMPv6"
set rule 30 protocol icmpv6

set rule 40 action accept
set rule 40 description "allow DHCPv6 client/server"
set rule 40 destination port 546
set rule 40 source port 547
set rule 40 protocol udp
top

# Hook it up
set interfaces ethernet eth0 firewall in ipv6-name WAN6_IN
set interfaces ethernet eth0 firewall local ipv6-name WAN6_LOCAL

This is rather minimalistic, but a good start.

DNS through PiHole

Originally I thought that just setting the name-server key and disabling DNS in the dhcpv6-pd would be enough:

#configure
edit interfaces ethernet eth1 ipv6 router-advert
set name-server fe80::xxxx:xxxx:xxxx:xxxx
top
set interfaces ethernet eth0 dhcpv6-pd pd 0 interface eth1 no-dns
set interfaces ethernet eth0 dhcpv6-pd no-dns
#commit
#save
#exit

would be enough.

But I was very naïve.

You see, the no-dns under dhcpv6-pd is a good call. But slapping any configuration under router-advert kills off the prefix announcement. So the router adverts worked beautifully, but there was no prefix announced. Therefore no ipv6 for the clients on LAN4.

In the end I found out that one can set prefix ::/64:

#configure
edit interfaces ethernet eth1 ipv6
set prefix ::/64 autonomous-flag true
set prefix ::/64 on-link-flag true
set prefix ::/64 valid-lifetime 1800
top
#commit
#save
#exit

and it works. :-)

For the full blast I actually set it up as:

#configure
edit interfaces ethernet eth1 ipv6 router-advert
set prefix ::/64 autonomous-flag true
set prefix ::/64 on-link-flag true
set prefix ::/64 valid-lifetime 1800
set radvd-options "RDNSS fe80::xxxx:xxxx:xxxx:xxxx { AdvRDNSSLifetime 300; };"
set min-interval 3
set max-interval 10
set default-lifetime 1800
set reachable-time 0
set retrans-timer 0
set send-advert true
top
#commit
#save
#exit

In the process I learned that EdgeRouters use radvd for the announcements. And that radvdump is an awesome commandline utility to debug the announcements. :)

Also, careful readers will notice I’m using a link-local address for the PiHole. That’s because I find the whole idea of binding it to an address which has its prefix fetched via DHCP iffy. If you know a better way, I’m all ears.

Solution

In the end, I’m left with:

configure

# DHCP w/ prefix delegation + no dns
edit interfaces ethernet eth0 dhcpv6-pd
set rapid-commit enable
set pd 0 prefix-length /48
set pd 0 interface eth1 service slaac
set pd 0 interface eth1 prefix-id :0
set pd 0 interface eth1 host-address ::1
set pd 0 interface eth1 no-dns
set no-dns
top

# Proper announcements
edit interfaces ethernet eth1 ipv6 router-advert
set prefix ::/64 autonomous-flag true
set prefix ::/64 on-link-flag true
set prefix ::/64 valid-lifetime 1800
set radvd-options "RDNSS fe80::xxxx:xxxx:xxxx:xxxx { AdvRDNSSLifetime 300; };"
set min-interval 3
set max-interval 10
set default-lifetime 1800
set reachable-time 0
set retrans-timer 0
set send-advert true
top

# Firewall (rather basic one)
## WAN → LAN
edit firewall ipv6-name WAN6_IN
set default-action drop

set rule 10 action accept
set rule 10 description "allow established"
set rule 10 protocol all
set rule 10 state established enable
set rule 10 state related enable

set rule 20 action drop
set rule 20 description "drop invalid packets"
set rule 20 protocol all
set rule 20 state invalid enable

set rule 30 action accept
set rule 30 description "allow ICMPv6"
set rule 30 protocol icmpv6

top

## WAN → local
edit firewall ipv6-name WAN6_LOCAL
set default-action drop

set rule 10 action accept
set rule 10 description "allow established"
set rule 10 protocol all
set rule 10 state established enable
set rule 10 state related enable

set rule 20 action drop
set rule 20 description "drop invalid packets"
set rule 20 protocol all
set rule 20 state invalid enable

set rule 30 action accept
set rule 30 description "allow ICMPv6"
set rule 30 protocol icmpv6

set rule 40 action accept
set rule 40 description "allow DHCPv6 client/server"
set rule 40 destination port 546
set rule 40 source port 547
set rule 40 protocol udp
top

## Hook it up
set interfaces ethernet eth0 firewall in ipv6-name WAN6_IN
set interfaces ethernet eth0 firewall local ipv6-name WAN6_LOCAL

# Out
commit
save
exit

Closing words

I would wager that hardly any of this will be surprising to someone with IPv6 experience.

For me – configuring IPv6 by hand up until now – it was different.

What mystifies me is why EdgeRouters don’t use dnsmasq for the router announcements, too. Searching around with fresh eyes, I discovered Setting up IPv6 using dhcpv6-pd/slaac with dnsmasq post that shows a way to configure it. But that’s a bit too much of a hack to my taste.

I hope this all becomes fully obsolete when I replace it with a VPP-based setup. Stay tuned?

  1. For the first time in forever, actually.

  2. And yes, these guides are dime a dozen. In fact, this one links several of them. And also: this one is mine. My preciousssssss.

  3. A 2-message (solicit, reply) DHCPv6 exchange instead of the 4-message (solicit, advertise, request, reply) DHCPv6 exchange.

  4. And I’m saying it rather nonchalantly here. But it took me a sweet long while to figure out. In the end radvdump – and manually comparing the announcements from Fiber7 with the ones from our LAN – helped.