---
layout: page
title: Wie groß ist das MTU in einem OpenVPN-Tunnel?
permalink: /blog/openvpn-mtu-de/
keywords: openvpn,mtu,overhead
description: Welches MTU hat OpenVPN? Welches Overhead hat OpenVPN? Wie hängt dies mit den verwendeten Chiffren zusammen?
lang: de
feed: true
date: 2024-10-04 00:00:00 +0100
---

OpenVPN verwendet standardmäßig 1500 als MTU. Dies kann jedoch zu Fragmentierung der äußeren VPN-Pakete führen, was man im Allgemeinen vermeiden möchte. Daher ist es notwendig, das MTU im Tunnel so zu senken, dass keine Fragmentierung auftritt. Daher stellt sich die Frage, wie groß das optimale MTU sein darf. OpenVPN bietet dafür leider keine einfache Dokumentation an.

Die eigentlichen Daten, welche im Tunnel transportiert werden, werden auch als Nutzdaten oder Payload bezeichnet. Vor diesen Daten werden jedoch noch verschiedene Header vorgestellt. Diese dienen unter anderem dazu, dass die Pakete richtig zugestellt werden (IP-Routing) als auch dafür, verschiedene kryptografische Parameter zu übertragen.

Der Prozess, dass mehrere Header den eigentlichen Nutzdaten vorangestellt werden, bezeichnet man auch als Kapselung.

Folgende Kapseln existieren:

- IP Header
- UDP/TCP Header
- OpenVPN Header
- Nutzdaten

Um also das optimale MTU - also die maximale Größe der Nutzdaten, ohne dass es zu Fragmentierung kommt - zu kennen, muss die Größe des IP-Headers, des UDP/TCP-Header sowie des OpenVPN-Headers bekannt sein.

## IP-Header

Im Normalfall hat ein IP-Header eine Größe von 20-40 Bytes. Wenn IPv4 verwendet wird, sind es 20 Bytes, bei IPv6 sind es 40 Bytes. Wenn man als Endpunkt nicht eine feste IP-Adresse, sondern einen DNS-Namen angibt, entscheidet im Normalfall die Software oder das Betriebssystem, ob IPv4 oder IPv6 verwendet werden soll. Ich empfehle daher, immer mit 40 Bytes als IP-Header zurechnen.

TL;DR: 40 Bytes

## UDP/TCP-Header

In OpenVPN kann man zwischen UDP und TCP als Transportprotokoll wählen. Im Allgemeinen wird für VPN-Anwendungen UDP empfohlen. Dort beträgt die Headergröße 8 Byte. Bei TCP beträgt die Headergröße zwischen 20 und 60 Bytes. OpenVPN scheint die Verwendung von 20 Bytes nicht zu erzwingen. Ich empfehle daher, bei TCP mit 60 Bytes, der maximalen Größe eines TCP-Headers, zu rechnen.

TL;DR: 8 Bytes bei UDP, 60 Bytes bei TCP

## OpenVPN-Header

Der OpenVPN-Header unterscheidet sich je nach verwendeter Chiffre und verwendetem Betriebsmodus. Zusätzlich gibt es zwei unterschiedliche Headerformate `P_DATA_V1` und `P_DATA_V2`. Moderne OpenVPN-Clients sollten eigentlich ausschließlich `P_DATA_V2` verwenden. Um die kryptografischen Parameter auszuhandeln, unterstützt OpenVPN zwei Methoden: TLS und Preshared Key (PSK). Dabei ist PSK veraltet und sollte nicht mehr verwendet werden. Darüber hinaus unterstützt die PSK-Methode kein Perfect Forward Secrecy (PFS), was eine wünschenswerte kryptografische Eigenschaft ist. Ich gehe für folgende Angaben von einem "modernen" OpenVPN-Client aus, welcher `P_DATA_V2` verwendet.

### AEAD-Chiffren / GCM-Betriebsmodus (auch CHACHA20-POLY1305)

Der OpenVPN-Header besteht aus folgenden Komponenten:

