The way a VPN works is quite simple, a client connects to a server, a ciphered tunnel is created between the client and the server. And as soon as this tunnel is up and running, the client and the server start to exchange their network traffic trough that tunnel. There are many possible applications to create with a such tool, this article focus on the following(s):
- Reaching the VPN server through both IPv4 and IPv6
Table of contents
- A working Debian-based server
- The Debian server has IPv4 enabled and fully working
- The Debian server has IPv6 enabled and fully working
- An installed and working OpenVPN server >= 2.4.0 (latest 2.4.x stable is recommended)
- The OpenVPN server should already been configured to be reachable through IPv4
- The OpenVPN server is configured to carry VPN traffic through UDP
After a few searches, it seems to be pretty easy to activate both IP stacks, just need to replace
proto udp by
proto udp6 into the
server.conf file. So by forcing only IPv6 on the server side, it enables both IP stack… How is it possible ? That has simply nothing to do with OpenVPN, it is a feature of the Linux kernel. It seems to be enabled by default, but to be sure, it is possible to check the status of this parameter with the sysctl command. The parameter name is net.ipv6.bindv6only and has to have its value set to 0 to enable both IP stack when an IPv6 binding is done.
firstname.lastname@example.org:~# sysctl net.ipv6.bindv6only net.ipv6.bindv6only = 0
This parameter is not really new, it has existed since 2003 and has been introduced since Linux 2.4.21 and 2.6. See IPV6_V6ONLY in IPv6 manpage.
Do not expect to see this double binding through command like
ss, it is totally transparent, only IPv6 will show up.
email@example.com:~# lsof -i -P -n | grep openvpn COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME openvpn 1234 nobody 7u IPv6 9876543 0t0 UDP *:1194
firstname.lastname@example.org:~# ss -nulp | grep openvpn State Recv-Q Send-Q Local Address:Port Peer Address:Port UNCONN 0 0 :::1194 :::* users:(("openvpn",pid=1234,fd=42))
At this point, I was a little bit confuse about the OpenVPN configuration lines
proto udp4, and
These parameters allow to have impact on two different family of protocols, transport and network. It would have been simpler to understand if two different kind of parameters have existed, one for each protocol.
To add more complexity, these parameters exist in both client and server configuration files. On the server side, it will impact what IP version the server is listening on. On the client side, it will impact what IP version the client pick to connect the server. That’s two different mechanisms! I apologize for those looking for difference between UDP and TCP, I mainly focused on the network layer. Here is a summary of what I found.
|configuration||on the server side||on the client side|
|depends (1)||depends (2)|
|IPv4 only||IPv4 only|
|IPv6 only or IPv6 +IPv4 (3)||IPv6 only|
(1) that was really hard to find details about that one. I had to read OpenVPN source code to have a better idea of it. What you have to remember is that OpenVPN prefers to pick IPv6 stack when it has the choice. But OpenVPN also asks the operating system which IP stack it should use to create a server. If the operating system answers to use IPv4 stack, OpenVPN will use it even if the IPv6 stack works perfectly. So don’t be surprised if most of the time, with the parameter
proto udp, your server uses the IPv4 stack only.
If you are curious to know what IP stack your system prefers, just start an OpenVPN server with the parameter
proto udp. In the log file, you should see a line like this
Could not determine IPv4/IPv6 protocol. Using AF_INET. Meaning that no stack choice has been made by configuration and the OpenVPN took the one suggested by the operating system. In this example, the selected one is AF_INET, meaning IPv4. (explanation for this log line)
(2) client will also asked to the operating system which IP stack to use to connect a server. But with a huge difference, if the first IP stack does not work, a fallback mechanism will try the second IP stack.
(3) bind to both IP stacks only if the parameter
net.ipv6.bindv6only is set to 0. Otherwise it will only use the ipv6 stack.
I was curious to know how OpenVPN was asking the system the IP stack to use. It uses the function
getaddrinfo. (manpage) This function allow to ask a list of IP for the local host or for any remote host. The order of the list will depend of the system preferences. If the system prefers IPv6, that will be the first addresses in the list. But if the system prefers IPv4, IPv6 addresses will be at the end of the list and IPv4 addresses at the beginning.
With the configuration line
proto udp6 in the OpenVPN server configuration, and the parameter
net.ipv6.bindv6only set to 0 on the server side, it is now possible to reach the OpenVPN server through both ipv4 and IPv6.
For obvious security reasons, the following files are not provided: ca.crt, crl.pem, dh.pem, server.crt, server.key, ta.key
I struggled for quite a while with a OpenVPN server behind a DSLite internet connection. The client would just not connect because the server config contained
udp6. My misconception was, that
proto udpwould eventually listen to both IPv4 and IPv6, if available. I fixed it by myself with some research and trial and error but could not really grasp why
proto udpwould not work. Then I found your article 😀
Thanks for explaining the differences of these options cleary, they are imho not documented as thoroughly as they could.
this concise and clear explanation helped me a lot while setting up an OpenVPN server behind a DSlite (native IPv6 only) tunnel. I think it is pretty strange that it is so hard to find a decent and clear explanation of these important options and how they behave under certain circumstances.
Thanks for sharing your findings.