openvpn-mtu-en.md 6.4 KB


layout: page title: How large is the MTU in an OpenVPN tunnel? permalink: /blog/openvpn-mtu-en/ keywords: openvpn,mtu,overhead description: What MTU does OpenVPN have? What overhead does OpenVPN have? How does this relate to the ciphers used? lang: en feed: true

date: 2024-10-04 00:00:00 +0100

OpenVPN uses 1500 as MTU by default. However, this can lead to fragmentation of the outer VPN packets, which is generally to be avoided. It is therefore necessary to reduce the MTU in the tunnel so that no fragmentation occurs. This raises the question of how large the ideal MTU may be. Unfortunately, OpenVPN does not offer any simple documentation for this.

The actual data that is transported in the tunnel is also referred to as payload. However, various headers are presented before this data. These are used, among other things, to ensure that the packets are delivered correctly (IP routing) and to transmit various cryptographic parameters.

The process of placing several headers in front of the actual user data is also known as encapsulation.

The following encapsulations exist:

  • IP header
  • UDP/TCP header
  • OpenVPN header
  • Payload

In order to know the optimum MTU - i.e. the maximum size of the payload without fragmentation - the size of the IP header, the UDP/TCP header and the OpenVPN header must be known.

IP header

Normally, an IP header has a size of 20-40 bytes. If IPv4 is used, it is 20 bytes, with IPv6 it is 40 bytes. If you specify a DNS name rather than a fixed IP address as the endpoint, the software or operating system normally decides whether IPv4 or IPv6 should be used. I therefore recommend always using 40 bytes as the IP header.

TL;DR: 40 bytes

UDP/TCP header

In OpenVPN, you can choose between UDP and TCP as the transport protocol. UDP is generally recommended for VPN applications. The header size there is 8 bytes. With TCP, the header size is between 20 and 60 bytes. OpenVPN does not seem to enforce the use of 20 bytes. I therefore recommend using 60 bytes for TCP, the maximum size of a TCP header.

TL;DR: 8 bytes for UDP, 60 bytes for TCP

OpenVPN header

The OpenVPN header differs depending on the cipher and operating mode used. In addition, there are two different header formats P_DATA_V1 and P_DATA_V2. Modern OpenVPN clients should actually only use P_DATA_V2. To negotiate the cryptographic parameters, OpenVPN supports two methods: TLS and Preshared Key (PSK). PSK is outdated and should no longer be used. In addition, the PSK method does not support Perfect Forward Secrecy (PFS), which is a desirable cryptographic property. I assume a “modern” OpenVPN client that uses P_DATA_V2 for the following information.

AEAD ciphers / GCM mode (also CHACHA20-POLY1305)

The OpenVPN header consists of the following components:

  • 1 byte opcode and key ID (5-bit opcode and 3-bit key ID)
  • 3 bytes peer ID
  • 4 bytes packet ID
  • 16 bytes tag

TL;DR: Overhead = 24 bytes

CBC mode

The OpenVPN header consists of the following components:

  • 1 bytes opcode and key ID (5-bit opcode and 3-bit key ID)
  • 3 bytes peer ID
  • HMAC
  • IV
  • 4 bytes Packet ID
  • Only for PSK: 4 bytes Timestamp
  • Padding

If the optimum MTU is not to be calculated exactly, 16 bytes can be used for padding.

In CBC mode, the packet ID and the timestamp (for PSK) are also encrypted. If the length of this encrypted text is a multiple of 16, a padding of 16 bytes is appended. Otherwise, a padding is appended so that the length is a multiple of 16. The following algorithm can be used to calculate the optimum MTU:

  1. Calculate the temporary MTU without packet ID, timestamp or padding.
  2. Is the temporary MTU a multiple of 16?
    • If no: Determine the largest number that is less than temporary MTU + 4 (packet ID) + 4 (timestamp for PSK) and is a multiple of 16.
  3. Subtract 4 (packet ID), 4 (timestamp for PSK) and 1.

TL;DR: Overhead = 26 bytes + IV size + HMAC size + 4 bytes timestamp (for PSK)

CFB/OFB mode

The OpenVPN header consists of the following components:

  • 1 byte Opcode and Key-ID (5-bit Opcode and 3-bit Key-ID)
  • 3 bytes Peer-ID
  • HMAC
  • IV

TL;DR: Overhead = 4 bytes + HMAC size + IV size

No encryption

With the none cipher, OpenVPN offers a mode which does not encrypt the data, but only authenticates it.

The OpenVPN header then consists of the following components:

  • 1 byte opcode and key ID (5-bit opcode and 3-bit key ID)
  • 3 bytes peer ID
  • HMAC
  • 4 bytes Packet-ID
  • Only for PSK: 4 byte timestamp

TL;DR: Overhead = 8 bytes + HMAC size + 4 bytes timestamp (for PSK)

IV size

The IV of most ciphers is 16 bytes in size. The size of the IV can be found out via the block size. This can be displayed with openvpn --show-ciphers.

HMAC size

Sometimes the size of the HMAC is needed to calculate the MTU. Below is a table with the HMAC on the right and its size on the left.

HMAC size
SHA1 20 bytes
SHA256 / SHA2-256 / SHA3-256 32 bytes
SHA384 / SHA2-384 / SHA3-384 48 bytes
SHA512 / SHA2-512 / SHA3-512 64 bytes

Alternatively, you can use openvpn --show-digests to determine the sizes.

Recommended MTUs

The following table assumes that the outer MTU is 1500 bytes, that UDP is used as the transport protocol, that the IV is 16 bytes in size and that IPv6 could be used.

Encryption + Mode MTU
TLS + AEAD/GCM 1428
TLS + CBC + SHA1 1403
TLS + CBC + SHA256 1387
TLS + CBC + SHA384 1371
TLS + CBC + SHA512 1355
PSK + CBC + SHA1 1399
PSK + CBC + SHA256 1383
PSK + CBC + SHA384 1367
PSK + CBC + SHA512 1351
TLS + CFB/OFB + SHA1 1412
TLS + CFB/OFB + SHA256 1400
TLS + CFB/OFB + SHA384 1384
TLS + CFB/OFB + SHA512 1368
TLS + None + SHA1 1424
TLS + None + SHA256 1412
TLS + None + SHA384 1396
TLS + None + SHA512 1380
PSK + None + SHA1 1420
PSK + None + SHA256 1408
PSK + None + SHA384 1392
PSK + None + SHA512 1376

Sources