IPv6 Firewall Configuration: Essential Rules
Configure your firewall for IPv6 without breaking connectivity. Essential ICMPv6 rules, Linux examples, and common mistakes to avoid.
IPv4 firewalls let you block ICMP without major consequences. IPv6 doesn't work that way. Block the wrong ICMPv6 messages and you'll break path MTU discovery, neighbor discovery, and basic connectivity. Your firewall will silently cause connection failures that take hours to debug.
TL;DR - Quick Summary
Key Points:
- ICMPv6 is essential: Unlike IPv4 ICMP, blocking ICMPv6 breaks basic network operations
- Allow specific types: Types 1-3 (errors), 128-129 (ping), 133-136 (NDP) are required
- Never block Type 2: Packet Too Big messages are critical for Path MTU Discovery
- Use hop limit 255 for NDP: Prevents off-link spoofing of neighbor discovery
- Apply to all protocol families: Don't forget to configure both iptables and ip6tables
Skip to: Essential ICMPv6 Types | Linux Examples | Common Mistakes
Why IPv6 Firewalls Are Different#
In IPv4, ICMP handles diagnostics like ping and traceroute. You can block it entirely and most things still work. ARP runs at layer 2, DHCP uses UDP, and routers use dedicated protocols.
IPv6 merged these functions into ICMPv6. Address resolution, router discovery, and duplicate address detection all depend on specific ICMPv6 types. Block them and hosts can't find their default gateway, neighbors can't communicate on the same link, and connections hang when MTU mismatches occur.
The protocol designers made this choice deliberately. ICMPv6 is part of the IPv6 specification, not a diagnostic add-on.
Essential ICMPv6 Types#
Your firewall must allow these ICMPv6 types for basic functionality:
| Type | Name | Purpose | Block This? |
|---|---|---|---|
| 1 | Destination Unreachable | Port/protocol is closed | No - breaks TCP |
| 2 | Packet Too Big | Path MTU discovery | NEVER - breaks connections |
| 3 | Time Exceeded | Hop limit reached | No - breaks traceroute |
| 128 | Echo Request | Ping request | Optional (but why?) |
| 129 | Echo Reply | Ping response | Optional (but why?) |
| 133 | Router Solicitation | Find default gateway | NEVER - breaks connectivity |
| 134 | Router Advertisement | Gateway announcements | NEVER - breaks connectivity |
| 135 | Neighbor Solicitation | Address resolution (ARP equivalent) | NEVER - breaks everything |
| 136 | Neighbor Advertisement | Address resolution responses | NEVER - breaks everything |
Blocking ICMPv6 types 2, 133, 134, 135, or 136 will break IPv6 connectivity in subtle, hard-to-debug ways. Don't do it.
Type 2 (Packet Too Big) deserves special attention. IPv6 has no fragmentation at intermediate routers. When a packet exceeds the path MTU, the router drops it and sends back a Packet Too Big message. Block this and connections hang after the initial SYN/ACK. You'll spend hours debugging why HTTPS works but large transfers fail.
Never block ICMPv6 Type 2 (Packet Too Big). This breaks Path MTU Discovery and causes connection hangs. Learn more in our MTU and PMTUD guide.
Linux ip6tables Examples#
Minimal Host Firewall#
For a client machine or server that doesn't route traffic:
# Flush existing rules
ip6tables -F
ip6tables -X
# Default policies
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
# Allow loopback
ip6tables -A INPUT -i lo -j ACCEPT
# Allow established connections
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow essential ICMPv6
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 1 -j ACCEPT # Destination Unreachable
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 2 -j ACCEPT # Packet Too Big
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 3 -j ACCEPT # Time Exceeded
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 128 -j ACCEPT # Echo Request
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 129 -j ACCEPT # Echo Reply
# Allow neighbor discovery (must be link-local with hop limit 255)
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 133 -m hl --hl-eq 255 -j ACCEPT # Router Solicitation
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 134 -m hl --hl-eq 255 -j ACCEPT # Router Advertisement
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 135 -m hl --hl-eq 255 -j ACCEPT # Neighbor Solicitation
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 136 -m hl --hl-eq 255 -j ACCEPT # Neighbor Advertisement
# Allow DHCPv6 (if needed)
ip6tables -A INPUT -p udp --dport 546 -j ACCEPT
# Log dropped packets (optional)
ip6tables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables-dropped: "The hop limit check (--hl-eq 255) prevents spoofed neighbor discovery packets from off-link sources. Legitimate neighbor discovery always uses hop limit 255.
The hop limit check is a security feature: neighbor discovery messages should only come from directly connected devices. A hop limit of 255 means the packet couldn't have been forwarded through a router.
Server Firewall#
Add your services after the ICMPv6 rules:
# SSH
ip6tables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
ip6tables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
# HTTP/HTTPS
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT
# DNS (if running a DNS server)
ip6tables -A INPUT -p udp --dport 53 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 53 -j ACCEPTThe SSH rule uses recent to implement basic rate limiting. After 4 connection attempts in 60 seconds from the same address, additional attempts are dropped.
Router Forwarding Rules#
For routers or systems that forward traffic:
ip6tables -P FORWARD DROP
# Allow established connections
ip6tables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow ICMPv6 forwarding (critical for PMTUD)
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type 1 -j ACCEPT
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type 2 -j ACCEPT
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type 3 -j ACCEPT
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type 128 -j ACCEPT
ip6tables -A FORWARD -p ipv6-icmp --icmpv6-type 129 -j ACCEPT
# Allow internal network to access internet
ip6tables -A FORWARD -i eth1 -o eth0 -j ACCEPTDon't forward neighbor discovery messages (133-136). Those are link-local only.
Linux nftables Examples#
Modern distributions use nftables instead of iptables. The syntax is cleaner:
# Create table
nft add table ip6 filter
# Create chains
nft add chain ip6 filter input { type filter hook input priority 0\; policy drop\; }
nft add chain ip6 filter forward { type filter hook forward priority 0\; policy drop\; }
nft add chain ip6 filter output { type filter hook output priority 0\; policy accept\; }
# Loopback
nft add rule ip6 filter input iif lo accept
# Established connections
nft add rule ip6 filter input ct state established,related accept
# ICMPv6
nft add rule ip6 filter input icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, echo-request, echo-reply } accept
# Neighbor discovery with hop limit check
nft add rule ip6 filter input icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept
# SSH with rate limiting
nft add rule ip6 filter input tcp dport 22 ct state new limit rate 4/minute accept
# HTTP/HTTPS
nft add rule ip6 filter input tcp dport { 80, 443 } acceptThe set notation ({ 80, 443 }) creates one rule instead of two, making the ruleset more efficient.
Windows Firewall#
Windows Firewall enables IPv6 ICMPv6 by default for most essential types, but you should verify:
# Show current ICMPv6 rules
Get-NetFirewallRule -DisplayName "*ICMPv6*" | Format-Table DisplayName, Enabled, Direction
# Enable all ICMPv6 inbound (if disabled)
Enable-NetFirewallRule -DisplayName "Core Networking - Destination Unreachable (ICMPv6-In)"
Enable-NetFirewallRule -DisplayName "Core Networking - Packet Too Big (ICMPv6-In)"
Enable-NetFirewallRule -DisplayName "Core Networking - Neighbor Discovery Solicitation (ICMPv6-In)"
Enable-NetFirewallRule -DisplayName "Core Networking - Neighbor Discovery Advertisement (ICMPv6-In)"
Enable-NetFirewallRule -DisplayName "Core Networking - Router Advertisement (ICMPv6-In)"
# Allow SSH server on IPv6
New-NetFirewallRule -DisplayName "SSH (IPv6)" -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow -Profile Any -RemoteAddress AnyFor web servers, add rules to allow HTTP and HTTPS traffic:
New-NetFirewallRule -DisplayName "HTTP (IPv6)" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "HTTPS (IPv6)" -Direction Inbound -Protocol TCP -LocalPort 443 -Action AllowCloud Security Groups#
AWS#
Security groups are stateful and allow established return traffic automatically. Add explicit rules for:
- ICMPv6: Use "All ICMPv6" or select specific types
- Services: Add your TCP/UDP ports
Azure#
Network Security Groups (NSGs) handle IPv6. Default rules allow outbound and established traffic. Add inbound rules for services.
GCP#
Firewall rules support IPv6. Create separate rules with --source-ranges=::/0 for IPv6. Default rules don't include ICMPv6, so add it explicitly.
All three providers require you to enable IPv6 on the VPC/network first. IPv6 isn't enabled by default.
Common Mistakes#
Blocking All ICMPv6#
The single most common IPv6 firewall mistake. Administrators port IPv4 rules that block all ICMP and wonder why IPv6 doesn't work. If you only remember one thing from this article: never block all ICMPv6.
No IPv6 Firewall Rules#
Some admins configure iptables carefully but ignore ip6tables entirely. IPv6 is then completely open. Both protocol families need firewall rules.
Forgetting Egress Filtering#
Most examples show ingress rules only. If you implement strict egress filtering (you should), allow outbound ICMPv6 types 133, 135, and 128. Blocking outbound neighbor solicitations prevents the host from resolving neighbors.
Wrong Hop Limit on Neighbor Discovery#
Accepting neighbor discovery packets without checking hop limit (255) allows attackers to send spoofed router or neighbor advertisements from anywhere on the internet. Always verify hop limit.
Allowing Too Much#
Enabling "all ICMPv6" is safer than blocking it all, but it's still excessive. You don't need to allow Multicast Listener Discovery messages from the internet, for example. Use specific types.
Best Practice
Allow specific ICMPv6 types rather than all ICMPv6. Essential types are: 1-4 (errors), 128-129 (echo), and 133-136 (neighbor discovery). This provides security without breaking functionality.
Testing Your Firewall#
After configuring rules, verify basic connectivity:
# Test ping (requires ICMPv6 types 128/129)
ping6 -c 3 2001:4860:4860::8888
# Test path MTU discovery (requires ICMPv6 type 2)
# Send large packet, verify it doesn't hang
curl -6 -v https://ipv6.google.com/These commands verify that essential ICMPv6 messages are being allowed. If ping works but curl hangs, check that Type 2 (Packet Too Big) isn't blocked.
Check neighbor discovery and routing:
# Check neighbor discovery (requires types 135/136)
ip -6 neigh show
# Verify routes (requires types 133/134)
ip -6 route showFrom another host, test that unauthorized ports are actually blocked:
# Should timeout or return "Connection refused"
telnet -6 your:server::address 23
# Should work (if SSH is allowed)
ssh -6 your:server::addressUse online scanners like IPv6 Port Scanner (ipv6-tools.com) or test-ipv6.com to verify your firewall from external networks.
IPv6 firewalls require understanding what ICMPv6 does. The protocol isn't optional or just for diagnostics. Allow the essential types, verify neighbor discovery works, and test path MTU discovery with real traffic. Get these right and your IPv6 firewall will be both secure and functional.
Related Articles#
- IPv6 Security Best Practices - Comprehensive guide to securing your IPv6 network
- How to Enable IPv6 - Configure IPv6 on your systems and network