VPN-Server vor DDoS-Angriffen schützen

Veröffentlicht am 38 Min. Lesezeit

Warum die Adresse eines VPN-Servers öffentlich sein muss und in jeder Clientdatei steht, was WireGuard mit mac1 und Cookie-Antwort selbst leistet, wie tls-crypt OpenVPN entlastet, und ab welcher Angriffsgröße nur noch Filterung im Netz vor dem Server hilft.

Ein VPN-Server hat ein Problem, das ein Webserver nicht hat: Seine IP-Adresse muss öffentlich erreichbar sein, sonst käme kein einziger Client herein, und sie steht im Klartext in der Konfigurationsdatei jedes einzelnen Nutzers. Man kann sie nicht hinter einem CDN verstecken, und man kann sie nicht wechseln, ohne jedes Gerät neu einzurichten. Genau deshalb ist Filterung im Netz vor dem Server bei einem VPN nicht eine Möglichkeit unter mehreren, sondern die einzige.

Dieser Beitrag zeigt zuerst, warum VPN-Server überhaupt angegriffen werden, dann was WireGuard und OpenVPN aus eigener Kraft gegen eine Flut ausrichten, danach welche Messwerte einen Angriff belegen, und zum Schluss, welche Regeln auf dem Server wirklich etwas bringen und wo sie aufhören. Alle Angaben beziehen sich auf Debian 12, Debian 13, Ubuntu 22.04 LTS oder Ubuntu 24.04 LTS. Die Befehle sind für root geschrieben, als normaler Benutzer stellen Sie sudo voran. Läuft der Angriff gerade, ändern Sie zuerst nichts an der Konfiguration und starten den Dienst nicht neu: Sichern Sie zuerst die Messwerte, nach dem Angriff sind sie weg.

Warum ein VPN-Server anders angegriffen wird als ein Webserver

Bei einem Webserver ist die öffentliche Adresse austauschbar. Sie stellen einen Proxy davor, Sie ziehen die Anwendung auf eine andere Maschine, Sie ändern einen A-Eintrag im DNS, und nach wenigen Minuten landet der Verkehr woanders. Bei einem VPN-Server funktioniert keiner dieser drei Wege sauber. Das ist kein Konfigurationsfehler, sondern liegt in der Natur der Sache.

Die Adresse steht in jeder Konfigurationsdatei

Ein VPN-Client braucht einen Endpunkt, und dieser Endpunkt ist eine IP-Adresse oder ein Name, der zu einer IP-Adresse aufgelöst wird. Bei WireGuard steht er in der Zeile Endpoint = 203.0.113.10:51820 der Clientdatei, bei OpenVPN in der Zeile remote 203.0.113.10 1194. Jeder, der jemals ein Profil bekommen hat, kennt die Adresse: der ausgeschiedene Mitarbeiter, dessen Profil niemand gelöscht hat, der Familienangehörige, der die Datei weitergegeben hat, und jeder, der ein Telefon mit einem importierten Profil verloren hat.

Dazu kommt ein Unterschied zwischen den beiden Protokollen, der genau hier zählt. WireGuard löst einen Hostnamen im Endpunkt genau einmal auf, nämlich beim Start der Schnittstelle mit wg-quick up. Ändert sich der DNS-Eintrag danach, merkt eine laufende Verbindung davon nichts, sie schickt weiter an die alte Adresse. Deshalb liegt den wireguard-tools das Hilfsskript reresolve-dns.sh bei, das den Namen regelmäßig neu auflöst und den Peer per wg set aktualisiert. OpenVPN verhält sich anders: remote darf mehrfach vorkommen, und zusammen mit resolv-retry infinite löst der Client bei jedem Verbindungsversuch neu auf. Ein Adresswechsel ist bei OpenVPN also machbar, bei WireGuard nur mit Zusatzarbeit auf jedem Gerät.

Warum ein CDN vor einem VPN-Server nicht funktioniert

Ein CDN nimmt HTTP- und HTTPS-Anfragen entgegen, liest den Hostnamen aus der TLS-Erweiterung SNI oder aus dem Host-Kopf und reicht sie an den richtigen Ursprungsserver weiter. Ein VPN liefert nichts davon. WireGuard spricht ein eigenes UDP-Protokoll ohne HTTP-Schicht und ohne TLS, es gibt also weder einen Hostnamen im Paket noch eine Sitzung, die sich an anderer Stelle beenden und neu aufbauen ließe. OpenVPN über UDP genauso. Selbst OpenVPN über TCP auf Port 443 ist kein HTTPS: Es sieht nur so aus, solange niemand hinsieht, und ein HTTP-Proxy kann damit nichts anfangen.

Übrig bleibt reine Paketweiterleitung auf Ebene 3 und 4, und genau das ist es, was ein Filternetz leistet. Der Unterschied zu einem CDN ist aber wesentlich: Der Schutz muss dort sitzen, wo Ihre Adresse ohnehin schon hingehört, also im Netz des Anbieters vor dem Server. Etwas davorzuschalten, das Sie selbst mieten und auf das Sie Ihre Clients umziehen, ist bei einem VPN keine praktikable Antwort.

Was ein Angreifer mit einem VPN-Server erreicht

Ein Angriff auf einen Webserver nimmt eine Website herunter. Ein Angriff auf einen VPN-Server nimmt den Zugang zu allem herunter, was dahinter liegt. Bei einem Firmen-VPN heißt das konkret: Niemand erreicht mehr das Warenwirtschaftssystem, das Ticketsystem, die Dateiablage oder die interne Datenbank, und zwar auch dann nicht, wenn all diese Systeme völlig unbeeindruckt weiterlaufen. Die Arbeit steht still, weil der eine Weg dorthin zu ist.

Der zweite Punkt ist noch unangenehmer: Wer seine Verwaltungszugänge ausschließlich über das VPN erreichbar gemacht hat (und genau das ist die empfohlene Bauweise), steht während des Angriffs vor der eigenen Tür. SSH ist zu, das Monitoring ist zu, das Panel ist zu. Deshalb gehört zu jedem VPN-Server ein zweiter, netzunabhängiger Weg, mehr dazu weiter unten. Was ein DDoS-Angriff technisch ist und wie er zusammengesetzt wird, erklärt der Beitrag Was ist ein DDoS-Angriff?.

Die Ports und Protokolle, um die es tatsächlich geht

Ein VPN-Server braucht genau einen Port im offenen Netz. Alles andere in dieser Tabelle gehört entweder gar nicht ins Internet oder nur auf Ihre eigene Adresse.

Dienst Port Protokoll Wo eingestellt Ins offene Netz?
WireGuard 51820 UDP /etc/wireguard/wg0.conf: ListenPort ja, als einziger
OpenVPN (Voreinstellung) 1194 UDP server.conf: port und proto udp ja, als einziger
OpenVPN über TCP 1194 oder 443 TCP server.conf: proto tcp-server nur wenn wirklich nötig
IKEv2/IPsec 500 und 4500 UDP ipsec.conf beziehungsweise swanctl.conf ja, beide zusammen
OpenVPN-Verwaltungsschnittstelle 7505 (frei wählbar) TCP server.conf: management nein, nur 127.0.0.1
DNS-Auflöser im VPN 53 UDP und TCP dnsmasq oder unbound, an die VPN-Schnittstelle gebunden nein, niemals
SSH 22 TCP /etc/ssh/sshd_config nur eigene Adresse

Eine Zeile dieser Tabelle verdient besondere Aufmerksamkeit. Wer auf dem VPN-Server einen eigenen DNS-Auflöser betreibt, damit die Clients Namen auflösen können, hat genau dann ein Problem, wenn dieser Auflöser versehentlich auf 0.0.0.0 lauscht statt nur auf der VPN-Schnittstelle. Aus dem Auflöser wird dann ein offener Verstärker, der für Angriffe gegen Dritte missbraucht wird, und Ihre Leitung trägt die Last. Die Zeilen interface=wg0 und bind-dynamic bei dnsmasq sind deshalb keine Kosmetik. Wie das sauber aufgesetzt wird, steht in WireGuard-VPN auf dem eigenen Server einrichten.

WireGuard unter Angriff: was das Protokoll selbst leistet

Ein Port, ein Protokoll, und sonst nichts

WireGuard spricht ausschließlich UDP und lauscht auf genau einem Port, voreingestellt 51820. Es gibt kein TCP, keinen zweiten Steuerkanal, keinen Statusport und keine Fernwartungsschnittstelle. Die gesamte Angriffsfläche im Netz besteht aus einem einzigen UDP-Port, und das Protokoll kennt darauf nur vier Nachrichtentypen, erkennbar am ersten Byte der UDP-Nutzlast:

Typ Nachricht Größe Richtung beim Server Was sie kostet
1 Handshake Initiation 148 Byte eingehend teuer: Curve25519, erst nach bestandener mac1-Prüfung
2 Handshake Response 92 Byte ausgehend die Antwort des Servers
3 Cookie Reply 64 Byte ausgehend, nur unter Last billig: ein MAC über Adresse und Port
4 Transport Data 32 Byte Kopf plus Nutzlast eingehend ChaCha20Poly1305, günstig

