OpenWrt Forum Archive

Topic: [SOLVED] Set up IPv6 on OpenWrt behind a cable modem/router -> NAT6

The content of this topic has been archived on 23 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

Hi,

I took several attempts to set up IPv6 on my OpenWrt router (TP-Link Archer C7 v2 running Chaos Calmer 15.05) but I cannot get it to work, hence I ask for help here.

My network layout is this:
Cisco Cable Gateway <--> OpenWrt Router (in router mode) <--> LAN and WiFi clients

What I accomplished so far:
- IPv4 works fine on all devices. The OpenWrt router acts as a DHCP client to the cable gateway and as a DHCP server for a separate subnet for the clients.

- IPv6 works fine on the OpenWrt Router (configured as a DCHPv6 client), but clients can't establish IPv6 connections to external servers.

The problems are (as far as I understand or could find out):
(1) My Cisco cable gateway runs a firmware crippled by the ISP. It's not possible to set it to bridged mode.
(2) The Cisco gateway gets a /56 prefix, however it doesn't seem to support PD (Prefix Delegation) according to forum entries.
So, the OpenWrt router behind the gateway gets a valid IPv6 address and I can ping or trace IPv6 addresses from the OpenWrt router. But the clients attached to the OpenWrt router do not get IPv6 addresses with the same (globally routable) prefix, and they cannot ping external IPv6 addresses. They can however, ping the IPv6 address of the OpenWRT router (but not the cable gateway).

What I do not want:
I know it would be much easier to get IPv6 and IPv4 working if I set my OpenWrt router as a dumb access point. However, since my ISP has full access to my cable gateway, I would like my OpenWrt to work as my "gatekeeper", i.e. I definitely want to use the firewall on OpenWrt to ensure the integrity of my home network.

Nevertheless, I'm sure there are ways to work around my the given boundaries. I'm new to IPv6, so maybe for some here the possible solutions are obvious. But I couldn't draw the "right" conclusions from the Documentation/Wiki.

So, please, what options do you see for me to get IPv6 working?

I have two things in mind:
a) Somehow let my cable gateway handle the IPv6 address assignments (like forwarding the address negotiation traffic) while still keep the firewall functionality of OpenWrt to protect my home network.
b) Set the OpenWrt router up as a gateway/proxy that masks all clients requests as coming from the OpenWrt router (something like NAT) so all IPv6 traffic is routed through the OpenWrt machine and the clients are actually not reachable from outside. (This would actually be my preferred option, if possible, although I know it's not ideal to have an additional "translation layer".)

EDIT: I found a solution for approach b) with the package kmod-ipt-nat6. See post 6 for full documentation!


I'd appreaciate any advice you can give me to setup IPv6.

Thank you and regards,

Timo

(Last edited by silentcreek on 2 Nov 2015, 10:18)

I don't know if it helps, but here is my network and dhcp configuration of my OpenWrt machine.

EDIT: Removed paste of network configuration as it's irrelevant to the solution layed out in post 6 and hence might confuse new readers. Start from the deault settings, get your WAN connection up and then follow the steps documented in post 6, if you wan't to setup NAT6.

(Last edited by silentcreek on 2 Nov 2015, 10:16)

Ok, I tried something else, but without success. Inspired by this old wiki page:
http://wiki.openwrt.org/doc/uci/6relayd
I set ra, ndp and dhcpv6 on the lan interface to "relay" mode. (I know this wiki entry is deprecated and 6relayd isn't used anymore - I just applied those settings in LUCI without touching the config files manually.) However, that didn't do anything. In fact, with this configuration ipv6 doesn't work at all anymore on the clients (whereas before, they could at least ping the OpenWrt router via ipv6, just not external hosts).

Any ideas? Am I looking in the absolute wrong direction?

Thanks,

Timo

Update: I made some progress - got a working IPv6 connection!

Inspired by this article [1] I set up NAT for IPv6 by installing the package kmod-ipt-nat6, adding a masquerade rule to ip6tables and a route to enable external requests over my gateway. This way, I managed to get a working IPv6 connection on my desktop computer.

It has left me with two issues so far - one of which is new:

a) For now, I only got IPv6 working on my (wired) desktop. My wireless clients can't connect to external IPv6 hosts yet. I have yet to figure out why that is. One difference I know of is that my desktop client uses a static IPv4 configuration whereas the others do not, but I'm not sure how that would make a difference for the IPv6 setup. I'll do more testing tonight.

b) When IPv6 is working, the resolution of local host names configured in the OpenWrt router does not work anymore. I can reach the clients via their IPv4 addresses but typing "openwrt.lan" leads to timeouts. As soon as I disable IPv6, it works fine again.

