in networking, Tools

Build a OpenVPN server on Ubuntu to provide a IPv6 tunnel over IPv4

Like a lot of computer engineers, I use to work from various places such as my office, home, at a customer’s, in the train… It’s important to always have same LAN/Internet configuration wherever I am and the best solution to achieve this is of course using a VPN.

If you have a dedicated server connected to the Internet running Ubuntu (or any other Linux OS), this can be achieved quite easily and for totally free with OpenVPN. OpenVPN clients are available on almost all platforms, Linux, MacOS, Windows, Android and iOS. If your server has IPv6 connectivity, you can also take advantage of it, even if all you have is a terrible IPv4 connection with a lot of restrictions.

Here is how I did it, on a fresh Ubuntu 14.04 LTS installation.

All commands in this tutorial must be run as root.

We consider the server has external IPv4 and IPv6 aaaa:bbbb:cccc:dddd::/64 on interface eth0. The subnet aaaa:bbbb:cccc:dddd:80::/112 is allocated to the VPN clients on interface tun0.

Enable NAT and NDP proxy

The first step is to enable NAT for IPv4 and NDP proxy for IPv6. We could do NAT with IPv6 but it’s worthless since only the IP address of the VPN server would be reachable externally. NDP proxy is the only way to make the clients directly reachable from the Internet using their IPv6 address.

First, allow the server’s kernel to forward traffic from client devices out to the Internet.
vim /etc/sysctl.conf

Uncomment/add the following lines:

Now we can enable NAT for IPv4 (considering eth0 is the interface that is connected to the Internet):
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables-save > /etc/iptables.rules

To enable NAT again after reboot, create the following up script:
vim /etc/network/if-up.d/iptables

Make the script executable.
chmod +x /etc/network/if-up.d/iptables

You can now restart the networking services
sysctl -p
/etc/init.d/networking restart

Install OpenVPN on the server

First of all, update all your packages.
apt-get update

Then install the OpenVPN packages.
apt-get install openvpn easy-rsa

Generate server certificate and key

Here comes the boring part: generating the certificate files and other security-related stuff that is necessary to make the connection possible.

First copy over the Easy-RSA generation scripts.
cp -r /usr/share/easy-rsa/ /etc/openvpn

Then create the storage directory for the generated keys.
mkdir /etc/openvpn/easy-rsa/keys

Now, modify the default values that will be used to build the certificates. This will avoid you to type them every time you generate a new certificate. Edit the file /etc/openvpn/easy-rsa/vars to modify the following keys:
vim /etc/openvpn/easy-rsa/vars

The server keys will be named server so in the same file, also modify the KEY_NAME value as follows:


Now generate the Diffie-Hellman parameters. This takes a few minutes to process so feel free to take a break and a cup of coffee.
openssl dhparam -out /etc/openvpn/dh2048.pem 2048

Then, build the certificate authority (CA). You will be invited to modify the values, just press [ENTER] to keep the information you previously entered in the vars file.
cd /etc/openvpn/easy-rsa
. ./vars

It’s now time to generate the certificate and the key for the server. As before, you will be invited to modify the values. Leave the 2 last fields blank (challenge password and optional company name) then press Y.
cd /etc/openvpn/easy-rsa
./build-key-server server

When you’re done, copy the files to the OpenVPN directory.
cp /etc/openvpn/easy-rsa/keys/{server.crt,server.key,ca.crt} /etc/openvpn

Server configuration

Here is an example of configuration for the following settings:

  • Full IPv6 connectivity over IPv4.
  • IPv4 TCP connection on port 443. The default setting (UDP 1194) may offer better performance but may be blocked on some connections such as mobile networks.
  • Clients can communicate with each other which can be useful if you are developing a mobile website and you want to test it directly on the device.
  • Fixed IP addresses for some specific clients, for example for the laptop on which the web server of the development website is running.
  • NDP proxying is enabled on demand using client-connect scripts and provides two-way Internet access to the clients.

First of all, create a vpn user for the daemon:
sudo useradd -r -s /bin/false vpn

Create the client config directory:
mkdir /etc/openvpn/ccd

Create a OpenVPN variables file that will be used by the client connection scripts. Modify the tunnel subnet prefix by yours:
sudo vim /etc/openvpn/variables

Create the and scripts. These scripts will create and remove the NDP proxy rules for each connecting client.
sudo vim /etc/openvpn/

sudo vim /etc/openvpn/

Make the scripts executable.
chmod +x /etc/openvpn/
chmod +x /etc/openvpn/

OpenVPN needs root privileges to run the scripts so add the following in the sudoers file:

Now, let’s create the main config file:
vim /etc/openvpn/server.conf

Start the server

The server should now be fully operational by starting its service.
service openvpn restart

You can check if it’s correctly running by typing:
service openvpn status

Client configuration

The last step consists in creating the configuration files for each client. The same client can’t open simultaneous sessions so it’s recommended to create a client configuration per user and per device “Peter PC, Paul iPhone, Mary laptop…”.

Let’s create a configuration for Nicolas’s iPhone, that we’ll name iphone-nicolas.

We first need to create the key and certificate, just the same way we did for the server. Leave the 2 last fields blank (challenge password and optional company name) then press Y.
cd /etc/openvpn/easy-rsa
source ./vars
./build-key iphone-nicolas

Now download these 3 files on your workstation:

  • /etc/openvpn/easy-rsa/keys/ca.crt
  • /etc/openvpn/easy-rsa/keys/iphone-nicolas.crt
  • /etc/openvpn/easy-rsa/keys/iphone-nicolas.key

Then, create the .ovpn client config file that you will then provide to the end user. Replace By your VPN server IP address or domain name. You may have to comment the user nobody and group nobody statements on some Unix OS (for example when using Tunnelblick on MacOS X).

If you want to set a static IP for some clients, you have to create a configuration file named after the client name on the server. For example, to give IPv4 and IPv6 aaaa:bbbb:cccc:dddd:80::1001/112 to the client iphone-nicolas:

vim /etc/openvpn/ccd/iphone-nicolas


If everything went fine, you should now be able to use IPv6 services using your OpenVPN server. A good way to find out if it’s working is to do a IPv6 traceroute on the client:

You can also test your setup compatibility by heading to with a IPv6-capable browser such as Google Chrome.