Diese Tabelle ist mehr als Theorie, sie ist die Grundlage jeder brauchbaren Filterregel auf dem Server. Ein reiner Einwahlserver, zu dem sich die Clients verbinden, empfängt ausschließlich Typ 1 und Typ 4. Typ 2 und Typ 3 empfängt er nur dann, wenn er selbst Verbindungen aufbaut, also im Standortverbund mit einem fest eingetragenen Endpoint auf der Gegenseite. Alles andere auf Port 51820 ist kein gültiges WireGuard-Paket.

Der Handschlag und warum mac1 der eigentliche Filter ist

WireGuard baut seinen Handschlag auf dem Noise-Protokollrahmen auf, genauer auf der Variante Noise IKpsk2 mit Curve25519 für den Schlüsselaustausch, ChaCha20Poly1305 für die Verschlüsselung und BLAKE2s als Hashfunktion. Der teure Teil daran ist die Rechnung auf der elliptischen Kurve, und genau die will man einem Angreifer nicht kostenlos anbieten.

Deshalb trägt jede Handschlag-Nachricht am Ende ein Feld namens mac1. Es ist ein schlüsselbasierter Hash über die gesamte Nachricht, und der Schlüssel dafür wird aus dem öffentlichen Schlüssel des Empfängers abgeleitet. Die Folge: Wer den öffentlichen Schlüssel des Servers nicht kennt, kann kein gültiges mac1 erzeugen. Der Server prüft mac1 als Allererstes, mit einer einzigen Hashoperation. Schlägt die Prüfung fehl, wird das Paket verworfen, bevor auch nur eine einzige Kurvenoperation stattgefunden hat.

Das ist der Grund, warum eine blinde Handschlag-Flut gegen einen WireGuard-Server erstaunlich wenig Rechenzeit kostet: Der Angreifer kennt den öffentlichen Serverschlüssel nicht und produziert damit nur Pakete, die nach einem Hash im Papierkorb landen. Die schlechte Nachricht steht auf der anderen Seite derselben Medaille: Wer ein gültiges Clientprofil besitzt, kennt den öffentlichen Serverschlüssel, denn er steht unter [Peer] PublicKey in jeder Profildatei. Ein verärgerter Ex-Nutzer kann also sehr wohl Pakete bauen, die die mac1-Prüfung bestehen und den Server in die teure Rechnung zwingen. Das ist der praktisch relevante Fall.

Für genau diesen Fall hat WireGuard einen zweiten Mechanismus. Sobald der Server unter Last steht, antwortet er auf eine Initiation nicht mit einem Handschlag, sondern mit einer Cookie-Antwort (Typ 3, 64 Byte). Darin steckt, verschlüsselt an den Absender, ein Cookie, das aus einem serverseitigen Geheimnis sowie der Quelladresse und dem Quellport des Absenders berechnet wird. Der Client muss dieses Cookie in seinen nächsten Versuch als zweites Feld mac2 einrechnen, sonst gilt der Versuch weiterhin als unbestätigt.

Der Effekt ist präzise umrissen und sollte nicht überschätzt werden. Ein Angreifer, der seine Absenderadresse fälscht, bekommt die Cookie-Antwort nie zu sehen, denn sie geht an die gefälschte Adresse. Er kann also kein gültiges mac2 bilden und den Server nie in die teure Rechnung zwingen. Die Cookie-Antwort macht gefälschte Handschlag-Fluten wirkungslos, sie macht sie aber nicht unsichtbar. Die Pakete kommen weiterhin an, belegen weiterhin Ihre Leitung und kosten weiterhin je einen Hash. Gegen einen Angriff, der schlicht die Leitung füllt, hilft der Mechanismus nicht.

Wann gilt der Server als unter Last? In der Kernel-Implementierung dann, wenn die Warteschlange der eingehenden Handschläge ein Achtel ihrer Kapazität erreicht, also 512 von 4096 Einträgen, oder wenn dieser Zustand innerhalb der letzten Sekunde einmal eingetreten war. Das ist eine technische Feinheit mit einer praktischen Folge: Im normalen Betrieb sehen Sie nie eine Cookie-Antwort, unter Angriff sind es plötzlich alle.

Die eingebaute Ratenbegrenzung im Kernel

WireGuard bringt zusätzlich eine eigene Ratenbegrenzung für die Verarbeitung von Handschlägen mit. Die Werte stehen fest im Quelltext der Kernel-Implementierung und sind nicht konfigurierbar: 20 Handschlag-Pakete je Sekunde und Quelle, mit einem Spielraum von fünf Paketen. Als Quelle zählt bei IPv4 die vollständige Adresse, bei IPv6 dagegen das gesamte /64. Das ist bewusst so gewählt, denn ein Angreifer mit einem IPv6-Präfix hätte sonst beliebig viele scheinbar verschiedene Adressen zur Verfügung.

Merken Sie sich die Zahl 20 pro Sekunde: Sie ist der Maßstab dafür, wie eng Sie Ihre eigene Regel in nftables ziehen dürfen, ohne echte Clients zu treffen. Ein regulärer Client baut alle 120 Sekunden einen neuen Handschlag auf und wiederholt einen fehlgeschlagenen Versuch alle fünf Sekunden. Selbst ein halbes Dutzend Geräte hinter einem gemeinsamen Anschluss bleibt damit weit unter einem Handschlag pro Sekunde.

Warum WireGuard stumm bleibt, und was das für die Erkennung bedeutet

Ein WireGuard-Server antwortet auf kein einziges Paket, das die mac1-Prüfung nicht besteht. Er sendet keine Fehlermeldung, kein ICMP Port Unreachable, gar nichts. Für einen Portscan ist der Port damit nicht von einem gefilterten oder geschlossenen Port zu unterscheiden, nmap meldet open|filtered und kommt nicht weiter.

Das hat zwei Konsequenzen, eine gute und eine schlechte. Die gute: WireGuard taugt nicht als Verstärker für Angriffe gegen Dritte. Selbst wenn ein Angreifer den öffentlichen Serverschlüssel besitzt, antwortet der Server auf 148 Byte mit 92 Byte oder unter Last mit 64 Byte. Das ist ein Verstärkungsfaktor von 0,6 beziehungsweise 0,43, also eine Abschwächung. Zum Vergleich: Die üblicherweise missbrauchten Protokolle liegen bei Faktoren von rund 30 bis über 51.000, nachzulesen in Was ist ein DDoS-Angriff?.

Die schlechte Konsequenz: Ihr VPN-Dienst meldet Ihnen einen Angriff nicht. Ein Webserver schreibt bei einer Flut Tausende Zeilen ins Zugriffsprotokoll, ein WireGuard-Server schreibt gar nichts, weil er nichts protokolliert, was er sofort verwirft. Ein Angriff auf einen WireGuard-Server ist ausschließlich an den Zählern der Netzwerkkarte und des Kernels zu erkennen, nicht am Dienst selbst. Wer nur in wg show schaut, sieht lediglich, dass die Handschläge alt werden, und weiß nicht, warum.

OpenVPN unter Angriff: UDP, TCP und der teure Handschlag

UDP oder TCP, und warum TCP unter Angriff besonders leidet

OpenVPN läuft wahlweise über UDP oder über TCP, voreingestellt ist UDP auf Port 1194. TCP wird meistens dann gewählt, wenn ein restriktives Netz alles außer Port 443 sperrt. Unter Angriff ist diese Wahl teuer, und zwar aus drei Gründen.

Erstens erzeugt jede TCP-Verbindung Zustand im Kernel, bevor OpenVPN sie überhaupt sieht. Ein SYN-Flood mit gefälschten Absendern füllt die Warteschlange halboffener Verbindungen, und schon einige zehntausend SYN-Pakete pro Sekunde legen die Verbindungsannahme eines Standard-Linux lahm, lange bevor die Leitung voll ist. Dagegen helfen SYN-Cookies, die den Zustand nicht speichern, sondern aus der Antwort des Clients zurückrechnen (net.ipv4.tcp_syncookies muss auf 1 stehen). Bei UDP gibt es dieses Problem nicht, weil es keinen Verbindungsaufbau gibt, den man halb offen lassen könnte.

Zweitens leidet TCP im TCP. Die Anwendung des Nutzers spricht meist selbst TCP, und dieses TCP läuft dann in einer TCP-Verbindung. Geht im äußeren Strom ein Segment verloren, hält das äußere TCP die Reihenfolge ein und blockiert alles Nachfolgende, bis die Wiederholung angekommen ist. Das innere TCP wertet die entstehende Verzögerung als Stau und drosselt zusätzlich. Unter Paketverlust, und Paketverlust ist genau das, was ein Angriff erzeugt, bricht der Durchsatz deshalb überproportional ein. Über UDP fehlt ein verlorenes Paket einfach, und das innere TCP regelt es selbst.

Drittens beschäftigt eine aufgebaute, aber stille Verbindung den Server. Wer eine TCP-Verbindung vollständig aufbaut und dann schweigt, belegt einen Platz, bis das Zeitfenster für den Handschlag abläuft. Dieses Fenster steuert hand-window und steht voreingestellt auf 60 Sekunden. Mit wenigen hundert solcher Verbindungen füllt ein Angreifer den Server, ohne nennenswerte Bandbreite aufzuwenden. Die Empfehlung ist deshalb eindeutig: Betreiben Sie OpenVPN über UDP, es sei denn, ein Netz zwingt Sie zu TCP. Wer beides braucht, betreibt zwei Instanzen und hält die TCP-Instanz klein.

