IPv6 on Mikrotik on Starlink
11 June 2023
I’ve just gotten a Starlink satellite internet connection as a temporary stopgap until I get fibre wire in.
My previous ISP didn’t provide native IPv6, so I long played with various tunnels, to various effect; Netflix for example is very much not happy if your IPv4 appears to be in New Zealand but your IPv6 comes out in Sydney. Most recently I was with Route48, which provided an Auckland-based Wireguard tunnel, which was pretty good, but they shut down over spam. Thus, with Starlink having IPv6, I immediately wanted to get it going.
Some starlink setup details:
- I have a rectangular dishy
- I’m not bypassing the router
- I’m wired in with the official ethernet adapter
Some mikrotik setup details:
- RouterOS 7.8 everywhere. I’ll upgrade to 7.9 soon but not today.
- I have a hEX PoE at the “comms centre” of my house, which has the Starlink intake on its
ether1
(PoE in, via a 57V AC/DC adapter) - That powers two wifi APs in the form of two ac²s at either end of the house
- …I’ve promised myself that I’ll get ax²s when fibre arrives, so I can have proper Wifi 6
- (I did have Wifi 6 via an OpenWRT’d Ubiquiti Unify but it was still too dodgy/unconfigurable for my tastes)
Some network details:
- An IPv4 /23 in the 10/8 block, with the upper /24 for DHCP and the lower for statics
- The hEX acts as router with dhcp/dns/ntp. I don’t do queueing so the mips is plenty for that.
- Double NAT for IPv4, because I don’t want starlink to be able to see my network.
- DNS “terminated” at the hEX with DoH for the upstream, again because I don’t want my DNS to be snoopable.
The AP setup is uninteresting save that on the topic of IPv6, I didn’t do anything special but cleared the firewall.
Now, the router setup. Credit where credit is due, I cribbed a bunch of it from:
Interfaces
You should probably already have that or something like it, but just in case:
/interface list
add name=WAN
add name=LAN
/interface list member
add interface=ether1 list=WAN
add interface=ether2 list=LAN
add interface=ether3 list=LAN
add interface=ether4 list=LAN
add interface=ether5 list=LAN
add interface=bridge list=LAN
# Eventually I'll get the fibre intake on the SFP, so:
add interface=sfp1 list=WAN
And the bridge:
/interface bridge port
add bridge=bridge ingress-filtering=no interface=ether2
add bridge=bridge ingress-filtering=no interface=ether3
add bridge=bridge ingress-filtering=no interface=ether4
add bridge=bridge ingress-filtering=no interface=ether5
# I like to put my non-bridged ports in but disabled so it's clear where they're at
add bridge=bridge disabled=yes ingress-filtering=no interface=ether1
add bridge=bridge disabled=yes ingress-filtering=no interface=sfp1
The actual IPv6 config
/ipv6 settings
set disable-ipv6=no forward=yes accept-redirects=no \
accept-router-advertisements=yes max-neighbor-entries=8192
# that little script is just to print the prefix to logs; originally (see tim's thread) it also warns
# on prefix change but Starlink no longer changes prefixes willy nilly so it never occurs. but just in case...
/ipv6 dhcp-client
add interface=ether1 pool-name=starlink rapid-commit=no request=prefix \
script=":log info (\$\"pd-prefix\" . \" DHCP\")\
\n:if (\$oldpd = \$\"pd-prefix\") do={ } else={ :log warning \"different P\
D\" }\
\n:global oldpd \$\"pd-prefix\"\
\n" use-interface-duid=yes
# wait for prefix delegation
:delay 5000ms
# Take ::2 in the pool. Leaving ::1 alone may or may not help.
/ipv6 address
add address=::2 from-pool=starlink interface=bridge
# If no address was added automatically here only:
# Replace 2406:xxxx:xxxx:xxxx with your starlink's address prefix
# again we take ::2; in this case ::1 is nominally the starlink's
add address=2406:xxxx:xxxx:xxxx::2 advertise=no interface=ether1
# This was the critical bit for me.
# Other guides insist routing is automatic, but it wasn't in my case. YKMV.
/ipv6 route
add disabled=no distance=1 dst-address=2000::/3 gateway=\
[/ipv6/dhcp-client get value-name=dhcp-server-v6 number=ether1] \
routing-table=main scope=30 target-scope=10
/ipv6 nd prefix default
set preferred-lifetime=10m valid-lifetime=15m
/ipv6 nd
set [ find default=yes ] disabled=yes
add advertise-dns=no advertise-mac-address=no interface=ether1 ra-lifetime=none
# if you're not doing DNS on mikrotik, you'll want to change/remove `dns` here
add dns=[<your address on bridge>] hop-limit=64 interface=bridge \
managed-address-configuration=yes mtu=1280 other-configuration=yes \
ra-interval=3m20s-8m20s
v6 Firewall
This is basically copied from tyd.
First, some address lists:
/ipv6 firewall address-list
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
add address=::1/128 comment="defconf: lo" list=bad_ipv6
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
add address=fe80::/10 list=prefix_delegation
add address=[/ipv6/dhcp-client get value-name=dhcp-server-v6 number=ether1] \
list=prefix_delegation comment="dhcp6 client server value"
Then some rules:
/ipv6 firewall filter
add action=accept chain=input dst-port=5678 protocol=udp
add action=accept chain=input comment=\
"defconf: accept established,related,untracked" connection-state=\
established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
invalid
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" port=\
33434-33534 protocol=udp
add action=accept chain=input comment=\
"defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
udp src-address-list=prefix_delegation
add action=drop chain=input comment=\
"defconf: drop everything else not coming from LAN" in-interface=!bridge
add action=accept chain=forward comment=\
"defconf: accept established,related,untracked" connection-state=\
established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
connection-state=invalid
add action=drop chain=forward comment=\
"defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment=\
"defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=drop chain=forward comment=\
"defconf: drop everything else not coming from LAN" in-interface=!bridge
Optionals; my setup
NTP
/system ntp client
set enabled=yes
/system ntp server
set enabled=yes
/system ntp client servers
add address=nz.pool.ntp.org
DNS
/tool fetch url=https://curl.se/ca/cacert.pem
/certificate import file-name=cacert.pem password=""
/ip dns static
add address=9.9.9.9 name=dns.quad9.net
add address=149.112.112.112 name=dns.quad9.net
add address=2620:fe::fe name=dns.quad9.net type=AAAA
add address=2620:fe::9 name=dns.quad9.net type=AAAA
/ip dns
set allow-remote-requests=yes cache-size=4096KiB use-doh-server=\
https://dns.quad9.net/dns-query verify-doh-cert=yes