How to calculate the right MTU size for WireGuard
WireGuard might not work for you under specific conditions, such as when using the internet via PPPoE. This could happen when the default MTU size of 1420 bytes is too large. But why could that happen, and how do you calculate the right MTU size?
Packet structure
The maximum MTU for cable and fiber optic connections is 1500 bytes. However, for DSL connections established via PPPoE, an additional 8-byte header is required, which changes the maximum MTU to 1492 bytes.
The IPv4 header takes up an additional 60 bytes. But if you use IPv6, it will be 80 bytes.
Since WireGuard uses UDP by default, an additional 8 bytes are needed for the UDP header.
Then comes the WireGuard header itself, which consists of1:
- 4-byte type;
- 4-byte key index;
- 8-byte nonce;
- 16-byte authentication tag;
- n-byte encrypted data;
This makes the WireGuard header a total of 32 bytes.
Calculating the right MTU size
So, let’s calculate how many bytes per packet we need for WireGuard via DSL with IPv4:
1500 (maximum MTU)
- 8 (PPPoE header)
- 60 (IPv4 header)
- 8 (UDP header)
- 32 (WireGuard header)
------
= 1392 bytesUnder these conditions, the maximum MTU is 1392 bytes.
A little experiment
If you want to test that yourself, you can make an experiment with ping.
You’ll need the following options:
-s <packet_size>- Specify the number of data bytes to be sent. The default is 56, which translates into 64 ICMP data bytes when combined with the 8 bytes of ICMP header data;-D- Set the “Don’t Fragment” bit;
So, what you want to do, is to run the ping and decrease the maximum <packet_size> of 1500 by 2 bytes with each execution, until the ping starts working:
ping -t3 -D -s <packet_size> 1.1.1.1If you have a DSL internet connection with IPv4 and have disabled the VPN, it will start working when the packet size is set to 1424:
~> ping -t3 -D -s 1424 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 1424 data bytes
1432 bytes from 1.1.1.1: icmp_seq=0 ttl=59 time=26.717 ms
1432 bytes from 1.1.1.1: icmp_seq=1 ttl=59 time=23.710 ms
1432 bytes from 1.1.1.1: icmp_seq=2 ttl=59 time=19.754 msB-b-but…
Wait, didn’t we calculate the maximum to be 1392 bytes? What happened?
It’s simple. The ICPM used for ping adds 8 bytes, so you see 1432 bytes in the output. Another 60 bytes are added by the IPv4 header. So in total, we have a maximum of 1492 bytes (1424 + 8 + 60).