tls-auth und tls-crypt als Filter vor dem teuren TLS-Handschlag

Der eigentliche Grund, warum OpenVPN unter einer Handschlag-Flut leidet, ist der Steuerkanal. Ein neuer Client schickt ein Paket vom Typ P_CONTROL_HARD_RESET_CLIENT_V2, und der Server beginnt daraufhin einen vollständigen TLS-Handschlag mit Zertifikatsprüfung. Das ist um Größenordnungen teurer als alles, was WireGuard tut, und OpenVPN arbeitet in der Betriebsart mode server einsträngig, erledigt diese Handschläge also nacheinander.

Dagegen gibt es Mechanismen, die alle dasselbe Ziel verfolgen: ein unautorisiertes Paket verwerfen, bevor TLS überhaupt angefasst wird.

  • tls-auth ta.key 0 hängt an jedes Paket des Steuerkanals einen HMAC, berechnet mit einem gemeinsamen statischen Schlüssel. Pakete ohne gültigen HMAC verwirft OpenVPN, bevor es sie an die TLS-Schicht reicht. Das ist der ältere Mechanismus, oft als HMAC-Firewall bezeichnet. Der Steuerkanal bleibt dabei lesbar, nur eben nicht fälschbar.
  • tls-crypt ta.key ab OpenVPN 2.4 geht einen Schritt weiter und verschlüsselt den Steuerkanal zusätzlich, mit AES-256-CTR und HMAC-SHA-256. Ein Beobachter sieht dann nicht einmal mehr, dass hier ein TLS-Handschlag stattfindet, und ein Scanner erkennt den Dienst nicht als OpenVPN. Der Richtungsparameter entfällt, die Zeile lautet auf beiden Seiten identisch.
  • tls-crypt-v2 ab OpenVPN 2.5 vergibt je Client einen eigenen Schlüssel statt eines gemeinsamen. Das ist die richtige Wahl, sobald Sie mehr als eine Handvoll Nutzer haben, denn ein ausgeschiedener Nutzer lässt sich dann entfernen, ohne allen anderen eine neue Datei zu geben.

In der Serverkonfiguration sieht das so aus. Beachten Sie, dass tls-crypt und tls-auth einander ausschließen, beide zusammen sind ein Konfigurationsfehler:

proto udp
port 1194
dev tun
tls-crypt /etc/openvpn/server/ta.key
auth SHA256
cipher AES-256-GCM
tls-version-min 1.2
remote-cert-tls client
crl-verify /etc/openvpn/server/crl.pem
verb 3
mute 20
explicit-exit-notify 1

Wer bisher tls-auth verwendet hat, kann auf tls-crypt umstellen, muss aber alle Clientprofile gleichzeitig tauschen. Das Schlüsselmaterial selbst bleibt dasselbe (openvpn --genkey secret ta.key erzeugt in beiden Fällen 2048 Bit Zufallsmaterial), nur die Verwendung ändert sich.

connect-freq und connect-freq-initial

OpenVPN bringt zwei eigene Bremsen mit, und beide sind unter Angriff relevant. connect-freq n sec begrenzt, wie viele neue Verbindungen der Server in einem Zeitraum überhaupt annimmt. connect-freq-initial n sec gibt es seit OpenVPN 2.6, gilt nur für UDP und begrenzt die Zahl der Antworten auf erste Verbindungspakete. Die Voreinstellung lautet 100 Antworten je 10 Sekunden, und Verbindungsversuche, die den Aufbau tatsächlich abschließen, zählen nicht dagegen.

Der Zweck dieser Option ist ausdrücklich die Abwehr von Reflexion: Ein OpenVPN-Server, der auf jedes erste Paket antwortet, lässt sich mit gefälschter Absenderadresse als Reflektor gegen ein fremdes Ziel einspannen. Der Verstärkungsfaktor ist dabei klein, in der Größenordnung von zwei, also weit entfernt von den Faktoren bekannter Verstärkerprotokolle. Der eigentliche Schaden liegt woanders: Ihre Leitung trägt die Last, und Ihre Adresse landet auf den Listen der Netze, die auffälligen Verkehr senden.

connect-freq 20 10
connect-freq-initial 30 10
max-clients 50

Setzen Sie max-clients auf die Zahl, die Sie tatsächlich brauchen, und nicht höher. Jeder Platz ist eine Ressource, die belegt werden kann. Und lassen Sie duplicate-cn weg, wenn jeder Nutzer sein eigenes Zertifikat hat: Ohne diese Option wirft ein zweiter Verbindungsaufbau mit demselben Zertifikatsnamen den ersten heraus, was ein Angreifer mit einem geleakten Profil gezielt ausnutzen kann.

WireGuard und OpenVPN im direkten Vergleich

Eigenschaft WireGuard OpenVPN
Transport ausschließlich UDP UDP oder TCP
Voreingestellter Port 51820 UDP 1194 UDP, oft 443 TCP
Antwort auf unautorisierte Pakete keine, immer stumm ohne tls-crypt eine Antwort, mit tls-crypt stumm
Filter vor der teuren Rechnung mac1, ein Hash je Paket tls-auth oder tls-crypt, ein HMAC je Paket
Schutz gegen gefälschte Absender Cookie-Antwort unter Last connect-freq-initial, bei TCP zusätzlich SYN-Cookies
Eingebaute Ratenbegrenzung 20 Handschläge je Sekunde und Quelle, fest verdrahtet connect-freq, frei einstellbar
Verarbeitung im Kernel, mehrkernfähig im Benutzerprozess, Handschläge nacheinander
Adresswechsel des Servers Name wird nur beim Start aufgelöst mehrere remote, Auflösung bei jedem Versuch
Erkennbar für Scanner nein, open|filtered ohne tls-crypt ja, mit tls-crypt nein
Taugt als Verstärker nein, Faktor unter 1 ohne tls-crypt gering, Faktor etwa 2

Die vier Angriffsarten, die einen VPN-Server treffen

1. UDP-Flut auf den VPN-Port

Die einfachste und häufigste Variante. Der Angreifer schickt beliebige UDP-Pakete an 51820 oder 1194, meist mit gefälschten Absenderadressen. Er braucht dafür kein Wissen über Ihr VPN, nicht einmal die Portnummer muss stimmen, denn eine volle Leitung ist eine volle Leitung, ganz gleich an welchem Port die Pakete klopfen. WireGuard verwirft sie nach einem Hash, OpenVPN mit tls-crypt nach einem HMAC. Beides kostet wenig Rechenzeit und ändert nichts daran, dass die Pakete Ihre Leitung bereits belegt haben, als sie ankamen.

2. Handschlag-Flut

Die gezieltere Variante, und die einzige, die Vorwissen erfordert. Der Angreifer baut Pakete, die als Verbindungsaufbau durchgehen: bei WireGuard eine Initiation mit gültigem mac1, was den öffentlichen Serverschlüssel voraussetzt, bei OpenVPN ein P_CONTROL_HARD_RESET_CLIENT_V2 mit gültigem HMAC, was den ta.key voraussetzt. Beides steckt in jedem ausgegebenen Clientprofil. Der typische Auslöser ist deshalb kein anonymer Angreifer aus dem Netz, sondern jemand, der einmal Zugang hatte.

Bei OpenVPN ist der Hebel besonders groß, weil ein vollständiger TLS-Handschlag mit Zertifikatsprüfung dahinter hängt und der Server ihn einsträngig abarbeitet. Bei WireGuard greift zuerst die eingebaute Ratenbegrenzung und danach die Cookie-Antwort. Die Gegenmaßnahme ist in beiden Fällen dieselbe und sie kostet nichts: Nehmen Sie ausgeschiedene Nutzer aus der Konfiguration. Bei WireGuard ist das der betreffende [Peer]-Block, bei OpenVPN der Widerruf des Zertifikats in der crl.pem, und mit tls-crypt-v2 zusätzlich der Clientschlüssel.

3. Verstärkungsangriff auf die Leitung

Hier interessiert sich der Angreifer überhaupt nicht für Ihr VPN. Er schickt kleine Anfragen mit Ihrer gefälschten Adresse an fremde, falsch konfigurierte Dienste im Netz, und deren große Antworten landen bei Ihnen. DNS, NTP, CLDAP, SSDP und im Extremfall memcached liefern dabei Faktoren von rund 30 bis über 51.000. Ihr VPN-Server hat auf keinem dieser Ports etwas laufen und verwirft alles korrekt, aber die Pakete haben Ihre Leitung schon gefüllt, bevor der Kernel sie ansehen konnte.

Das ist der Angriff, gegen den es auf dem Server buchstäblich keine Einstellung gibt. Er trifft die Adresse, nicht den Dienst.

4. Gezielte Sättigung der Paketrate

Die unangenehmste Variante, weil sie auf der Bandbreitenanzeige harmlos aussieht. Statt großer Pakete schickt der Angreifer sehr viele sehr kleine. In eine Leitung mit 1 Gbit/s passen bei 64 Byte großen Paketen rund 1,49 Millionen Pakete pro Sekunde, und ein normaler Serverkernel verarbeitet je nach CPU und Netzwerkkarte nur einige hunderttausend davon, bevor er zu verwerfen beginnt. Der Bandbreitengraph zeigt dann vielleicht 200 Mbit/s, und trotzdem ist nichts mehr erreichbar.

