Die Schwachstelle
Wenn:
- der VPN-Endpunkt ein IP-adressiertes Interface in einem unsicheren Netz unterhält und
- das so genannte “Weak Host Model” gilt (der Default, den man auch nicht so einfach ändern kann) und
- Reverse Path Filtering nicht aktiv ist oder im Modus “loose” betrieben wird,
Dann:
- kann ein Angreifer manipulierte Pakete an das Linux absenden, die dieses dann in die VPN-Verbindung einspielen wird, und
- durch Beobachtung des Timings von verschlüsselten Paketen kann der Angreifer diese Pakete mit Sequenz-Nummern ausstatten, die die Pakete als Teil einer gültigen TCP- oder UDP-Verbindung über den Tunnel erscheinen lassen.
Der Angreifer kann hingegen nicht oder nicht ohne Weiteres:
- Nutzdaten in Verbindungen einspielen, da er sie nicht verschlüsseln kann, oder
- Nutzdaten aus den Verbindungen auslesen, da er sie nicht entschlüsseln kann.
Nichtsdestotrotz ist die Sicherheitszusage des VPNs damit gedämpft und tiefere Angriffe sind vorstellbar bzw. möglich.
Die Gegenmaßnahmen
Vorbemerkung: Wer “Bonding” oder “Multihoming” mit mehreren Netzwerk-Adaptern macht, muss sich tiefer einlesen, das wird in diesem Artikel nicht behandelt.
“Weak” und “Strong Host Model” werden in RFC 1122 beschrieben; “Reverse Path Filtering” im Modus “strict” bzw. “loose” in RFC 3704.
- https://tools.ietf.org/html/rfc1122
- https://tools.ietf.org/html/rfc3704
- Reverse Path Filtering für IPv4 aktivieren (mit
sysctl
):
Folgende sysctl-Variablen sind maßgeblich:
-
Die Voreinstellung für alle Interfaces, wenn nicht anders gesetzt:
net.ipv4.conf.default.rp_filter=0|1|2
-
Die Einstellung für alle Interfaces:
net.ipv4.conf.all.rp_filter=0|1|2
-
Eine abweichende Einstellung für das Interface
eth0
:net.ipv4.conf.eth0.rp_filter=0|1|2
Der Wert ist Linux Kernel-seitig per default auf 0 (“aus”) gesetzt. Es gibt keinen Standard bei den Linux-Distributionen, zumindest einige Installationen von Systemd setzen ihn auf 2 (“loose”).
Der Wert sollte für die Netzwerkkarte im unsicheren Netz auf 1 (“strict reverse path filtering”) gesetzt werden. Bei mir sind das zwei zusätzliche Zeilen in /etc/sysctl.d/99-sysctl.conf
:
net.ipv4.conf.enp0s31f6.rp_filter=1
net.ipv4.conf.wlp61s0.rp_filter=1
Es sei nochmal bemerkt, dass diese Einstellungen bei Bonding oder Multihoming zu fatalen Problemen führen können; auch manche Setups von Traffic-Redirection auf einem VPN-Endpunkt/Gateway könnten nicht mehr funktionieren wie erwartet. Wer das braucht, muss sich wirklich tiefer einlesen und ggf. zum “Strong Host Model” mit separaten Routingtabellen übergehen.
- Reverse Path Filtering für IPv4 aktivieren (mit ip6tables):
Wer firewalld benutzt, prüft in der /etc/firewalld/firewalld.conf
die Einstellung IPv6_rpfilter
; steht diese auf yes
und ist firewalld aktiv, ist Reverse Path Filtering für IPv6 bereits aktiv.
Manuell kann eine entsprechende Regel wie folgt eingefügt werden:
ip6tables -t raw -I PREROUTING -m rpfilter --invert -j DROP
- Eingehende Pakete an das VPN-Netzwerk verwerfen (am Beispiel IPv4):
Als zusätzliche Schutzmaßnahme kann der IP-Paketfilter (iptables, nftables) verwendet werden. Das folgende Beispiel behandelt einen OpenVPN-Tunnel “beispiel”, der via IPv4 aufgebaut wird. Paketfilter-Regeln werden darum mit “iptables” hinzugefügt; würde die Verbindung mit IPv6 stattfinden, würde stattdessen “ip6tables” zum Einsatz kommen.
Beim Aufbau der OpenVPN-Verbindung wird per up-Skript eine iptables-Regel zu INPUT hinzugefügt, die jedes Paket verwirft, das an das VPN-Netzwerk addressiert ist, aber nicht auf dem Tunnel-Device ankommt. Dafür nutzt der Filter die Argumente des up-Skripts, die ihn über Netzwerk-Adresse, Netzmaske und Interface-Namen des VPNs informieren. Damit kann das up-Skript für mehrere VPNs gleichzeitig wiederverwendet werden.
In /etc/openvpn/client/beispiel.conf
:
...
script-security 2
up beispiel/up.sh
down beispiel/down.sh
In /etc/openvpn/client/beispiel/up.sh
:
#!/bin/sh
tun_dev=$1
ifconfig_local_ip=$4
ifconfig_remote_ip=$5
mode=${6:-init}
if test "$mode" = "init" ; then
/usr/sbin/iptables \
-I INPUT \
-d "$ifconfig_local_ip/$ifconfig_remote_ip" \
\! -i $tun_dev \
-j DROP
fi
In /etc/openvpn/client/beispiel/down.sh
:
#!/bin/sh
tun_dev=$1
ifconfig_local_ip=$4
ifconfig_remote_ip=$5
/usr/sbin/iptables \
-D INPUT \
-d "$ifconfig_local_ip/$ifconfig_remote_ip" \
\! -i
$tun_dev \
-j DROP
Die Angreifbarkeit, die in CVE-2019-14899 beschrieben wird, nutzt den Umstand, dass Linux-Netzwerkinterfaces in der Standardkonfiguration Pakete mit Zieladressen annehmen, die nicht auf ihnen selbst (aber auf einer anderen Netzwerkschnittstelle desselben Rechners) eingerichtet sind. Mit den hier dargestellten Gegenmaßnahmen unterbinden Sie dieses Verhalten.