If you have some insights, ideas, etc - I'd be happy to hear them smile

Thanks,

Timo

[1] http://blog.iopsl.com/ipv6-nat-with-openwrt-router/

Success! I finally got IPv6 NAT working yesterday. I had a small mistake in my script to set up the NAT masquerading which caused the previous problems. So, I got IPv6 NAT working on all clients now and when this was fixed the problem with resolving local hostnames (like openwrt.lan) was gone, too.

I will post the full documentation of how I set it up soon (although it's mostly the same as in the aforementioned and linked blog post). There's just one small question I'd like to look into first and that is why one of my clients (an Android 5.1 smartphone) seems to prefer IPv4 connections while IPv6 works at the same time (and it can also connect to IPv6 only hosts). All my other clients seem to prefer IPv6.

RESOLUTION

I have it all figured out now. Here's the documentation how to set up NAT6 or IPv6 NAT on OpenWrt Chaos Calmer:

Prerequesites: This guide assumes that you already have a working IPv6 WAN connection on your OpenWrt router and you want to allow your client devices to use this connection via NAT6.

1) Install the package kmod-ipt-nat6 either via the LuCI interface under "System" -> "Software" or via ssh with the command

opkg update && opkg install kmod-ipt-nat6

2) In the LuCI webinterface go to "Network" -> "Interface". Change the first letter of the "IPv6 ULA Prefix" from 'f' to 'd'.
Explanation: If you do not do this, IPv6 NAT may still work on some clients, but others will prefer the IPv4 route instead because the default prefix (starting with something like fd25...) does not indicate a globally routed address. Changing this to a global IPv6 address solves this - just make sure it's an address that is not being used yet (addresses starting with d... are unassigned and therefore safe to use).


3) On the same page, move up to the "LAN" section and click on "Edit". There you scoll down to "DHPC Server" and hit the tab "IPv6 Settings". Then check the box "Always announce default router".


4) Make sure that the following values are set (should be by default): "Router Advertisement-Service" and "DHCPv6-Service" should both be set to "server mode", "NDP-Proxy" to "disabled" and "DHCPv6-Mode" to "stateless + stateful".
Note: The original blog post on which this guide is based on recommends to disable the DHCPv6-Service. But my testing showed that with DHCPv6 disabled, some clients would still prefer IPv4 even though IPv6 worked as well (e.g. my Android smartphone showed this behaviour). Enabling DHCPv6 solved this.


5) Last but not least, you need a small script to add the actuall IPv6 NAT rule to the firewall and set the default route/gateway. Via ssh create a new file /root/nat6.sh with the following content (using your favorite editor like vi, nano, etc.):

#/bin/ash

# Wait until IPv6 route is up...
line=0
while [ $line -eq 0 ]
do
        sleep 5
        line=`route -A inet6 | grep ::/0 | awk 'END{print NR}'`
done

# Add masquerading rule (NAT6) to the firewall
ip6tables -t nat -I POSTROUTING -s `uci get network.globals.ula_prefix` -j MASQUERADE

# Set default gateway for requests to global addresses
route -A inet6 add 2000::/3 `route -A inet6 | grep ::/0 | awk 'NR==1{print "gw "$2" dev "$7}'`

# Set accept_ra to 2, otherwise temporary addresses won't work
echo 2 > /proc/sys/net/ipv6/conf/`route -A inet6 | grep ::/0 | awk 'NR==1{print $7}'`/accept_ra

# Use temporary addresses (IPv6 privacy extensions)
echo 2 > /proc/sys/net/ipv6/conf/`route -A inet6 | grep ::/0 | awk 'NR==1{print $7}'`/use_tempaddr

Note: If you do not want or cannot use IPv6 privacy extensions on your OpenWrt router, you can remove the last 5 lines (starting from "# Set accept_ra to 2...") from this script. Then your IPv6 suffix or interface identifier will be static.


6) Make the script executable by issuing the following command via ssh:

chmod +x /root/nat6.sh

7) Make the script being executed whenever your router boots. To do this, add the folloing line to /etc/rc.local before the last line that contains 'exit 0':

/root/nat6.sh &

You can do this either via ssh using your preferred editor or via LuCI under "System" -> "Startup" -> "Local Startup".


8) Restart your router and verify IPv6 is working on your clients.



Credits
This solution was based on this blog post: http://blog.iopsl.com/ipv6-nat-with-openwrt-router/

(Last edited by silentcreek on 29 Oct 2015, 12:16)