Bei einem VPN-Server kommt eine Besonderheit hinzu: Jedes Paket, das auf dem VPN-Port ankommt, muss mindestens einmal kryptografisch angefasst werden, bevor es verworfen werden darf. Die Kosten je Paket liegen damit höher als bei einem Webserver, der ein Paket auf einem geschlossenen Port sofort fallen lässt. Ein VPN-Server erreicht seine Grenze bei der Paketrate deshalb eher als andere Dienste an derselben Leitung.

Woran Sie merken, dass Ihr VPN-Server angegriffen wird

WireGuard: wg show und die letzten Handschläge

Der erste Blick geht auf den Zustand der Peers. Zwei Befehle genügen:

wg show wg0 latest-handshakes
wg show wg0 transfer

latest-handshakes gibt je Peer einen Unix-Zeitstempel aus. Rechnen Sie die Differenz zur aktuellen Zeit aus: Alles über 180 Sekunden bedeutet, dass die Sitzung abgelaufen ist und kein neuer Handschlag zustande kam. Wenn alle Peers gleichzeitig alt werden, ist das ein Netzproblem und kein Clientproblem. Bleiben bei transfer zusätzlich die empfangenen Bytes stehen, während die gesendeten weiterlaufen, gehen Ihre Pakete hinaus und es kommt nichts zurück.

Zum Einordnen der Zeiten: WireGuard erneuert eine Sitzung nach 120 Sekunden, verwirft sie nach 180 Sekunden, wiederholt einen gescheiterten Handschlag alle fünf Sekunden und gibt nach 90 Sekunden auf, bis wieder neuer Verkehr anfällt. Genau das ist die Erklärung für das häufige Phänomen, dass ein VPN nach dem Ende eines Angriffs nicht von selbst zurückkommt: Der Client hat aufgegeben und wartet auf ein Paket von innen. Mit PersistentKeepalive = 25 in der Clientdatei versucht er es dagegen dauerhaft weiter.

OpenVPN: die Zeilen im journalctl, die eindeutig sind

OpenVPN ist gesprächig, und das ist unter Angriff ein Vorteil:

journalctl -u openvpn-server@server -n 200 --no-pager
journalctl -u openvpn-server@server -f

Drei Meldungen sind aussagekräftig und bedeuten jeweils etwas anderes:

  • TLS Error: cannot locate HMAC in incoming packet from heißt, dass Pakete ankommen, die den tls-auth- oder tls-crypt-Schlüssel nicht kennen. Vereinzelt sind das Scanner, massenhaft ist es eine Flut. Der Filter arbeitet dabei korrekt, die Meldung ist der Beweis dafür.
  • TLS Error: TLS key negotiation failed to occur within 60 seconds heißt, dass ein Verbindungsaufbau begonnen und nicht beendet wurde. Das sind entweder Clients mit Paketverlust oder Verbindungen, die absichtlich offen gelassen werden.
  • Authenticate/Decrypt packet error: packet HMAC authentication failed betrifft den Datenkanal einer bestehenden Sitzung und deutet eher auf ein MTU- oder Schlüsselproblem als auf einen Angriff hin.

Setzen Sie unter Angriff verb 3 und nicht höher. Eine höhere Stufe schreibt pro verworfenem Paket eine Zeile, und dann legt Ihnen die Protokollierung den Server lahm, den der Angriff allein noch nicht erwischt hätte. mute 20 fasst Wiederholungen zusammen und gehört in jede Serverkonfiguration.

nstat, ss und die Zähler der Netzwerkkarte

Das sind die Messwerte, die unabhängig vom VPN-Programm gelten und die Sie in jedem Fall brauchen:

ip -s link show eth0
nstat -az | grep -E 'Udp|IpReasm'
ss -lnup
cat /proc/net/softnet_stat
ethtool -S eth0 | grep -iE 'drop|miss|discard'

ip -s link show eth0 zweimal im Abstand von zehn Sekunden ausgeführt und die Differenz gebildet, ergibt Ihre tatsächliche Paketrate. Steigt in derselben Ausgabe die Spalte dropped, verwirft schon die Netzwerkkarte oder der Treiber, und das ist der härteste verfügbare Beleg für Überlast. In /proc/net/softnet_stat ist die zweite Spalte je Kern die Zahl der Pakete, die verworfen wurden, weil die Warteschlange dieses Kerns voll war. Steht dort etwas anderes als Nullen, ist die Paketrate die Ursache und nicht die Bandbreite.

Bei nstat unterscheiden sich die beiden VPN-Programme wesentlich, und das ist die praktisch wichtigste Diagnoseregel dieses Beitrags. Kernel-WireGuard verarbeitet Pakete direkt im Netzwerkpfad des Kernels und nicht über die Warteschlange eines Anwendungs-Sockets. Der Zähler UdpRcvbufErrors bleibt dort deshalb bei null, auch unter schwerem Angriff. Verluste sehen Sie ausschließlich an der Netzwerkkarte und in softnet_stat. Bei OpenVPN ist es umgekehrt: Der Dienst liest aus einem gewöhnlichen UDP-Socket, und ein steigender UdpRcvbufErrors heißt dort, dass der Prozess nicht hinterherkommt. Dagegen helfen größere Puffer:

sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.rmem_default=1048576
sysctl -w net.core.netdev_max_backlog=16384

Prüfen Sie außerdem IpReasmFails und IpReasmTimeout. Steigen diese Werte, kommen fragmentierte Pakete an, deren Bruchstücke nie vollständig werden. Bei einem reinen WireGuard-Server ist das immer auffällig, denn WireGuard setzt im äußeren IP-Kopf das Don't-Fragment-Bit und erzeugt selbst keine Fragmente.

Die Gegenprobe: Angriff, MTU-Problem oder eigener Fehler

Bevor Sie einen Angriff melden, schließen Sie die beiden häufigen Verwechslungen aus. Ein MTU-Problem sieht einem Angriff auf den ersten Blick ähnlich, weil kleine Pakete durchgehen und große hängen bleiben: Der Handschlag klappt, ping klappt, aber Webseiten bauen sich nur halb auf. Der Test dafür dauert zehn Sekunden, nämlich testweise MTU = 1280 in der Clientdatei. Läuft es damit sauber, war es die MTU und kein Angriff.

Der zweite Fall ist die eigene Firewall. Prüfen Sie, ob Ihre Regeln überhaupt greifen, indem Sie auf die Zähler sehen. Bleiben sie bei null, wird die Regel nicht erreicht, und das ist eine völlig andere Diagnose als eine wirkungslose Regel. Das systematische Vorgehen samt der Frage, wie man einen Ansturm von einem Angriff unterscheidet, steht in DDoS-Angriff erkennen, die Reihenfolge der Schritte im Ernstfall in Schwerer DDoS-Angriff: was tun.

Was auf dem Server hilft, und wie die Regeln aussehen

Dieser Abschnitt ist der längste, und das mit Absicht. Ein sauber konfigurierter VPN-Server hält kleine und mittlere Angriffe aus eigener Kraft aus, unabhängig davon, bei wem er steht.

1. Bestandsaufnahme: was lauscht überhaupt?

Bevor Sie eine einzige Regel schreiben, sehen Sie nach, was Ihr Server nach außen anbietet. Nicht raten, nachsehen:

ss -lntup
wg show
systemctl status openvpn-server@server

Interessant ist die Spalte mit der lokalen Adresse. 0.0.0.0:51820 bedeutet aus dem ganzen Internet erreichbar, 127.0.0.1:7505 bedeutet nur lokal und braucht keine Firewall-Regel. Taucht hier ein DNS-Auflöser auf 0.0.0.0:53 auf, ist das der dringendste Punkt Ihrer Liste. Die Sicht des Angreifers liefert ein Scan von außen:

nmap -Pn -sU -p 51820,1194,500,4500 IHRE.SERVER.IP.ADRESSE
nmap -Pn -sT -p- --min-rate 1000 IHRE.SERVER.IP.ADRESSE

2. Ratenbegrenzung je Quelladresse auf dem VPN-Port

Jetzt der Kern. Die Regel nutzt aus, dass WireGuard seine Nachrichtentypen im ersten Byte der UDP-Nutzlast trägt und dass die Initiation eine feste Größe hat: 148 Byte Nutzlast, also 156 Byte im Längenfeld des UDP-Kopfes. Damit lässt sich der teure Handschlag getrennt vom günstigen Datenverkehr begrenzen, und genau das ist der Unterschied zu einer platten Regel über alle Pakete.

#!/usr/sbin/nft -f

flush ruleset

define WG_PORT = 51820
define OVPN_PORT = 1194

