Networking – Allow traffic through a firewall to a dynamic IPv6 address

firewalliptablesipv6networking

Suppose I have this configuration on IPv4 right now:

My router (a Linux box) is connected to the Internet on eth0 and my LAN on eth1. I want to forward port 80 to 10.1.2.3. Here's how I'd currently do that:

iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to 10.1.2.3
iptables -A FORWARD -m conntrack --ctstate DNAT -j ACCEPT

Now I want to do the equivalent on IPv6. Suppose I have the same configuration as before, with these changes:

My ISP gives my router the range 2001:db8:aaaa::/64 via prefix delegation. My router takes 2001:db8:aaaa::1 for itself on eth1 and gives 2001:db8:aaaa::123 to the host that I want port 80 open on.

NAT is no longer necessary in the IPv6 case, so all I need is a firewall rule to allow the traffic. Here's the rule I can think of to do that:

ip6tables -A FORWARD -i eth0 -d 2001:db8:aaaa::123 -p tcp -m tcp --dport 80 -j ACCEPT

The problem I have with this is that I had to hardcode 2001:db8:aaaa::123 into my firewall rule, and the 2001:db8:aaaa:: prefix is subject to change at my ISP's whim. In the IPv4 world, the only IP that I had to hardcode was an internal one, so I knew it would never get changed out from under me. Is there any way I can allow traffic like this without having to modify a rule every time my ISP changes my delegated prefix? (If pf can do what I want but ip6tables can't, I'd be willing to switch to BSD for it.)

Best Answer

While there's no dedicated option, you can use the generic u32 iptables module (see iptables-extensions) to match just the interface ID part (which always starts at byte 32 of IP header):

-A FORWARD -m u32 --u32 "32 = 0x11223344 && 36 = 0xAABBCCDD" -j ACCEPT

This would match any destination address ending with :1122:3344:aabb:ccdd.

In IPv6 headers, the source address starts at byte 8 (network at 8, interface at 16); the destination address is at 24 (network at 24, interface at 32). You can use bitwise operations to implement things like CIDR mask matching in u32 as well.

Related Question