One short follow up on this:

I made one more change to the nat6 script so it won't loop infinitely, e.g. in case there is a problem with my IPv6 WAN connection.

Specifically I replaced this code:

# Wait until IPv6 route is up...
line=0
while [ $line -eq 0 ]
do
        sleep 5
        line=`route -A inet6 | grep ::/0 | awk 'END{print NR}'`
done

with this code:

# Wait until IPv6 route is up...
# Don't loop infinitely, but stop after (delay x limit) seconds
line=0
count=1
delay=5
limit=24
while [ $line -eq 0 ]
do
    if [ $count -gt $limit ]
    then
        exit 1
    fi
    sleep $delay
    count=$((count+1))
    line=`route -A inet6 | grep ::/0 | awk 'END{print NR}'`
done

This should help to free CPU resources in case an IPv6 connection can't be established. My "delay" is 5 seconds because this is the time my router usually takes to get IPv6 up (so the while loop is usually only executed once).

I have an archer c7 v2 this solution works for me too,thanks,but only work in wired conections,in wifi i dont have ipv6,you have this problem in wifi too?

Nope. Wifi works fine for me. I did have problems with my Android phone when DHCPv6 was disabled. But when enabled, all my wireless clients work - and I have 9 different wireless clients on my network (laptops, phones, tablets, streaming clients).

I answered in your other thread. If you post your configuration there, maybe we can figure out whats going on.

Hey, thanks for this!! I finally managed to get IPv6 working on my home network after a week of research! I'm so glad that I've found this thread. My mobile devices also work fine, no issues there.

I made one small correction, though. I'm not sure if that's ok, but I changed ULA prefix to my static IPv6 /64 prefix (delegated from ISP), since you've mentioned that it needs to be some public address.

There is no way to route (bridge) without NATing IPv6? All my devices get a IPv6 address from same /64 as main cable modem but thre is no routing from lan interface to wan6...

Oh well I think I'd try NATing.

sasom wrote:

Hey, thanks for this!! [...] I made one small correction, though. I'm not sure if that's ok, but I changed ULA prefix to my static IPv6 /64 prefix (delegated from ISP), since you've mentioned that it needs to be some public address.

For a static prefix that my work well, but as soon as that changes you may end up using a prefix that is actually used elsewhere on the internet. That's why I use a prefix starting with d... It's public, too, but not not used or assigned on the internet.

rmacielalves wrote:

There is no way to route (bridge) without NATing IPv6? All my devices get a IPv6 address from same /64 as main cable modem but thre is no routing from lan interface to wan6...

There are certainly ways to use IPv6 without NAT. But it depends on your modem and router setup. If your modem supports prefix delegation, you don't need NAT. If your modem suports bridging, you don't need NAT either. Or if you can configure your router (behind the modem) as a dumb access point (without firewall), then you can also avoid NAT. But if you don't have these options or don't want to use them, then NAT may be a solution that still let's you use IPv6 on your subnet.

So, one more update to this thread:

I added a wiki page for setting up NAT6. You will find that the wiki entry is much more extensive than the solution provided in this forum topic.

The most notable changes are:

1) Instead of adding a custom script that is called by /etc/rc.local during boot, I wrote an init script so we only need to change one file during the setup. The init script can be enabled and disabled just like any other init script (and will also be listed on the web interface).

2) The init script may look much more complicated, but it basically does the same thing. The increased length comes mostly from the added logging capability (any action or failure of the script can be found in the system logs). But it also does some basic sanity checks to make sure the script doesn't continue if a returned value is bogus, for example. The script also adds some variables for easy customization.

3) I added one more step in the setup guide that disables one of the default firewall rules in OpenWrt (Allow-ICMPv6-Forward). This rule is not needed when you use NAT6.

Hi Silentcreek,

I followed your ipv6.nat6 openwrt.wiki..

I posted already a question here:

 forum openwrt org/viewtopic.php ? pid=337478#p337478

basically, what I figured out by now. Your script isn't executing on my end.

$(uci get "network.$WAN6_NAME.ifname") does nothing

$(route -A inet6 -e | grep "$WAN6_INTERFACE" | awk '/::\/0/{print $2; exit}')
results:
-ash: fe80::1: not found

point is. when I set my hosts manually to gateway dd00:1:1::1 it works
when I set my host to use dhcpv6 they get the fe80:: IP and NAT doesn't work

also the "log"
logread | grep NAT6

shows nothing!

so something must be wrong with the script.

Using CHAOS CALMER (15.05.1, r48532)

Ahhhhh