- 1 Byte Opcode und Key-ID (5-bit Opcode und 3-bit Key-ID)
- 3 Bytes Peer-ID
- 4 Bytes Packet-ID
- 16 Bytes tag

TL;DR: Overhead = 24 Bytes

### CBC-Betriebsmodus

Der OpenVPN-Header besteht aus folgenden Komponenten:

- 1 Bytes Opcode und Key-ID (5-bit Opcode und 3-bit Key-ID)
- 3 Bytes Peer-ID
- HMAC
- IV
- 4 Bytes Packet-ID
- Nur bei PSK: 4 Bytes Zeitstempel
- Padding

Wenn das optimale MTU nicht genau berechnet werden soll, kann man für das Padding 16 Bytes verwenden.

Im CBC-Betriebsmodus wird die Packet-ID und der Zeitstempel (bei PSK) mit verschlüsselt. Wenn die Länge dieses verschlüsselten Text ein Vielfaches von 16 ist, wird ein Padding von 16 Bytes angehängt. Ansonsten wird ein Padding angehängt, sodass die Länge ein Vielfaches von 16 ist.
Um das optimale MTU zu berechnen, kann folgendes Algorithmus verwendet werden:
1. Berechne das temporäre MTU ohne Packet-ID, Zeitstempel oder Padding.
2. Ist das temporäre MTU ein Vielfaches von 16?
    - Wenn nein: Bestimme die größte Zahl, die kleiner als temporäres MTU + 4 (Packet-ID) + 4 (Zeitstempel bei PSK) ist und ein Vielfaches von 16 ist.
3. Subtrahiere 4 (Packet-ID), 4 (Zeitstempel bei PSK) und 1.

TL;DR: Overhead = 26 Bytes + IV-Größe + HMAC-Größe + 4 Byte Zeitstempel (bei PSK)

### CFB/OFB-Betriebsmodus

Der OpenVPN-Header besteht aus folgenden Komponenten:

- 1 Byte Opcode und Key-ID (5-bit Opcode und 3-bit Key-ID)
- 3 Bytes Peer-ID
- HMAC
- IV

TL;DR: Overhead = 4 Bytes + HMAC-Größe + IV-Größe

### Keine Verschlüsselung

OpenVPN bietet mit der `none` Chiffre einen Modus an, welcher die Daten nicht verschlüsselt, sondern nur authentifiziert.

Der OpenVPN-Header besteht dann aus folgenden Komponenten:

- 1 Byte Opcode und Key-ID (5-bit Opcode und 3-bit Key-ID)
- 3 Bytes Peer-ID
- HMAC
- 4 Bytes Packet-ID
- Nur bei PSK: 4 Byte Zeitstempel

TL;DR: Overhead = 8 Bytes + HMAC-Größe + 4 Byte Zeitstempel (bei PSK)

## IV-Größe

Das IV der meisten Chiffren ist 16 Byte groß. Die genaue Größe des IV lässt sich über die Blockgröße herausfinden. Diese kann man mit `openvpn --show-ciphers` anzeigen.

## HMAC-Größe

Manchmal wird die Größe des HMACs benötigt, um das MTU zu berechnen. Im Folgenden ist eine Tabelle mit der HMAC auf der rechten Seite und ihrer Größe auf der linken Seite.

| HMAC | Größe |
| --- | --- |
| SHA1 | 20 Bytes |
| SHA256 / SHA2-256 / SHA3-256 | 32 Bytes |
| SHA384 / SHA2-384 / SHA3-384 | 48 Bytes |
| SHA512 / SHA2-512 / SHA3-512 | 64 Bytes |

Alternativ kann mit `openvpn --show-digests` die Größen ermitteln.

## Empfohlene MTUs

In der folgenden Tabelle wird angenommen, dass das äußere MTU 1500 Bytes beträgt, das UDP als Transportprotokoll verwendet wird, dass der IV 16 Byte groß ist und dass IPv6 verwendet werden könnte.

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

## Quellen

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