Running an OpenVPN server on Ubuntu with dual stack IPv6

Where should I start? It took considerable amount of time to find my way and a lot of research to make it work, but at the end I succeeded. A well working OpenVPN server running on Ubuntu 24 with IPv6 support hosted at a VPS provider. Created my own self signed certificates, used dual stack at both sides (server and client) and decided that I only use one IP IPv6 address as I haven't succeeded in allocating addresses to the OpenVPN clients. Small price I decided to pay.

As I'm making these notes days after I've made it, there might be some discrepancies or missing steps, let me know if that's the case.

  1. Sudo yourself

  2. Install openvpn and easyrsa

    apt install openvpn easy-rsa
  3. Create CA store and the main certificates (I chose to put the CA files into the home of root for safety reasons). Obviously you need to change {{SERVER-NAME}} into something meaningful.

    make-cadir /root/easy-rsa
    cd /root/easy-rsa
    ./easyrsa init-pki
    ./easyrsa build-ca
    ./easyrsa gen-req {{SERVER-NAME}} nopass
    ./easyrsa gen-dh
    ./easyrsa sign-req server {{SERVER-NAME}}
  4. Copy certificates to the openvpn config folder

    cp pki/dh.pem pki/ca.crt pki/issued/{{SERVER-NAME}}.crt pki/private/{{SERVER-NAME}}.key /etc/openvpn/
  5. Create certificate for the (first) VPN user. You don't need to copy these files, you'll only need them present on the client, so you can remove these files if you like - after going through all the steps.

    ./easyrsa gen-req {{VPN-USERNAME}} nopass
    ./easyrsa sign-req client {{VPN-USERNAME}}
  6. Make sure the user above ({{VPN-USERNAME}}) is a valid unix user, if not, you can create it:

    adduser {{VPN-USERNAME}}
  7. Create tls-auth key which I decided to use to harden my VPN server

    openvpn --genkey secret ta.key
    cp ta.key /etc/openvpn/
  8. Add unprivileged user for OpenVPN

    adduser --system openvpn
  9. Create OpenVPN config file, I used the following one for myself. Save it as /etc/openvpn/{{SERVER-NAME}}.conf

    port 1194 # Port where OpenVPN listens
    proto udp # As above but the protocol
    dev tun
    ca ca.crt # CA file you created/copied
    cert {{SERVER-NAME}}.crt # Server you created/copied, change the name to what you've chosen
    key {{SERVER-NAME}}.key # Server's private key which you created/copied, change the name to what you've chosen
    dh dh.pem
    topology subnet
    ifconfig-pool-persist /var/log/openvpn/ipp.txt
    keepalive 10 120
    tls-auth ta.key 0
    user openvpn
    group nogroup
    persist-key
    persist-tun
    status /var/log/openvpn/openvpn-status.log
    verb 3
    explicit-exit-notify 1
    server 10.8.0.0 255.255.255.0 # IPv4 range
    server-ipv6 fd00:1234:abcd::/64 # IPv6 range
    push "route-ipv6 2000::/3" # Route all IPv6 traffic into the tunnel
    push "redirect-gateway ipv6" # see above
    push "redirect-gateway def1 bypass-dhcp" # Route all IPv4 traffic into the tunnel
    tun-ipv6 # Make tunnel ipv6 aware
    tun-mtu 1400 # Otherwise you'll have a lot of trouble with Windows clients
    mssfix 1360 # see above
  10. Make the OpenVPN server start together with the server, edit the /etc/default/openvpn file, and uncomment the AUTOSTART="all" line

  11. Restart OpenVPN service so we're sure the new service is running.

    systemctl restart openvpn
  12. Allow the forwarding of IPv4 and IPv6 packets in the kernel. Edit the /etc/sysctl.d/99-sysctl.conf file and add the following lines at the end or change their values if they're already present:

    net.ipv6.conf.all.forwarding = 1
    net.ipv4.ip_forward=1

    Make the system pick up the new values

    sysctl -p
  13. Enable the port above to pass through the firewall, in case of ufw:

    ufw allow 1194/udp
  14. Find the name of your WAN facing ethernet interface (from ip addr for example) and allow routing between your tunnel and WAN adapter:

    ufw route allow in on tun0 out on {{YOUR-ETH-INTERFACE}}
  15. Add NAT masquerade to the ufw to translate the VPN client's IPv4 address into your WAN IPv4 address and back. Edit the /etc/ufw/before.rules file, add either at the top or the bottom the following:

    # START OPENVPN RULES
    # NAT table rules
    *nat
    :POSTROUTING ACCEPT [0:0]
    -A POSTROUTING -s 10.8.0.0/24 -o {{YOUR-ETH-INTERFACE}} -j MASQUERADE
    COMMIT
    # END OPENVPN RULES
  16. Add the same, but for IPv6. The file you'll need is /etc/ufw/before6.rules and you have to put the following text at the very top or at the very end (again).

    # START OPENVPN RULES
    # NAT table rules
    *nat
    :POSTROUTING ACCEPT [0:0]
    -A POSTROUTING -s fd00:1234:abcd::/64 -o {{YOUR-ETH-INTERFACE}} -j MASQUERADE
    COMMIT
    # END OPENVPN RULES
  17. Restart ufw:

    ufw disable
    ufw enable
  18. Configure the OpenVPN client, you'll need the server's public IPv4 address, the linux username you dedicated to VPN use (can be your already exising user as well) and the corresponding password and the following files:

    /etc/openvpn/ta.key
    /root/easy-rsa/pki/ca.crt
    /root/easy-rsa/pki/private/{{VPN-USERNAME}}.key
    /root/easy-rsa/pki/issued/{{VPN-USERNAME}}.crt

    I've used the following config file for the client:

    client
    dev tun
    remote {{YOUR-SERVERS-IP-ADDRESS}} 1194 udp
    nobind
    tls-client
    key-direction 1
    ping 15
    ping-restart 45
    persist-tun
    persist-key
    mute-replay-warnings
    verb 3
    pull
    auth-user-pass
    connect-retry 1
    reneg-sec 3600
    remote-cert-tls server
    redirect-gateway def1
    <ca>
    {{CONTENTS-OF:/root/easy-rsa/pki/ca.crt}}
    </ca>
    <cert>
    {{CONTENTS-OF:/root/easy-rsa/pki/issued/{{VPN-USERNAME}}.crt}}
    </cert>
    <key>
    {{CONTENTS-OF:/root/easy-rsa/pki/private/{{VPN-USERNAME}}.key}}
    </key>
    <tls-auth>
    {{CONTENTS-OF:/etc/openvpn/ta.key}}
    </tls-auth>

    Save this file on the computer which you'll use as a client and import it into your favorite OpenVPN client.

That might be it! Attempt to make a connection, when asked for the username and password you will have to use the credentials you created.

Test your connectivity on http://ip4.me/External link and https://ip6only.me/,External link both of these should show you your server's IPv4 and IPv6 addresses.

If you run into errors, you can consult the journal, check the routing tables or leave a comment here so I can learn something too.

May-28-2025
firewall, network, ubuntu, linux, OpenVPN, tunnel

Leave a comment

Comments (if any)

Don't know what will come here, let's wait and see... But in the first instance it will be a login box (for myself):

Login