table inet vpn {
    set adminips {
        type ipv4_addr
        flags interval
        elements = { 203.0.113.10 }
    }

    chain input {
        type filter hook input priority filter; policy drop;

        iif lo accept
        ct state established,related accept
        ct state invalid counter drop

        ip saddr @adminips tcp dport 22 accept

        udp dport $WG_PORT @th,64,8 == 4 accept
        udp dport $WG_PORT udp length 156 @th,64,8 == 1 meter wg_hs { ip saddr limit rate over 2/second burst 10 packets } counter drop
        udp dport $WG_PORT udp length 156 @th,64,8 == 1 accept
        udp dport $WG_PORT counter drop

        udp dport $OVPN_PORT @th,64,5 == 7 meter ovpn_reset { ip saddr limit rate over 2/second burst 10 packets } counter drop
        udp dport $OVPN_PORT accept

        icmp type echo-request limit rate 5/second accept
        icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert } accept

        counter drop
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
        iifname { "wg0", "tun0" } accept
        oifname { "wg0", "tun0" } ct state established,related accept
    }

    chain output { type filter hook output priority filter; policy accept; }
}

Tragen Sie unter adminips Ihre eigene feste Adresse ein, bevor Sie laden, sonst sperren Sie sich aus SSH aus. Geprüft und aktiviert wird so, und der erste Befehl ist der eigentliche Schutz vor einem Tippfehler:

nft -c -f /etc/nftables.conf
systemctl enable --now nftables
nft list table inet vpn
nft list meter inet vpn wg_hs

Vier Punkte entscheiden darüber, ob diese Regeln wirken oder Schaden anrichten.

@th,64,8 ist das erste Byte nach dem UDP-Kopf. Der UDP-Kopf ist acht Byte lang, also 64 Bit, und @th zählt ab seinem Anfang. Bei WireGuard steht dort der Nachrichtentyp. Bei OpenVPN steckt im selben Byte der Opcode in den oberen fünf Bit und die Schlüsselkennung in den unteren drei, deshalb dort @th,64,5 und der Wert 7 für P_CONTROL_HARD_RESET_CLIENT_V2. Für Clients mit tls-crypt-v2 kommt der Wert 10 dazu, die Regel ist dann um eine Zeile mit @th,64,5 == 10 zu ergänzen.

Die Datenpakete stehen bewusst als erste Regel. Ein Paket, das durchgelassen wird, soll so früh wie möglich durchgelassen werden, denn jede Regel davor kostet Rechenzeit mal Paketrate. Bei einem laufenden VPN sind über 99 Prozent aller eingehenden Pakete vom Typ 4.

ip saddr im meter greift nur bei IPv4. In einer inet-Tabelle brauchen Sie für IPv6 eine zweite Zeile mit ip6 saddr, sonst läuft Ihr gesamter IPv6-Verkehr ungebremst durch. Nehmen Sie dort ein /64 als Schlüssel und nicht die vollständige Adresse, genau wie WireGuard es intern auch tut.

Zwei Handschläge pro Sekunde sind ein Startwert, keine Wahrheit. Ein echter Client braucht alle 120 Sekunden einen. Ein Büro oder eine Wohngemeinschaft hinter einer gemeinsamen Adresse braucht entsprechend mehr, und ein Mobilfunknetz kann Hunderte Ihrer Nutzer hinter derselben Adresse zusammenfassen. Messen Sie erst eine Woche im Normalbetrieb, bevor Sie die Werte festziehen, und sehen Sie danach regelmäßig in den Zähler. Steigt er, obwohl kein Angriff läuft, ist der Wert zu niedrig.

3. conntrack für den VPN-Port abschalten

Der Verbindungsverfolger des Kernels legt für jedes UDP-Paar aus Adressen und Ports einen Eintrag an, auch für ein einzelnes Paket, das ins Leere geht. Eine UDP-Flut mit gefälschten Absendern erzeugt damit pro Paket einen Eintrag, und sobald die Tabelle voll ist, meldet der Kernel nf_conntrack: table full, dropping packet und verwirft dann auch Pakete Ihrer echten Nutzer. Prüfen lässt sich das so:

sysctl net.netfilter.nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count
dmesg | grep -i conntrack

Für einen VPN-Port ist diese Buchführung ohnehin nutzlos, denn die Zugehörigkeit eines Pakets ergibt sich aus der Kryptografie und nicht aus einer Tabelle im Paketfilter. Nehmen Sie den Port deshalb aus der Verfolgung heraus:

table inet raw {
    chain prerouting {
        type filter hook prerouting priority raw; policy accept;
        udp dport { 51820, 1194 } notrack
    }
}

Wichtig ist die Folge davon: Pakete auf diesen Ports haben danach keinen Verbindungszustand mehr, die Regel ct state established,related accept greift für sie also nicht. Genau deshalb steht im Regelwerk oben für jeden VPN-Port eine ausdrückliche Zeile. Wer notrack setzt und die ausdrückliche Zeile vergisst, schaltet sein VPN ab.

4. Portwahl gegen Scanner, und warum das kein Schutz ist

Ein anderer Port als 51820 oder 1194 senkt das Grundrauschen. Massenscanner arbeiten Listen bekannter Ports ab, und ein VPN auf 51820 steht in jeder dieser Listen. Auf einem ungewöhnlichen Port fällt der Server aus diesen Durchläufen heraus, und das ist messbar weniger Verkehr.

Gegen einen gezielten Angriff ist die Portwahl wirkungslos. Der Port steht in jeder Clientdatei, genau wie die Adresse. Wer Ihr Profil hat, hat den Port. Und ein volumetrischer Angriff richtet sich ohnehin nicht nach Ports: Er füllt die Leitung, ganz gleich wohin die Pakete adressiert sind. Behandeln Sie die Portwahl also als Hygiene gegen Scanner, nicht als Schutzmaßnahme, und ändern Sie sie nicht mitten in einem Angriff, weil Sie damit alle Clients gleichzeitig aussperren.

Wenn Sie den Port ändern, ändern Sie ihn an zwei Stellen: ListenPort in der Serverdatei und Endpoint in jeder Clientdatei. Bei OpenVPN sind es port und remote. Ein Umstieg funktioniert schrittweise, indem Sie vorübergehend beide Ports freigeben.

5. MTU und Fragmentierung sauber setzen

Fragmentierung ist bei einem VPN doppelt unangenehm. Erstens trägt nur das erste Bruchstück eines fragmentierten Pakets den UDP-Kopf und damit die Portnummer, jedes weitere nicht. Ein Filter muss die Teile also erst zusammensetzen, bevor er überhaupt entscheiden kann, wohin sie gehören, und das kostet Speicher und Zeit. Zweitens ist eine Flut aus Fragmenten damit ein eigenes Angriffsmuster: Der Angreifer schickt erste Bruchstücke, deren Rest nie kommt, und füllt die Warteschlange für den Zusammenbau.

Die Werte dafür lassen sich ablesen und begrenzen:

sysctl net.ipv4.ipfrag_high_thresh net.ipv4.ipfrag_low_thresh net.ipv4.ipfrag_time
nstat -az | grep -i reasm

Die richtige Antwort ist aber nicht, Fragmente besser zu verwalten, sondern sie gar nicht erst entstehen zu lassen. Bei WireGuard erledigt das wg-quick von selbst: Es zieht 80 Byte von der ermittelten Pfad-MTU ab und landet auf einer normalen 1500er-Strecke bei 1420. WireGuard setzt außerdem das Don't-Fragment-Bit, erzeugt also selbst nie Fragmente. Bei OpenVPN 2.6 lautet die Voreinstellung mssfix 1492 mtu bei einer tun-mtu von 1500, davor war es das absolute mssfix 1450. Diese Voreinstellung entfällt automatisch, sobald Sie tun-mtu auf etwas anderes als 1500 setzen, und genau daran scheitern viele Umstellungen.

tun-mtu 1500
mssfix 1400 mtu
fragment 0

Der schnelle Gegentest bei unklaren Symptomen bleibt derselbe wie immer: MTU = 1280 auf der Clientseite. Das ist die kleinste MTU, die IPv6 garantiert, und funktioniert praktisch überall. Läuft es damit sauber, war die MTU das Problem.

6. Ausgeschiedene Nutzer wirklich entfernen

Die wirksamste kostenlose Maßnahme gegen eine Handschlag-Flut ist ein aufgeräumter Bestand, denn nur wer ein Profil hat, kann eine solche Flut überhaupt erzeugen. Bei WireGuard entfernen Sie den Peer im laufenden Betrieb, ohne die anderen Verbindungen abzuwerfen:

wg set wg0 peer OEFFENTLICHER_SCHLUESSEL remove
wg syncconf wg0 <(wg-quick strip wg0)

Denken Sie daran, den [Peer]-Block zusätzlich aus /etc/wireguard/wg0.conf zu löschen. Eine Änderung mit wg set lebt nur im Speicher und ist nach dem nächsten Neustart weg. Bei OpenVPN widerrufen Sie das Zertifikat und stellen sicher, dass der Server die Sperrliste auch liest:

./easyrsa revoke benutzername
./easyrsa gen-crl
cp pki/crl.pem /etc/openvpn/server/crl.pem
systemctl reload openvpn-server@server

In der Serverkonfiguration muss dafür crl-verify /etc/openvpn/server/crl.pem stehen. Fehlt diese Zeile, ist der Widerruf wirkungslos, und das ist einer der häufigsten stillen Fehler überhaupt. Beachten Sie außerdem, dass eine Sperrliste ein Ablaufdatum hat: Ist sie abgelaufen, verweigert OpenVPN jede Verbindung, auch die gültigen.

