---
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

- [OpenVPN's network protocol](https://build.openvpn.net/doxygen/network_protocol.html)
- [Data Channel Crypto module](https://build.openvpn.net/doxygen/group__data__crypto.html)
- [Does AES_cbc_encrypt add padding?](https://stackoverflow.com/questions/31226594/does-aes-cbc-encrypt-add-padding)
- [What size of initialization vector (IV) is needed for AES encryption?](https://crypto.stackexchange.com/questions/50782/what-size-of-initialization-vector-iv-is-needed-for-aes-encryption)
