IPv6 Firewall: Rules, Best Practices, and RA Guard
IPv6 Firewall: Rules, Best Practices, and RA Guard
Section titled “IPv6 Firewall: Rules, Best Practices, and RA Guard”IPv6 firewall in RouterOS operates under /ipv6 firewall filter — a separate
table from the IPv4 /ip firewall filter. The chain model is identical
(input, forward, output), but IPv6 introduces protocol-specific requirements:
ICMPv6 is critical to IPv6 operation and must not be blanket-blocked, RA Guard
protects against rogue router advertisements, and extension headers add
matching capabilities absent in IPv4.
Quick Start
Section titled “Quick Start”A minimal stateful IPv6 firewall protecting the router and forwarded traffic:
/ipv6 firewall filter
# Stateful baseadd chain=input action=accept connection-state=established,related,untracked comment="accept established/related"add chain=input action=drop connection-state=invalid comment="drop invalid"add chain=forward action=accept connection-state=established,related,untracked comment="fwd accept established/related"add chain=forward action=drop connection-state=invalid comment="fwd drop invalid"
# Essential ICMPv6 — do not skip, IPv6 breaks without theseadd chain=input action=accept protocol=icmpv6 comment="accept ICMPv6"add chain=forward action=accept protocol=icmpv6 comment="fwd accept ICMPv6"
# DHCPv6 prefix delegation client traffic from ISPadd chain=input action=accept protocol=udp dst-port=546 src-address=fe80::/10 \ in-interface-list=WAN comment="accept DHCPv6-PD from WAN"
# Drop all other input from WANadd chain=input action=drop in-interface-list=WAN comment="drop WAN input"add chain=input action=drop comment="drop all other input"add chain=forward action=drop comment="drop all other forward"IPv6 vs IPv4 Firewall Differences
Section titled “IPv6 vs IPv4 Firewall Differences”| Aspect | IPv4 | IPv6 |
|---|---|---|
| Command path | /ip firewall filter | /ipv6 firewall filter |
| ICMP protocol name | protocol=icmp | protocol=icmpv6 |
| TTL/hop-limit | ttl matcher | hop-limit matcher |
| Extension headers | Not applicable | ipv6-header, routing-header matchers |
| Fragment matching | fragment flag | ipv6-header=fragment |
| Bogon list | RFC1918, etc. | Different reserved ranges (see below) |
| NDP/SLAAC | No equivalent | ICMPv6 types 133–136 required |
Address notation in rules uses standard IPv6 CIDR format:
/ipv6 firewall filter add chain=input src-address=2001:db8::/32 action=dropChains
Section titled “Chains”The three built-in chains behave identically to IPv4:
| Chain | Traffic | Typical Use |
|---|---|---|
| input | Destined for the router | Protect management, NDP to router |
| forward | Routed through the router | LAN-to-WAN, inter-VLAN |
| output | Originating from the router | Rarely needed |
ICMPv6: What to Allow and What to Block
Section titled “ICMPv6: What to Allow and What to Block”Never drop all ICMPv6. IPv6 relies on ICMPv6 for neighbor resolution (NDP), path MTU discovery (PMTU), and address assignment (SLAAC). Blocking ICMPv6 indiscriminately breaks IPv6 connectivity silently.
Must Allow
Section titled “Must Allow”| ICMPv6 Type | Name | Required For |
|---|---|---|
| 1 | Destination Unreachable | Error signaling |
| 2 | Packet Too Big | PMTU discovery (critical) |
| 3 | Time Exceeded | Traceroute, loop detection |
| 4 | Parameter Problem | Malformed packet signaling |
| 128 | Echo Request | Ping |
| 129 | Echo Reply | Ping responses |
| 133 | Router Solicitation | SLAAC, default gateway |
| 134 | Router Advertisement | SLAAC, default gateway |
| 135 | Neighbor Solicitation | NDP address resolution |
| 136 | Neighbor Advertisement | NDP address resolution |
Conditional / Restrict by Interface
Section titled “Conditional / Restrict by Interface”| ICMPv6 Type | Name | Guidance |
|---|---|---|
| 130–132, 143 | MLD (Multicast Listener Discovery) | Allow on LAN; not required from WAN |
| 137 | Redirect | Allow only on trusted segments; block from WAN |
Granular ICMPv6 Rules by Interface Direction
Section titled “Granular ICMPv6 Rules by Interface Direction”For environments requiring per-type control rather than a blanket ICMPv6 accept:
/ipv6 firewall filter
# Error types — allow from anywhereadd chain=input action=accept protocol=icmpv6 icmp-options=1:0-255 comment="ICMPv6 dest unreachable"add chain=input action=accept protocol=icmpv6 icmp-options=2:0-255 comment="ICMPv6 packet too big"add chain=input action=accept protocol=icmpv6 icmp-options=3:0-255 comment="ICMPv6 time exceeded"add chain=input action=accept protocol=icmpv6 icmp-options=4:0-255 comment="ICMPv6 param problem"add chain=input action=accept protocol=icmpv6 icmp-options=128:0-255 comment="ICMPv6 echo request"add chain=input action=accept protocol=icmpv6 icmp-options=129:0-255 comment="ICMPv6 echo reply"
# NDP — allow from link-local (expected source for ND)add chain=input action=accept protocol=icmpv6 icmp-options=133:0-255 src-address=fe80::/10 comment="RS"add chain=input action=accept protocol=icmpv6 icmp-options=134:0-255 src-address=fe80::/10 comment="RA"add chain=input action=accept protocol=icmpv6 icmp-options=135:0-255 comment="NS"add chain=input action=accept protocol=icmpv6 icmp-options=136:0-255 comment="NA"
# MLD — LAN onlyadd chain=input action=accept protocol=icmpv6 icmp-options=130:0-255 in-interface-list=LAN comment="MLD Query"add chain=input action=accept protocol=icmpv6 icmp-options=131:0-255 in-interface-list=LAN comment="MLD Report"add chain=input action=accept protocol=icmpv6 icmp-options=132:0-255 in-interface-list=LAN comment="MLD Done"add chain=input action=accept protocol=icmpv6 icmp-options=143:0-255 in-interface-list=LAN comment="MLDv2 Report"Default Ruleset with Bogon Blocking
Section titled “Default Ruleset with Bogon Blocking”RouterOS ships with a bad_ipv6 address-list used in the default firewall
configuration. These are reserved, documentation, or invalid ranges that
should never appear as legitimate traffic sources or destinations.
bad_ipv6 Address List
Section titled “bad_ipv6 Address List”/ipv6 firewall address-list
add list=bad_ipv6 address=::/128 comment="unspecified"add list=bad_ipv6 address=::1/128 comment="loopback"add list=bad_ipv6 address=::ffff:0.0.0.0/96 comment="IPv4-mapped"add list=bad_ipv6 address=::/96 comment="IPv4-compatible (deprecated)"add list=bad_ipv6 address=100::/64 comment="discard prefix (RFC6666)"add list=bad_ipv6 address=2001:db8::/32 comment="documentation (RFC3849)"add list=bad_ipv6 address=2001:10::/28 comment="deprecated ORCHID"add list=bad_ipv6 address=3ffe::/16 comment="6bone (decommissioned)"add list=bad_ipv6 address=fc00::/7 comment="ULA — block on WAN (anti-spoof)"Note on ULA (
fc00::/7): ULA addresses are for internal use only and should never appear as traffic sources on a WAN interface. Addingfc00::/7tobad_ipv6for WAN anti-spoof rules is a hardening addition — it is not in the RouterOS factory default list.
Complete Default-Style Ruleset
Section titled “Complete Default-Style Ruleset”/ipv6 firewall filter
# --- input chain ---add chain=input action=accept connection-state=established,related,untracked \ comment="defconf: accept established,related,untracked"add chain=input action=drop connection-state=invalid \ comment="defconf: drop invalid"add chain=input action=accept protocol=icmpv6 \ comment="defconf: accept ICMPv6"add chain=input action=accept protocol=udp port=33434-33534 \ comment="defconf: accept UDP traceroute"add chain=input action=accept protocol=udp dst-port=546 src-address=fe80::/10 \ in-interface-list=WAN comment="defconf: accept DHCPv6-PD from WAN"add chain=input action=drop in-interface-list=!LAN \ comment="defconf: drop non-LAN to router"add chain=input action=drop \ comment="defconf: drop all other input"
# --- forward chain ---add chain=forward action=accept connection-state=established,related,untracked \ comment="defconf: accept established,related,untracked"add chain=forward action=drop connection-state=invalid \ comment="defconf: drop invalid"add chain=forward action=drop protocol=icmpv6 hop-limit=equal:1 \ in-interface-list=WAN comment="defconf: drop hop-limit=1 from WAN"add chain=forward action=accept protocol=icmpv6 \ comment="defconf: accept ICMPv6"add chain=forward action=accept protocol=139 \ comment="defconf: accept HIP"add chain=forward action=accept protocol=udp dst-port=500,4500 \ comment="defconf: accept IKE"add chain=forward action=accept protocol=ipsec-ah \ comment="defconf: accept AH"add chain=forward action=accept protocol=ipsec-esp \ comment="defconf: accept ESP"add chain=forward action=accept ipsec-policy=in,ipsec \ comment="defconf: accept inbound IPsec policy"add chain=forward action=drop src-address-list=bad_ipv6 \ comment="defconf: drop bad src IPv6"add chain=forward action=drop dst-address-list=bad_ipv6 \ comment="defconf: drop bad dst IPv6"add chain=forward action=drop \ comment="defconf: drop all other forward"Extension Headers
Section titled “Extension Headers”:::note Platform availability
The routing-header and ipv6-header matchers are available on physical RouterBOARD hardware with full IPv6 firewall support. These matchers may not be present on all builds (e.g., CHR). Verify available matchers with /ipv6 firewall filter add tab completion on your device.
:::
IPv6 extension headers enable additional matching not available in IPv4.
Block Routing Header Type 0 (RH0)
Section titled “Block Routing Header Type 0 (RH0)”RH0 was deprecated by RFC 5095 due to amplification attack potential. Drop it on hardware that supports the routing-header matcher:
/ipv6 firewall filteradd chain=forward action=drop routing-header=0 comment="drop RH0 (deprecated, RFC5095)"add chain=input action=drop routing-header=0 comment="drop RH0 to router"Match Fragmented Packets
Section titled “Match Fragmented Packets”On hardware supporting the ipv6-header matcher:
/ipv6 firewall filteradd chain=forward action=drop ipv6-header=fragment protocol=tcp \ comment="drop fragmented TCP (abnormal)"RA Guard and NDP Protection
Section titled “RA Guard and NDP Protection”The Rogue RA Problem
Section titled “The Rogue RA Problem”A rogue Router Advertisement (ICMPv6 type 134) from an unauthorized device on a LAN segment causes connected hosts to:
- Learn a wrong default gateway
- Configure incorrect IPv6 prefixes via SLAAC
- Have their traffic hijacked or blackholed
nd-suppression on Bridge Ports
Section titled “nd-suppression on Bridge Ports”:::note Hardware requirement
The nd-suppression bridge port property is available on physical RouterBOARD hardware but may not be present on all RouterOS builds (e.g., CHR). Verify with /interface bridge port print on your device before using.
:::
RouterOS provides per-bridge-port ND suppression on supported hardware. When enabled, the bridge drops ND/RA/RS/NS/NA traffic on that port (DHCPv6 is not suppressed). Use this on untrusted access ports while leaving uplinks/trusted ports unsuppressed.
/interface bridgeadd name=br-lan igmp-snooping=yes
/interface bridge port# Access ports — suppress ND (blocks rogue RA from hosts)add bridge=br-lan interface=ether2 nd-suppression=yesadd bridge=br-lan interface=ether3 nd-suppression=yesadd bridge=br-lan interface=ether4 nd-suppression=yes
# Uplink / trusted router port — ND allowed, multicast-router learned dynamicallyadd bridge=br-lan interface=sfp-sfpplus1 multicast-router=temporary-query
nd-suppressionis designed to be paired withmulticast-router=temporary-queryon the uplink so the bridge learns the legitimate multicast router rather than flooding ND to all ports.
Firewall-Level RA Filtering
Section titled “Firewall-Level RA Filtering”For environments without bridge-port nd-suppression support, or as an additional layer, drop rogue RAs in the firewall raw table before conntrack:
/ipv6 firewall rawadd chain=prerouting action=drop protocol=icmpv6 icmp-options=134:0-255 \ in-interface-list=UNTRUSTED comment="drop rogue RA from untrusted interfaces"Define UNTRUSTED as an interface list containing access-side ports where
router advertisements should never originate.
Best Practices Summary
Section titled “Best Practices Summary”| Practice | Reason |
|---|---|
Accept established,related,untracked early | Stateful operation, performance |
Drop invalid early | Conntrack anomalies, fragmented attack traffic |
| Never blanket-drop ICMPv6 | NDP, PMTU, SLAAC all depend on ICMPv6 |
| Drop RH0 extension header | Deprecated, enables amplification |
Drop hop-limit=1 from WAN on forward | Prevents routing loops leaking to LAN |
Block bad_ipv6 list in forward | Bogon/reserved ranges should never transit |
Add fc00::/7 to WAN anti-spoof | ULA is not globally routable |
Use nd-suppression on access ports | Prevents rogue RA attacks at L2 |
| Pair nd-suppression with MLD snooping | Contains multicast/ND flooding domains |
Allow DHCPv6-PD UDP 546 from fe80::/10 | Required if ISP delegates prefixes |