7. Einen zweiten Weg auf den Server behalten

Ein VPN-Server, dessen Verwaltung nur über das VPN erreichbar ist, ist im Angriffsfall unerreichbar. Das klingt selbstverständlich und wird trotzdem ständig so gebaut. Halten Sie mindestens einen der folgenden Wege offen: SSH auf einer zweiten, nicht öffentlich bekannten Adresse, SSH beschränkt auf Ihre eigene feste Adresse, oder eine Konsole, die nicht am Netzwerkstapel des Systems hängt.

Bei KVM-Rootservern und Dedicated Servern von KernelHost ist das die VNC-Konsole im Kundenbereich. Sie arbeitet unabhängig vom Netzwerk des Gastsystems, eine volle Leitung oder eine fehlerhafte Firewall-Regel kann sie also nicht blockieren. Wie Sie den SSH-Zugang selbst absichern, ohne sich auszusperren, steht in SSH absichern, und der passende Rettungsweg für die Firewall in UFW-Firewall einrichten.

8. Messwerte sammeln, solange alles normal ist

Der wichtigste Schritt ist der, den fast niemand vorher macht: eine Vergleichsbasis anlegen, solange nichts los ist. Ohne Normalwert können Sie nach einem Vorfall nicht sagen, ob 40.000 Pakete pro Sekunde viel waren oder einfach Montagmorgen. Mit apt-get install -y vnstat sysstat läuft die Messung dauerhaft mit, ohne dass Sie daran denken müssen.

Für einen VPN-Server sind vier Größen die richtige Grundlinie: Pakete je Sekunde an der Netzwerkkarte, Bit je Sekunde in beide Richtungen, die Zahl der Peers mit einem Handschlag der letzten drei Minuten, und die Zahl der verworfenen Pakete. Wie man daraus eine laufende Überwachung baut, die auch etwas meldet, steht in Server-Monitoring einrichten. Während eines Vorfalls genügen fünf Befehle:

sar -n DEV 1 10
ip -s link show eth0
nstat -az | grep -E 'Udp|Reasm'
wg show wg0 latest-handshakes
tcpdump -ni eth0 udp port 51820 -c 200 -q

Bei tcpdump gilt: immer mit -c begrenzen. Ein Mitschnitt unter Volllast belastet einen ohnehin überlasteten Server zusätzlich, und die ersten zweihundert Pakete sagen bereits alles, was Sie wissen müssen.

Wo diese Maßnahmen aufhören

Jetzt der Teil, den keine Konfigurationsdatei lösen kann. Alle bisherigen Maßnahmen laufen auf Ihrem Server, also am Ende der Leitung. Eine Filterregel entscheidet über ein Paket, das bereits über das Kabel gelaufen ist. Sie können es verwerfen, aber Sie können es nicht ungesendet machen.

Rechnen Sie einmal mit. Ein typischer Server hängt an 1 Gbit/s, das sind 125 Megabyte pro Sekunde, und die Leitung ist voll, sobald jemand mehr schickt. Angriffe gegen Projekte dieser Größe liegen üblicherweise zwischen 5 und 50 Gbit/s, also beim Fünf- bis Fünfzigfachen Ihrer Leitung. Ob Ihre meter-Regel dahinter gut gewählt ist, spielt dann keine Rolle mehr, denn die Pakete Ihrer Nutzer kommen schon vorher nicht durch.

Die zweite Größe ist die Paketrate, und sie schlägt bei einem VPN früher zu als bei anderen Diensten. In eine Leitung mit 1 Gbit/s passen bei 64 Byte großen Paketen rund 1,49 Millionen Pakete pro Sekunde. Ein normaler Serverkernel verarbeitet je nach CPU und Netzwerkkarte einige hunderttausend davon, und bei einem VPN kostet jedes dieser Pakete zusätzlich mindestens eine kryptografische Prüfung, bevor es verworfen werden darf. Betreiber erleben das als: der Graph war doch gar nicht hoch, trotzdem war alles weg.

Und der dritte Punkt ist der, der bei einem VPN am häufigsten übersehen wird: Ein Angreifer richtet sich nicht nach Ihrem Protokoll. Er schickt Verstärkungsverkehr und Fluten auf Ihre Adresse, ganz gleich, welcher Port dort offen ist. Ihr Server verwirft diese Pakete korrekt, aber sie haben Ihre Leitung bereits belegt, und Ihr VPN ist weg, ohne dass ein einziges Paket den Dienst erreicht hätte. Zur Einordnung, welche Größenordnungen real vorkommen: Auf KernelHost-Servern wurde unter anderem ein kombinierter Angriff auf einen Minecraft-Server und einen OpenVPN-Dienst (Ports 25565 TCP und 1194 UDP) mit über sechzehn verschiedenen Hauptangriffsmustern, über 4 Millionen Paketen pro Sekunde und über 8,6 Gbit/s gefiltert. Beide Dienste blieben durchgehend erreichbar. Dafür gibt es keine lokale Einstellung. Volumetrische Angriffe müssen im Netz vor dem Server enden.

Was KernelHost dagegen stellt

Der Dauerschutz, der auf jedem Server inklusive ist

Der DDoS-Schutz von KernelHost ist zweistufig aufgebaut und dauerhaft aktiv, ohne dass Sie etwas einschalten, bestellen oder konfigurieren müssen:

  • Stufe 1: 17 Tbps Mitigationskapazität im globalen Scrubbing-Netzwerk. Volumetrische Angriffe werden nah an ihrer Quelle bereinigt, bevor sie das Rechenzentrum erreichen.
  • Stufe 2: Arbor-Echtzeitfilterung mit 3,2 Tbps in Frankfurt am Main. Direkt vor dem Server werden protokollspezifische Muster erkannt und verworfen, Paket für Paket. Für ein VPN heißt das konkret: UDP-Fluten gegen 51820 und 1194 sowie SYN-Fluten gegen einen OpenVPN-Dienst auf TCP enden hier und nicht auf Ihrer Netzwerkkarte.

Drei Eigenschaften sind dabei entscheidend. Der Schutz läuft permanent und muss nicht erst auf einen Angriff reagieren, es gibt also keine Minuten am Anfang, in denen das VPN weg ist. Es wird kein Nullrouting eingesetzt: Ihre IP-Adresse bleibt im Netz, verworfen werden nur die schädlichen Pakete. Und, für ein VPN besonders wichtig: Die Filterung passiert im Netz vor dem Server, nicht auf einem zusätzlichen Weg, den Sie erst aufbauen oder auf den Sie Ihre Clients umziehen müssten. Auf Ihrer Seite bleibt der VPN-Tunnel genau der, den Ihre Clients ohnehin aufbauen, und die Profildateien bleiben unverändert. Der Standort ist Frankfurt am Main. Ausdrücklich abgedeckt sind unter anderem OpenVPN und WireGuard, ebenso wie allgemeiner TCP- und UDP-Verkehr auf beliebigen Ports.

Advanced DDoS Protection für dauerhaft beschossene VPN-Server

Manche Zugänge werden nicht gelegentlich, sondern gezielt und über Wochen angegriffen, und bei einem Firmen-VPN kostet jede Stunde Ausfall echte Arbeitszeit. Dafür gibt es die Advanced DDoS Protection ab 50,00 € im Monat, PrePaid, ohne Mindestlaufzeit und ohne Einrichtungsgebühr. Der Unterschied liegt nicht in mehr Kapazität, sondern in der Kontrolle:

  • Dedizierte Schutz-IP aus dem Frankfurter Kern, auf die Ihr Server im eigenen Netz umgestellt wird. Auf Ihrer Seite ist kein Umbau nötig, Sie tragen die neue Adresse lediglich in den Endpunkt Ihrer Profile ein.
  • Selbst verwaltbare Schutzregeln je Port und Protokoll im Kundenbereich: Sie geben genau 51820 UDP oder 1194 UDP frei und machen alles andere zu, ohne dafür ein Ticket zu schreiben.
  • Änderungen greifen in Echtzeit, Sie können also während eines laufenden Angriffs nachjustieren, etwa die erlaubte Paketrate je Quelladresse enger ziehen.
  • Passendes Profil für die Anwendung. Für OpenVPN und WireGuard ebenso wie für eigene oder abgewandelte Protokolle auf beliebigen TCP- oder UDP-Ports gibt es passende Profile.

Die Advanced DDoS Protection richtet sich an KernelHost-Kunden, denn die Filterung ist Teil des Netzes und kein Zusatz, der sich auf einem fremden Server installieren ließe. Wer seinen VPN-Server derzeit woanders betreibt, bekommt den Schutz deshalb nicht nachgerüstet, sondern durch den Umzug zu KernelHost. Bei einem VPN ist dieser Umzug übrigens vergleichsweise einfach: Es gibt keine Datenbank und keinen gewachsenen Zustand, sondern im Wesentlichen eine Konfigurationsdatei und einen Satz Schlüssel.

Die beiden Stufen im Vergleich

