Timothy Baldwins answer put me on the right track, although the answer was rather cryptic. IPv6 neighbor advertisements/solicitation is like ARP for IPv6. It's used to "see" other machines on the network. The router send a neighbor solicitation on which the machine (server or client) should reply on with a neighbor advertisement.
net.ipv6.conf.all.forwarding set to
1, neighbor advertisements and solicitations are not forwarded. To make eth0 forward neighbor advertisements and solicitations, eth0 should be set as proxy for the IPv6 address of the client behind tap0, and proxying for neighbor stuff should be enabled for eth0:
echo 1 > /proc/sys/net/ipv6/conf/eth0/proxy_ndp
/sbin/ip -6 neigh add proxy 2001:db8::100:abc:2 dev eth0
Unfortunately, it's not possible to retrieve the list of proxies added, nor does
ip -6 show error messages on repeatedly executing the command. Neither am I sure if "neigh del proxy" works, it does not give an error message and the C source is not really meaningful to me.
As I do not want to do everything manually, I've created a script which does the work for me.
IPv6 addresses are based on the IPv4 part (the 1 in 10.8.0.1). The prefix and netmask are stored in
The next steps are made for setting up OpenVPN with encrypted IPv4/IPv6 connectivity to the Internet over a native IPv4 connection. RSA keys and tls-auth are used for authentication and MITM prevention.
/etc/openvpn/variables contains variables which are used for the up script (run on startup, after creation of tap0 device) and client-connect script (run after the client has authenticated).
# this prefix is handled out by the provider, replace it with your own prefix
# netmask, 2001:db9::abc:0000 - 2001:db9::abc:FFFF
/etc/openvpn/server-clientconnect.sh is executed as root and makes sure that IPv6 is routed properly by adding the IPv6 address to the eth0 proxy. Because
client-connect is called after OpenVPN switched to the user specified by the
sudo is needed to give the script sufficient permissions to run as root. Of course, variables should be checked before using, the number should be between and including 2 ad 254. (1 is the gateway, 255 the broadcast address).
if [ -z "$ifconfig_pool_remote_ip" ]; then
echo "Missing environment variable."
ipp=$(echo "$ifconfig_pool_remote_ip" | cut -d. -f4)
if ! [ "$ipp" -ge 2 -a "$ipp" -le 254 ] 2>/dev/null; then
echo "Invalid IP part."
hexipp=$(printf '%x' $ipp)
/sbin/ip -6 neigh add proxy $pfx:$hexipp dev eth0
To make this work, the user
vpn should be allowed to run the script while preserving
$ifconfig_pool_remote_ip which contains the remote network IPv4 address. Add the next lines to the sudoers file by executing
sudo visudo and appending:
vpn ALL=NOPASSWD: /etc/openvpn/server-clientconnect.sh
/etc/openvpn/server-up.sh enables IPv4, IPv6 forwarding (eth0+tap0 did not work, it really had to be
all) and neighbor proxy on eth0. It adds the gateway address to servers
/sbin/ip -6 addr add $pfx:1/$pfxlen dev $dev
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 1 > /proc/sys/net/ipv6/conf/eth0/proxy_ndp
Finally, the OpenVPN configuration file at
server 10.8.0.0 255.255.255.0
client-connect "/usr/bin/sudo -u root /etc/openvpn/server-clientconnect.sh"
# encrypt all traffic
push "redirect-gateway def1"
# keep the same IP addresses each time
keepalive 10 120
tls-auth ta.key 0
# OpenVPN will switch to this user, it is also used for sudo
For completeness, permissions and ownerships of files in
drwx------ root root .
-rw------- root root ca.crt
-rw------- root root dh1024.pem
drwx------ root root easy-rsa <-- left from creation of keys
-rw------- root root ipp.txt
-rwx------ root root server-clientconnect.sh
-rw------- root root internet.conf
-rw------- root root variables
-rwx------ root root server-up.sh
-rw------- root root server.crt
-rw------- root root server.key
-rw------- root root ta.key
-rwx------ root root update-resolv-conf <-- this was installed by default
itpables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 10.8.0.0/24 -i tap0 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
ip6tables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A FORWARD -s 2001::db8::abc:0/112 -i tap0 -o eth0 -j ACCEPT
Configuration on client
remote 126.96.36.199 1194
tls-auth ta.key 1
ca.key are the same files from the server.
home.crt are files, created on the server.
client-up.sh adds the IPv6 address and route (based on IPv4 address):
hexippart=`printf '%x' "$(echo $ifconfig_local | cut -d. -f4)"`
/sbin/ip -6 addr add $pfx:$hexippart/$pfxlen dev $dev
/sbin/ip -6 route add default via $pfx:1 dev $dev
The guide at http://www.ipsidixit.net/2010/03/24/239/ was very helpful and OpenVPN manual page is useful for information about various settings.