Vor einiger Zeit war ich gezwungen den Traffic eines bestimmten Benutzeraccounts auf meinem Server über ein bestimmtes VPN-Interface zu schicken.
Mit ein wenig Konfigurations-Fuu lässt sich das ohne Probleme umsetzen.
Die Ausgangssituation
Ich habe zwei Server:
Server A
- OpenVPN Server im 10.10.0.1/24 Netz
- Setzt Default-Route beim Client (push „redirect-gateway def1 bypass-dhcp“)
Server B
- OpenVPN Client mit 10.10.0.10/24 IP am tun1
- Benutzer dessen Traffic weitergeleitet werden soll namens „yacy“
Wie anfangs schon erwähnt möchte ich nur den ausgehenden Traffic des Benutzers „yacy“ über das VPN zu Server A schicken. Folgende Probleme gilt es also auf Server B zu lösen:
- Droppen der „Default“ Route
- Weiterleitung des ausgehenden Traffics des „yacy“ Benutzers
- Der restliche Traffic soll uneingeschränkt über das eth0 Netzwerkinterface laufen
Die Umsetzung
OpenVPN Konfiguration anpassen
Um das erste Problem zu lösen, müssen wir unserem OpenVPN Client mitteilen, das er die vom OpenVPN Server gepushte Default Route nicht annehmen soll. Dazu muss man die folgende Option in die entsprechende „.ovpn“ Konfigurationsdatei eintragen:
#No default route route-nopull
Trafficweiterleitung
Wir werden später mittels den Iptables Pakete von unserem Benutzer markieren, um diese eine bestimmte Route zu schicken. Dazu erstellen wir zunächst eine neue Routing-Tabelle mit dem Namen „vpn.out“.
echo 201 vpn.out | sudo tee -a /etc/iproute2/rt_tables
Danach erstellen wir eine Regel, welche alle Pakete mit der Markierung „1“ durch die Tabelle „vpn.out“ jagt:
sudo /sbin/ip rule add fwmark 1 table vpn.out
Bisher sollte unsere neue Routing-Tabelle noch leer sein und die Pakete wissen noch nicht wohin. Das ändert sich jetzt:
sudo /sbin/ip route add default via 10.10.0.10 dev tun1 table vpn.out
Default-mäßig werden alle Pakete die in diese Tabelle kommen über das tun1 Device zum Server A geschickt.
Als nächstes bringen wir unserem „tun1“ Device bei, das es etwas lockerer mit der Überprüfung der Routebarkeit von Paketen sein soll. Der Wert „2“ erlaubt das Akzeptieren des Paketes falls es irgendwie auf irgendeinem Device geroutet werden kann.
sudo /sbin/sysctl -w net.ipv4.conf.tun1.rp_filter=2
Als nächstes müssen wir sicherstellen das alle Pakete vom Benutzer „yacy“, die das System über eth0 verlassen wollen, mit „1“ markiert werden. Dazu verwenden wir die Iptables:
sudo /sbin/iptables -t mangle -A OUTPUT -m owner --uid-owner yacy -o eth0 -j MARK --set-mark 1
Zuletzt müssen wir uns noch darum bemühen das die Pakete auch wieder zu uns zurück finden. Ein Source-NAT ist dafür genau richtig:
sudo /sbin/iptables -t nat -A POSTROUTING -o tun1 -j SNAT --to-source 10.10.0.10
Fertig :)
~ Sebastian