Merkmal Inkludierter DDoS-Dauerschutz Advanced DDoS Protection
Preis in jedem Serverpaket enthalten, ohne Aufpreis ab 50,00 € im Monat, PrePaid
Filterkapazität 17 Tbps globales Scrubbing plus Arbor-Echtzeitfilterung mit 3,2 Tbps in Frankfurt am Main dieselbe zweistufige Filterung
IP-Adresse die IP-Adresse Ihres Servers zusätzliche dedizierte Schutz-IP
Regelwerk automatische Profile, keine Konfiguration nötig eigene Regeln je Port und Protokoll im Kundenbereich
Änderungen laufen automatisch mit greifen in Echtzeit, auch während eines Angriffs
Profil für WireGuard und OpenVPN automatische Profile für UDP- und TCP-Dienste eigenes Regelwerk für 51820 UDP, 1194 UDP und den TCP-Betrieb
Nullrouting nein nein
Änderung an den Clientprofilen keine einmalig die neue Endpunktadresse
Laufzeit an das Serverpaket gebunden PrePaid, keine Mindestlaufzeit, keine Kündigungsfrist, keine Einrichtungsgebühr

Für die meisten VPN-Projekte reicht der inkludierte Dauerschutz zusammen mit einer sauberen Konfiguration. Die Advanced DDoS Protection ist die Antwort darauf, dass jemand es persönlich nimmt. Wer einen fertig eingerichteten Zugang statt einer Eigenbau-Installation möchte, findet ihn beim Dedicated Private VPN Server ab 4,99 € im Monat, mit dedizierter IPv4-Adresse samt /64-IPv6-Subnetz, Root-Zugang und demselben inkludierten Dauerschutz. Welcher Weg für wen passt, vergleicht Eigener VPN-Server oder VPN-Dienst.

Häufige Fehler und Lösungen

Das VPN kommt nach dem Angriff nicht von selbst zurück: Das ist kein Fehler, sondern das vorgesehene Verhalten von WireGuard. Der Client versucht einen Handschlag 90 Sekunden lang und gibt dann auf, bis wieder Verkehr von innen anfällt. Setzen Sie PersistentKeepalive = 25 in der Clientdatei, dann fällt dauernd Verkehr an und der Client versucht es weiter. Bei Telefonen ist die Zeile ohnehin Pflicht, weil Mobilfunk-NAT eine UDP-Zuordnung oft nach 30 bis 60 Sekunden vergisst.

Die Ratenbegrenzung trifft die eigenen Nutzer: Typisch bei einem Büro, einer Wohngemeinschaft oder einem Mobilfunknetz, hinter dem viele Geräte dieselbe öffentliche Adresse teilen. Für die Regel sieht das aus wie eine einzelne Adresse mit auffällig vielen Handschlägen. Prüfen Sie den Zähler mit nft list meter inet vpn wg_hs: Steigt er, obwohl kein Angriff läuft, ist der Wert zu niedrig. Erhöhen Sie ihn schrittweise.

Nach dem Setzen von notrack ist das VPN weg: Ohne Verbindungsverfolgung greift die Regel ct state established,related accept für diese Pakete nicht mehr. Es braucht dann für jeden VPN-Port eine ausdrückliche Zeile im Regelwerk, so wie oben gezeigt. Wer nur notrack setzt und sonst nichts ändert, sperrt seine Nutzer aus.

Der Handschlag klappt, aber dahinter ist nichts erreichbar: Das ist fast nie ein Angriff, sondern eine fehlende Weiterleitung. Prüfen Sie sysctl net.ipv4.ip_forward (muss 1 sein) und, falls ufw läuft, dessen eigene Weiterleitungsregel. Die vollständige Fehlersuche dazu steht in WireGuard-VPN einrichten.

Im Protokoll stehen tausende TLS-Fehler und der Server ist trotzdem langsam: Prüfen Sie zuerst Ihre eigene Protokollierungsstufe. Ab verb 4 schreibt OpenVPN je verworfenem Paket eine Zeile, und unter einer Flut macht das Schreiben mehr Last als der Angriff. Setzen Sie verb 3 und mute 20.

Der Widerruf eines Zertifikats wirkt nicht: In neun von zehn Fällen fehlt crl-verify in der Serverkonfiguration, oder die Sperrliste ist abgelaufen und OpenVPN weist danach alle Verbindungen ab. Prüfen Sie beides mit openssl crl -in /etc/openvpn/server/crl.pem -noout -nextupdate.

Der bisherige Anbieter hat die IP-Adresse gesperrt: Das ist Nullrouting. Der Anbieter schützt damit sein eigenes Netz, für Sie ist das Ergebnis identisch mit einem erfolgreichen Angriff, meist noch für Stunden danach. Bei einem VPN wiegt das besonders schwer, weil Ihre Nutzer nicht auf eine Ersatzadresse ausweichen können, solange die alte in ihren Profilen steht. Fragen Sie im Zweifel nach, ob gefiltert oder nullgeroutet wird. Die Antwort entscheidet mehr über Ihre Verfügbarkeit als jede Hardwareangabe. Die Grundlagen dazu stehen in Server vor DDoS-Angriffen sichern.

Im tcpdump ist nichts Auffälliges zu sehen: Wenn der Verkehr schon im Netz davor gefiltert wird, kommt auf dem Server erwartungsgemäß nichts an. Das ist der Normalfall bei funktionierender Filterung. Umgekehrt gilt: Ist die Leitung gesättigt, erreicht Sie unter Umständen nicht einmal mehr die SSH-Sitzung, mit der Sie messen wollten. Nutzen Sie dann die VNC-Konsole im Kundenbereich.

Kurz zusammengefasst

  • Die IP-Adresse eines VPN-Servers muss öffentlich erreichbar sein und steht in jeder Clientdatei. Sie lässt sich weder hinter einem CDN verstecken noch ohne Zutun auf jedem Gerät wechseln. Deshalb ist Filterung im Netz vor dem Server bei einem VPN die einzige belastbare Antwort auf einen volumetrischen Angriff.
  • Ein WireGuard-Server braucht genau einen offenen Port, voreingestellt 51820 UDP, und kennt darauf vier Nachrichtentypen. Ein reiner Einwahlserver empfängt nur Typ 1 (Handschlag, 148 Byte) und Typ 4 (Daten).
  • WireGuard prüft zuerst das Feld mac1, das aus dem öffentlichen Serverschlüssel abgeleitet wird. Pakete ohne gültiges mac1 kosten einen einzigen Hash. Nur wer ein Clientprofil besitzt, kann eine wirklich teure Handschlag-Flut erzeugen.
  • Die Cookie-Antwort unter Last bindet den Handschlag an die echte Quelladresse und macht gefälschte Handschlag-Fluten wirkungslos. Sie verhindert aber nicht, dass die Pakete ankommen und die Leitung füllen.
  • WireGuard begrenzt Handschläge fest auf 20 pro Sekunde je IPv4-Adresse beziehungsweise je IPv6-/64. Ein echter Client braucht einen Handschlag alle 120 Sekunden.
  • Bei OpenVPN ist tls-crypt der wirksamste kostenlose Schalter: Es verwirft unautorisierte Steuerpakete vor dem teuren TLS-Handschlag, macht den Dienst für Scanner unsichtbar und verhindert den Missbrauch als Reflektor.
  • OpenVPN über TCP leidet unter Angriff doppelt: SYN-Fluten erzeugen Zustand im Kernel, und TCP in TCP bricht bei Paketverlust überproportional ein. Nutzen Sie UDP, wo immer es geht.
  • Auf dem Server wirkt eine Ratenbegrenzung je Quelladresse, die nur die Handschlagpakete trifft und die Datenpakete ungebremst durchlässt. In nftables geht das über den Nachrichtentyp im ersten Byte der UDP-Nutzlast.
  • Ein anderer Port als 51820 senkt das Grundrauschen von Massenscannern und ist kein Schutz. Der Port steht in jeder Clientdatei, und ein volumetrischer Angriff richtet sich ohnehin nicht nach Ports.
  • Sobald die Leitung voll ist, hilft keine Regel auf dem Server mehr. Bei KernelHost filtert ein zweistufiger Dauerschutz ohne Aufpreis und ohne Nullrouting: 17 Tbps Mitigationskapazität im globalen Scrubbing-Netzwerk und Arbor-Echtzeitfilterung mit 3,2 Tbps in Frankfurt am Main.

Häufige Fragen

