Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What I'm trying to do is to route IPv6 traffic through a vpn tunnel. That way, I should be able to use IPv6 in a network that doesn't support IPv6.

I have a VPS which has an IPv6 block assigned. Part of this block I want to use for openvpn clients. The range I had in mind was 2001:db8::111:800:0/112 (prefix is anonymized), because openvpn only supports /64 and /112 as subnets.

IPv6 through the tunnel is already working, from the client, I can ping the server (2001:db8::111:800:1), and also interfaces on the server (2001:db8::111:100:100 and 2001:db8:216:3dfa:f1d4:81c0).

Though, when trying to ping google.com from the client, I get no response (ping timeout). In order to debug this issue, I have used tcpdump to capture traffic on the server, and I can see the ping packets going out, but no replies comming back. Adding log rules to ip6tables shows the same, packets going out, but nothing comming in.

I used an online traceroute tool which gets a timeout from my server. I also tried to set the ip directly on the interface, which does result in the ip (2001:db8::111:800:1001) to be reachable, so I think this is a routing problem.

I have enabled forwarding for ipv6 through /proc/sys/net/ipv6/conf/all/forwarding. ip6tables has policy allow for all chains.

My question is, what exactly is needed for linux to accept that packet for an ip that is not assigned to an interface and route it further? Just a route that exists doesn't seem enough.

Here is the setup for my client and server. Please let it know if more information is needed.


# ip -6 addresses
10: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qlen 100
    inet6 2001:db8::111:800:1001/112 scope global 
       valid_lft forever preferred_lft forever

# ip -6 routes
2001:db8::111:800:0/112 dev tun0  proto kernel  metric 256 
2000::/3 dev tun0  metric 1024 


# ip -6 address
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2001:db8:216:3dfa:f1d4:81c0/64 scope global dynamic 
       valid_lft 86254sec preferred_lft 14254sec
    inet6 2001:db8::111:100:100/128 scope global 
       valid_lft forever preferred_lft forever
12: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qlen 100
    inet6 2001:db8::111:800:1/112 scope global 
       valid_lft forever preferred_lft forever

# ip -6 route
2001:db8::111:100:100 dev eth0  proto kernel  metric 256 
2001:db8::111:800:0/112 dev tun0  proto kernel  metric 256 
2001:db8::/64 dev eth0  proto kernel  metric 256  expires 86194sec
default via fe80::230:48ff:fe94:d6c5 dev eth0  proto ra  metric 1024  expires 1594sec
share|improve this question
Possible you're looking for POSTROUTING ... MASQUERADE in the nat table. But I am not sure I understand completely. Are you trying to tunnel the IPv6 traffic? If so, do you have the respective facilities set up? Are -p ipv6 packets allowed in the IPv4(!) rules? – 0xC0000022L Jun 12 '14 at 13:10
Do you have the IP config of the router (on eth0)? Do you control the router? (can you add routes?) – ysdx Jun 12 '14 at 15:41
Try using the iptables raw table TRACE target (maybe not so much here), ip neighbour, and ip route get. Also, please specify who is pinging google.ca. – pilona Jun 13 '14 at 1:32
Pinging google.com or goole.com.? – totti Jun 13 '14 at 7:33
@totti google.com, was a typo – Ikke Jun 13 '14 at 7:35
up vote 6 down vote accepted

You need to tell your router to use your server for this VPN subnet: the correct solution to your problem is to add a route on the router for the OpenVPN subnet.

If you can't do this because you can't touch the router, another solution is to setup a NDP proxy for the clients on the eth0 link.

As you're using a VPS you probably can't add routes to the router: you probably have to use the second solution.

Add a route for the subnet

The correct solution to your problem is to tell the router that the VPN subnet must be routed via the OpenVPN server (this is for Linux):

ip route add 001:db8::111:800::/112 via 2001:db8::111:100:100

You have to enable IPv6 forwarding on the server:

sysctl sys.net.ipv6.conf.all.forwarding=1

NDP proxy

It seems the router is configured to send your whole IPv6 range on the eth0 link: you can setup a NDP proxy.

You should see NDP requests on the eth0 interface of the server for your OpenVPN subnet when trying to access the rest of internet from the client.

You need to enable IPv6 forwarding on the server as well and NDP proxy:

sysctl -w net.ipv6.conf.all.proxy_ndp=1

subnet NDP proxy

The Linux kernel does not allow to add a NDP proxy for a subnet but only for individual IPs. You can use a daemon (such as ndppd to setup a NDP proxy for a whole subnet (never used it).

Per IP NDP proxy

Another solution is to can add a NDP proxy for each IPv6 of the VPN subnet:

for i in $(seq 0 65535) ; do
  ip neigh add proxy 2001:db8::111:800:$(printf %x $i) dev tun0

This should work as you have a compatatively small number of IPs in the OpenVPN subnet.

Dynamic NDP proxy with OpenVPN hooks

You should be able to use OpenVPN hooks to add NDP proxy dynamicaly.

Add hook in the OpenVPN server conf:

learn-address /etc/openvpn/learn-address

With the following learn-address script:



case "$action" in
    add | update)
        ip neigh replace proxy "$addr" dev tun0
        ip neigh del proxy "$addr" dev tun0

See this thread.

Short answer

for i in $(seq 0 65535) ; do
  ip neigh add proxy 2001:db8::111:800:$(printf %x $i) dev tun0
share|improve this answer
Thanks, I'll look into it. I now understand the problem. ipsidixit.net/2010/03/24/239 contains more details about this. – Ikke Jun 13 '14 at 6:50
I have the ip from the client as neighbour proxy. I have enabled sys.net.ipv6.conf.all.proxy_ndp, but I still cannot ping google.com. When I check the server, I see ndp solications packets comming in on eth0, but no advertisements going out. – Ikke Jun 13 '14 at 16:01
After installing and setting up npd6 it suddenly works! – Ikke Jun 13 '14 at 16:15

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.