I use OpenVPN relatively often, for example to get reliable IPv6-connectivity in places which don’t have IPv6 yet (miredo works well most of the time, but an own VPN is more stable). One of the things which I previously understood only a little bit was the MTU (Maximum Transfer Unit). Not configuring it properly leads to transferring more data than necessary (best case) or losing some packets entirely (worst case). The evil detail is that it only affects packets of a certain size – for example Kerberos packets are usually pretty large and thus often get dropped when your MTU is misconfigured.
MTU on the link
The MTU is a setting of the IP protocol and specifies how much data can fit into a single IP packet. Typical values for the MTU are 1500 bytes on Ethernet links or 1492 bytes on PPPoE links. You can find out the MTU by looking at your interface configuration:
$ ip link show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000 link/ether 00:1f:16:3a:f9:b8 brd ff:ff:ff:ff:ff:ff
Let’s take an ICMP packet as an example: ICMP sits on top of IP. So, we have
the IP header which is 20 bytes, plus the ICMP header which is 8 bytes (use
Wireshark and look at the "Total Length" field of the IP packet to verify
this). Therefore, with an MTU of 1500 bytes, you can fit 1500 - 20 - 8 = 1472
bytes in one packet. We can use ping(1)
to send packets with that
size:
$ ping -M do -c 1 -s 1472 www.heise.de PING www.heise.de (193.99.144.85) 1472(1500) bytes of data. 1480 bytes from www.heise.de (193.99.144.85): icmp_req=1 ttl=243 time=96.4 ms --- www.heise.de ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 96.489/96.489/96.489/0.000 ms
As you can see, ping takes the ICMP payload size of 1472
bytes, leading to a total size of 1500 bytes. I think that the -s
argument varies between operating systems, because a lot of examples on the web
use -s 1500
, which is just wrong (on Linux at least). The -M
do
parameter advises ping to set the "do not fragment" bit.
Here is an example of the output you will get when you use the wrong MTU for your link:
$ ping -M do -c 1 -s 1500 www.heise.de PING www.heise.de (193.99.144.85) 1500(1528) bytes of data. From 87.198.114.189 icmp_seq=1 Frag needed and DF set (mtu = 1500) --- www.heise.de ping statistics --- 0 packets transmitted, 0 received, +1 errors
In this case, I got an ICMP error telling me about the correct MTU size to use. This is called "Path MTU Discovery", but in some rare cases, administrators block all ICMP traffic in their firewall and therefore this feature does not work. In that case, you would just get no ping reply.
To find out the right MTU, decrease the ping size until you get a reply, then set the MTU to the total packet size. Don’t just pick one single host to test with, though – maybe the host has a misconfigured MTU :-).
MTU in OpenVPN
Above, we have figured out that the MTU indeed is 1500 bytes for our link. Now
how do we configure OpenVPN for that? I assume you are running OpenVPN using
UDP. The UDP header is 8 bytes (just like ICMP), so we will end up with 1472
bytes as the payload size. In our OpenVPN configuration, we will therefore use
the link-mtu 1472
directive. This leads to OpenVPN setting the
correct MTU on its tun0
interface:
$ ip link show dev tun0 35: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1427 state UNKNOWN link/none
The MTU is 1427 due to the OpenVPN overhead. We can verify that packets using the full MTU will arrive correctly by using ping:
$ sudo ip -4 route add 193.99.144.85 via 10.254.254.254 $ ping -M do -c 1 -s 1399 193.99.144.85 PING 193.99.144.85 (193.99.144.85) 1399(1427) bytes of data. 1407 bytes from 193.99.144.85: icmp_req=1 ttl=246 time=97.4 ms --- 193.99.144.85 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 97.420/97.420/97.420/0.000 ms
By the way, I’ve sometimes seen OpenVPN error messages saying:
Authenticate/Decrypt packet error: packet HMAC authentication failed
Seeing these only some times (while the VPN itself works) is a hint to incorrect MTU configuration.
See also
-
http://www.netheaven.com/pmtu.html
A good description of Path MTU Discovery. -
http://openvpn.net/archive/openvpn-users/2005-10/msg00354.html
A thread describing the different MTU flags which OpenVPN has.
I run a blog since 2005, spreading knowledge and experience for almost 20 years! :)
If you want to support my work, you can buy me a coffee.
Thank you for your support! ❤️