# Logical interface name of outbound IPv6 connection
# There should be no need to modify this, unless you changed the default network interface names
WAN6_NAME="wan6"


This was very misleading. WAN6_NAME="wan" would solve the problem in my case
Although I did NOT change any network interface name!

It is good that you have something working. It is sad that you had to revert to NAT. NAT is why the internet is broken as it is today.

There are other ways of extending a providers /64, when they won't provide you a PD prefix. odhcpd has 'relay' mode which works pretty well. Also there is v6brouter which uses bridging for IPv6. Lastly there is RFC 7278 on extending a providers /64 (oriented to cell phones, but still an interesting read).

Hi CVMiller,

yes, NAT wouldn't be my first choice.

I'd expected a prefix with Prefix Delegation from the main router. But my ISP doesn't do that.
Also, one of the nice benefits from IPv6 huge amount of possible numbers was that each person/household would be able to get a "static" or "semi-static" ip range. But in Europe, the ISP arguments that in this case all the world will know you, log you, hack you and it will compromise your security and privacy and thus you get new IP Address ranges regularly. At least at the Telekom in Germany I got 8 changes in only 9 days!

As far as I know, relay and v6brouter need fixed IP's? Or are there ways to handle the changing IP Address?
I surely would like to disable NAT. Cost also a few % of CPU Performance I found out.

Probably the performance cut will get minimal with newer and faster routers, but still.

HI MrGenie,

Without your ISP supporting PD, you will have to use an "alternative" to use IPv6. To me, IPV6 NAT is the very, very, last alternative I would use. NAT breaks applications, and there are lots of "extra" protocols to deal with NAT. I would hope in an IPv6 world, we can simplify networking.

It is interesting to hear the European ISP view. I think those are valid concerns, ones which have already been addressed by Stateful Firewalls, and RFC 4941 (IPv6 Temporary addresses which change about every 24 hours).

Stateful Firewalls block inbound traffic unless there is a rule to allow it (just like IPv4, and mapping ports into your LAN), but allow outbound traffic to flow freely (again, unless there is a rule to block it). Temporary addresses which every OS supports, means a new suffix (or host part of the address) is generated about every 24 hours, and that is used for outbound connections. Therefore, tracking based on IP address should not be a problem.

Content providers will continue to track via cookies for the foreseeable future.

Neither v6router or odhcp relay-mode require any fixed addresses. When the ISP changes their prefix, it will be advertised via RA, which will be transmitted into your LAN, and your devices will get a new prefix. All automagically.

If you want to use DNS on your LAN (a good idea with IPv6), the current best practice is to have your router also advertise a ULA /48 (Unique Local Address, starting with FDxx:), thus giving you static IPv6 addresses inside your network, which you can then place into your local DNS. OpenWRT supports the ULA quite nicely.

I wouldn't worry about the IPv6 NAT performance, bur rather about what you are doing to your network (address mangling), and not taking the opportunity to create a simpler network.

mrgenie wrote:

Ahhhhh

# Logical interface name of outbound IPv6 connection
# There should be no need to modify this, unless you changed the default network interface names
WAN6_NAME="wan6"


This was very misleading. WAN6_NAME="wan" would solve the problem in my case
Although I did NOT change any network interface name!

Sorry for being late to the party, but I just didn't notice your post (not checking very often), Anyway, glad you got it working and interesting that you had to change the wan interface name. It might have to do with the default network configuration of your specific device. Does your device have an interface named wan6 by default? Could you post your network configuration? Maybe I can add a fallback to the script to make it less error prone.

cvmiller wrote:

It is good that you have something working. It is sad that you had to revert to NAT. NAT is why the internet is broken as it is today.

That's quite an overstatement. First, in many cases, people won't care about or even notice NAT. Second, NAT makes network configuration and operation more complicated, yes, but not impossible. A more serious issue here is carrier-grade NAT, because - as a customer - you have no chance to make the configuration changes you might need to get things going.