Warum lässt sich die IP-Adresse eines VPN-Servers nicht verstecken?
Weil jeder Client sie braucht, um sich überhaupt verbinden zu können. Sie steht im Klartext in jeder Profildatei: bei WireGuard in der Zeile Endpoint, bei OpenVPN in der Zeile remote. Ein CDN kann nicht davor, denn ein CDN vermittelt HTTP und HTTPS anhand des Hostnamens, und ein VPN liefert weder eine HTTP-Schicht noch einen Hostnamen im Paket. Und ein Adresswechsel bedeutet, dass jedes einzelne Gerät eine neue Profildatei braucht. Deshalb ist Filterung im Netz vor dem Server bei einem VPN die einzige belastbare Antwort auf einen volumetrischen Angriff.
Welchen Port und welches Protokoll braucht ein VPN-Server?
WireGuard braucht genau einen Port, voreingestellt 51820 UDP, eingestellt in ListenPort in der Datei /etc/wireguard/wg0.conf. WireGuard spricht ausschließlich UDP, es gibt kein TCP und keinen zweiten Steuerkanal. OpenVPN nutzt voreingestellt 1194 UDP und kann wahlweise über TCP laufen, meist auf 443. IKEv2 mit IPsec braucht 500 und 4500 UDP. Alles andere gehört nicht ins offene Netz: Die Verwaltungsschnittstelle von OpenVPN bindet man an 127.0.0.1, einen DNS-Auflöser für die Clients ausschließlich an die VPN-Schnittstelle.
Was macht WireGuard von sich aus gegen eine Handschlag-Flut?
Drei Dinge. Jede Handschlag-Nachricht trägt ein Feld mac1, einen Hash, dessen Schlüssel aus dem öffentlichen Schlüssel des Servers abgeleitet wird. Wer diesen Schlüssel nicht kennt, erzeugt nur Pakete, die nach einer einzigen Hashoperation verworfen werden, lange vor der teuren Kurvenrechnung. Zweitens begrenzt der Kernel die Verarbeitung von Handschlägen fest auf 20 Pakete je Sekunde und Quelle, bei IPv6 je /64. Drittens antwortet der Server unter Last mit einer Cookie-Antwort statt mit einem Handschlag. Gefälschte Absender kommen damit nie zum Abschluss.
Was leistet die Cookie-Antwort von WireGuard, und was leistet sie nicht?
Sie bindet den Handschlag an die echte Quelladresse. Sobald der Server unter Last steht, antwortet er auf eine Initiation mit einem 64 Byte großen Cookie, das aus einem Geheimnis des Servers sowie Adresse und Port des Absenders berechnet wird. Der Client muss dieses Cookie im nächsten Versuch einrechnen. Ein Angreifer mit gefälschter Absenderadresse sieht das Cookie nie und kommt deshalb nie in die teure Rechnung. Die Pakete kommen aber weiterhin an und belegen weiterhin Ihre Leitung. Gegen einen volumetrischen Angriff hilft der Mechanismus nicht.
Warum sieht ein WireGuard-Server einen Angriff nicht in seinen Protokollen?
Weil WireGuard auf kein einziges Paket antwortet, das die mac1-Prüfung nicht besteht, und weil es nichts protokolliert, was es sofort verwirft. Es sendet weder eine Fehlermeldung noch ein ICMP Port Unreachable, für einen Portscan meldet nmap nur open|filtered. Ein Angriff auf einen WireGuard-Server ist deshalb ausschließlich an den Zählern der Netzwerkkarte und des Kernels zu erkennen: ip -s link show eth0, /proc/net/softnet_stat und nstat. Der Befehl wg show zeigt lediglich, dass die letzten Handschläge alt werden, und nennt keinen Grund.
Warum hilft tls-crypt bei OpenVPN gegen eine Flut?
Weil es unautorisierte Steuerpakete verwirft, bevor OpenVPN einen TLS-Handschlag beginnt. Ein neuer Client schickt ein Paket vom Typ P_CONTROL_HARD_RESET_CLIENT_V2, und der Server antwortet darauf mit einem vollständigen TLS-Handschlag samt Zertifikatsprüfung, den er einsträngig abarbeitet. Mit tls-crypt trägt jedes Steuerpaket einen HMAC-SHA-256 und ist zusätzlich mit AES-256-CTR verschlüsselt. Pakete ohne gültigen HMAC fallen nach einer billigen Prüfung heraus. Nebenbei erkennt ein Scanner den Dienst nicht mehr als OpenVPN, und er lässt sich nicht als Reflektor missbrauchen.
Ist OpenVPN über UDP oder über TCP besser gegen Angriffe?
Über UDP, und zwar deutlich. TCP erzeugt Zustand im Kernel, bevor OpenVPN das Paket überhaupt sieht: Ein SYN-Flood füllt die Warteschlange halboffener Verbindungen, und einige zehntausend SYN-Pakete pro Sekunde genügen, lange bevor die Leitung voll ist. Dazu kommt TCP im TCP, das bei Paketverlust überproportional einbricht, weil das äußere TCP die Reihenfolge erzwingt und das innere die Verzögerung als Stau wertet. Und eine aufgebaute, aber stille TCP-Verbindung belegt bis zu 60 Sekunden einen Platz. Nehmen Sie TCP nur, wenn ein Netz Sie dazu zwingt.
Bringt es etwas, WireGuard auf einen anderen Port als 51820 zu legen?
Gegen Massenscanner ja, gegen einen gezielten Angriff nein. Scanner arbeiten Listen bekannter Ports ab, und 51820 steht in jeder dieser Listen. Ein ungewöhnlicher Port nimmt den Server aus diesen Durchläufen heraus, und das ist messbar weniger Grundrauschen. Der Port steht aber in jeder Clientdatei neben der Adresse: Wer Ihr Profil hat, hat auch den Port. Und ein volumetrischer Angriff richtet sich gar nicht nach Ports, er füllt die Leitung unabhängig davon, wohin die Pakete adressiert sind. Behandeln Sie die Portwahl als Hygiene, nicht als Schutz.
Kann ich mich mit nftables gegen einen DDoS-Angriff auf mein VPN wehren?
Gegen kleine Angriffe und Handschlag-Fluten ja, gegen volumetrische Angriffe nicht. Die wirksamste Regel begrenzt nur die Handschlagpakete je Quelladresse und lässt die Datenpakete ungebremst durch. Bei WireGuard geht das über den Nachrichtentyp im ersten Byte der UDP-Nutzlast (@th,64,8 gleich 1 für den Handschlag, gleich 4 für Daten) und über die feste Größe der Initiation von 148 Byte. Eine Firewall-Regel entscheidet aber immer über ein Paket, das bereits über Ihre Leitung gelaufen ist. Ist die Leitung voll, kommen die Pakete Ihrer Nutzer schon vorher nicht mehr durch.
Warum sollte ich conntrack für den VPN-Port abschalten?
Weil der Verbindungsverfolger für jedes UDP-Paar aus Adressen und Ports einen Eintrag anlegt, auch für ein einzelnes Paket mit gefälschtem Absender. Eine UDP-Flut füllt damit die Tabelle, der Kernel meldet nf_conntrack: table full, dropping packet und verwirft danach auch Pakete Ihrer echten Nutzer. Für einen VPN-Port ist diese Buchführung nutzlos, denn die Zugehörigkeit eines Pakets ergibt sich aus der Kryptografie. Setzen Sie notrack in der raw-Tabelle, aber achten Sie darauf: Danach greift ct state established für diese Pakete nicht mehr, jeder VPN-Port braucht eine ausdrückliche Regel.
Ab welcher Angriffsgröße schafft mein VPN-Server das nicht mehr allein?
Ein typischer Server hängt an 1 Gbit/s, das entspricht 125 Megabyte pro Sekunde. Angriffe gegen Projekte dieser Größe liegen üblicherweise zwischen 5 und 50 Gbit/s. Ebenso wichtig ist die Paketrate: In 1 Gbit/s passen bei 64 Byte großen Paketen rund 1,49 Millionen Pakete pro Sekunde, ein normaler Serverkernel verarbeitet nur einige hunderttausend davon. Bei einem VPN liegt die Grenze noch niedriger, weil jedes Paket auf dem VPN-Port mindestens eine kryptografische Prüfung kostet, bevor es verworfen werden darf. Ein Angriff kann Sie also lahmlegen, obwohl die Bandbreite nicht ausgereizt ist.
Geht mein VPN-Server bei KernelHost während eines Angriffs offline?
Nein. Es wird kein Nullrouting eingesetzt. Ihre IP-Adresse bleibt im Netz, verworfen werden nur die schädlichen Pakete. Der Schutz ist zweistufig: 17 Tbps Mitigationskapazität im globalen Scrubbing-Netzwerk und eine Arbor-Echtzeitfilterung mit 3,2 Tbps in Frankfurt am Main. Er läuft permanent und muss nicht erst auf einen Angriff reagieren, es gibt also keine Minuten am Anfang, in denen das VPN weg ist. Die Filterung passiert im Netz vor dem Server, Ihre Profildateien bleiben unverändert und auf Ihrer Seite ist kein Umbau nötig.
Kostet der DDoS-Schutz extra, und wann brauche ich Advanced DDoS Protection?
Der zweistufige Dauerschutz ist bei jedem Serverpaket ohne Aufpreis enthalten und ab der Bereitstellung aktiv, Sie müssen ihn weder bestellen noch einschalten. Die Advanced DDoS Protection lohnt sich, wenn Ihr Zugang gezielt und über Wochen angegriffen wird und Sie die Filterung selbst steuern wollen: dedizierte Schutz-IP, Schutzregeln je Port und Protokoll selbst verwaltbar im Kundenbereich, Änderungen greifen in Echtzeit. Der Preis beginnt bei 50,00 € im Monat, PrePaid, ohne Mindestlaufzeit und ohne Einrichtungsgebühr. Wer seinen VPN-Server woanders betreibt, kann den Schutz nicht nachrüsten, denn er ist Teil des Netzes. Die Empfehlung lautet dann Umzug zu KernelHost.

VPN VPN-Server-DDoS-Schutz WireGuard OpenVPN nftables Port 51820 Port 1194 Advanced DDoS Protection