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:
- eth0: WAN (Fiber7 uplink)
- eth1: LAN
- eth2: DMZ
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:
- the LAN IP (last 64 bits) were autoconfigured
- there is no firewall on inbound
- 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 commit”3 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?
-
For the first time in forever, actually. ↩
-
And yes, these guides are dime a dozen. In fact, this one links several of them. And also: this one is mine. My preciousssssss. ↩
-
A 2-message (solicit, reply) DHCPv6 exchange instead of the 4-message (solicit, advertise, request, reply) DHCPv6 exchange. ↩
-
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. ↩