But I agree in the sense that NAT6 should not be the preferred option (btw, I don't use NAT6 anymore because in the meantime I got a new cable router which is not crippled/locked down by the ISP). But it's good to have at least an option when other solutions don't work.

cvmiller wrote:

There are other ways of extending a providers /64, when they won't provide you a PD prefix. odhcpd has 'relay' mode which works pretty well. Also there is v6brouter which uses bridging for IPv6. Lastly there is RFC 7278 on extending a providers /64 (oriented to cell phones, but still an interesting read).

For some reason, I never got the relay mode to work properly, unfortunately. That's why I opted for NAT6 in the end. But v6brouter is quite an interesting alternative.

While I agree, end users don't care whether NAT is used, it does make applications more complex (having to use other protocols like STUN to get around NAT issues), and between the additional complexity, and the bit swapping (of NAT) there is a performance/latency hit.

IPv6 is our chance to rectify the "Temporary" solution of NAT (created in 1993 by RFC 1621)

http://ipv6-net.blogspot.com/2016/06/br … -mind.html

Hello Silentcreek and cvmiller,

I used all your articles and tested them all.

On my E3000 I get everything to work.
Relay mode, NAT6, v6brouter.

Works 100% Great job.

SO obviously you 2 know what you're talking about.

But the problem I have on the Rpi3 remains: ICMP packets filtered.

Now I need them to work, don't ask me why, but it's psychological! On the E3000 everything works incl. the ICMP packets, so I must get that to work on the Rpi3 as well.

The firewall on my Rpi3 is just standard. Haven't' touched anything.

(Last edited by mrgenie on 29 Oct 2016, 17:08)

One more.

On normal routers everything works.
Funny thing is, on the Rpi3 as well.

But after a while, the IPv6 connection is down. I need to restart the Pi to get it working again.

This is with NAT6/DHCP Relay/v6brouter. Works in the beginning but after a while connection to the internet lost.

Any hints what it might be? Some job in the background causing this?

firewall doing soemthing?

Is the Rpi3 firewall your _only_ firewall? Do you have two interfaces on the Pi3? Or are you trying to do this via VLAN tagging? Does your ISP support DHCPv6-PD? If so, then you don't need NAT6 or v6brouter. A network diagram would be helpful.

For testing purposes only, you could flush the firewall rules and see if that allows ICMP to pass. Assuming you are really talking about ICMPv6, you would:

ip6tables -F

In the long run, you will want to create "exceptions" on your firewall to pass ND. Here's what mine looks like:

Chain zone_wan_input (2 references)
target     prot opt source               destination         
input_wan_rule  all      anywhere             anywhere             /* user chain for input */
ACCEPT     udp      fe80::/10            fe80::/10            udp spt:dhcpv6-server dpt:dhcpv6-client /* Allow-DHCPv6 */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp echo-request limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp destination-unreachable limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp packet-too-big limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp time-exceeded limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp bad-header limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp unknown-header-type limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp router-solicitation limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
ACCEPT     ipv6-icmp    anywhere             anywhere             ipv6-icmp neighbour-solicitation limit: avg 1000/sec burst 5 /* Allow-ICMPv6-Input */
zone_wan_src_REJECT  all      anywhere             anywhere            

But a quick flush of the rules will determine if it is the firewall that is blocking ICMPv6 (or something else).

I have followed the guide in the wiki but ran into various troubles although I am using the same hardware.

Model: TP-Link Archer C7 v2
Firmware First: OpenWrt Chaos Calmer 15.05 / LuCI (git-15.248.30277-3836b45)
Firmware Later: OpenWrt Chaos Calmer 15.05.1 / LuCI 15.05-149-g0d8bbd2 Release (git-15.363.78009-956be55)

First of all, there was no configuration directory for firewall.d so expected the hook to fail.
I've still created /etc/firewall.d/with_reload/, imported 90-nat6.fw and made it executable.

But if I run the script it fails:

root@OpenWrt:/etc# /etc/firewall.d/with_reload/90-nat6.fw
nat6: Firewall config="cfg04dc81" zone="lan" zone_masq6="0".
nat6: Firewall config="cfg06dc81" zone="wan" zone_masq6="1".
nat6: Found firewall zone_name="wan" with zone_masq6="1" zone_masq6_privacy="1".
nat6: Setting up masquerading nat6 for zone_name="wan" with zone_masq6_privacy="1"
nat6: Ensuring ip6tables chain="zone_wan_postrouting" contains our MASQUERADE.
ip6tables: No chain/target/match by that name.

I went through all the FAQ and troubleshooting steps and found nothing obvious:

root@OpenWrt:/etc# uci show dhcp.lan | grep -e 'dhcpv6=' -e 'ra=' -e 'ra_management=' -e 'ndp='
dhcp.lan.dhcpv6='server'
dhcp.lan.ra='server'
dhcp.lan.ra_management='1'

Any help would be appreciated.

UPDATE:

The script is expecting on a chain called "zone_${zone_name}_postrouting", so "zone_wan_postrouting" in my case, but there is (obsiously) no such chain in my ip6tables. What needs to be configured to adapt my setup so it is as you expect it?

(Last edited by darkyat on 10 Feb 2017, 09:31)

The discussion might have continued from here.