Wechsel von OpenVPN zu WireGuard zur Verschmelzung von Netzwerken zu einem L2-Netzwerk

Wechsel von OpenVPN zu WireGuard zur Verschmelzung von Netzwerken zu einem L2-Netzwerk

Ich möchte meine Erfahrungen bei der Verbindung von Netzwerken in drei geografisch voneinander entfernten Wohnungen teilen, in denen jeweils Router mit OpenWRT als Gateways verwendet werden, zu einem gemeinsamen Netzwerk. Bei der Auswahl der Methode zur Netzwerkverbindung zwischen L3 mit Routing von Subnetzen und L2 mit Bridging, bei dem alle Netzwerknoten in einem Subnetz sind, wurde die zweite Methode, die in der Einrichtung komplexer ist, aber bessere Möglichkeiten bietet, bevorzugt, da im zu schaffenden Netzwerk die transparente Nutzung der Technologien Wake-on-Lan und DLNA vorgesehen war.

Teil 1: Vorgeschichte

Als Protokoll für die Umsetzung dieser Aufgabe wurde zunächst OpenVPN gewählt, da es erstens in der Lage ist, ein tap-Gerät zu erstellen, das problemlos in einen Bridge integriert werden kann, und zweitens OpenVPN die Arbeit über das TCP-Protokoll unterstützt, was ebenfalls wichtig war, da in keiner der Wohnungen eine feste IP-Adresse vorhanden war und ich STUN nicht nutzen konnte, da mein Anbieter aus irgendeinem Grund eingehende Verbindungen über das UDP-Protokoll aus seinen Netzen blockiert, während das TCP-Protokoll es mir ermöglichte, den VPN-Server-Port auf dem gemieteten VPS über SSH weiterzuleiten. Ja, dieser Ansatz bedeutet eine höhere Belastung, da die Daten doppelt verschlüsselt werden, aber ich wollte das VPS nicht in mein privates Netzwerk integrieren, da das Risiko bestand, dass Dritte die Kontrolle darüber erlangen, weshalb es äußerst unerwünscht war, ein solches Gerät im Heimnetzwerk zu haben, und ich entschloss mich, für Sicherheit einen hohen Overhead in Kauf zu nehmen.

Für die Portweiterleitung auf dem Router, auf dem der Server eingerichtet werden sollte, wurde das Programm sshtunnel verwendet. Die Feinheiten seiner Konfiguration werde ich nicht beschreiben – das ist relativ einfach zu machen; ich möchte nur darauf hinweisen, dass seine Aufgabe die Weiterleitung des TCP-Ports 1194 vom Router auf das VPS war. Anschließend wurde der OpenVPN-Server auf dem tap0-Gerät eingerichtet, das in die Bridge br-lan eingefügt wurde. Nachdem die Verbindung zum neu eingerichteten Server von einem Laptop überprüft wurde, war klar, dass die Idee mit der Portweiterleitung erfolgreich war und mein Laptop ein Mitglied des Router-Netzwerks wurde, obwohl er physisch nicht darin war.

Die restlichen Schritte waren einfach: Es musste IP-Adressen in verschiedenen Wohnungen so verteilt werden, dass sie nicht in Konflikt standen, und die Router als OpenVPN-Clients konfiguriert werden.
Es wurden folgende IP-Adressen für die Router und DHCP-Server-Bereiche gewählt:

  • 192.168.10.1 mit dem Bereich 192.168.10.2192.168.10.80 für den Server
  • 192.168.10.100 mit dem Bereich 192.168.10.101192.168.10.149 für den Router in Wohnung Nr. 2
  • 192.168.10.150 mit dem Bereich 192.168.10.151192.168.10.199 für den Router in Wohnung Nr. 3

Es war auch notwendig, genau diese Adressen für die OpenVPN-Server-Client-Router zuzuweisen, indem man die folgende Zeile in seine Konfiguration hinzufügt:

ifconfig-pool-persist /etc/openvpn/ipp.txt 0

und die folgenden Zeilen in die Datei /etc/openvpn/ipp.txt hinzuzufügen:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

wobei flat1_id und flat2_id die Gerätenamen sind, die beim Erstellen der Zertifikate für die Verbindung zu OpenVPN angegeben werden.

Anschließend wurden auf den Routern die OpenVPN-Clients konfiguriert, die tap0-Geräte wurden beide in den br-lan-Bridge aufgenommen. In diesem Stadium schien alles in Ordnung zu sein, da alle drei Netzwerke einander sehen und als eine Einheit funktionieren. Es stellte sich jedoch heraus, dass es ein unangenehmer Punkt gab: Manchmal konnten Geräte eine IP-Adresse nicht von ihrem Router erhalten, mit allen daraus resultierenden Konsequenzen. Aus irgendeinem Grund konnte der Router in einer der Wohnungen nicht rechtzeitig auf DHCPDISCOVER antworten, und das Gerät erhielt nicht seine Adresse. Ich erkannte, dass ich solche Anfragen in tap0 auf jedem der Router filtern musste, aber wie sich herausstellte, kann iptables nicht mit einem Gerät arbeiten, wenn es Teil einer Brücke ist, und ich benötigte ebtables zu Hilfe. Leider war es in meinen Firmware-Versionen nicht vorhanden, und ich musste die Images für jedes Gerät neu erstellen. Nachdem ich dies getan hatte und solche Zeilen in /etc/rc.local jedes Routers hinzugefügt hatte, war das Problem gelöst:

ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A INPUT --in-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP
ebtables -A FORWARD --out-interface tap0 --protocol ipv4 --ip-protocol udp --ip-source-port 67:68 -j DROP

Diese Konfiguration hielt drei Jahre lang.

Teil 2: Einführung in WireGuard

In letzter Zeit wird im Internet zunehmend über WireGuard gesprochen, bewundert für die Einfachheit seiner Konfiguration, die hohe Übertragungsgeschwindigkeit und die niedrige Latenz bei vergleichbarer Sicherheit. Eine weitere Recherche ergab, dass weder der Betrieb als Teil einer Brücke noch der Betrieb über das TCP-Protokoll unterstützt wird, was mich zu der Überzeugung brachte, dass es für mich keine Alternative zu OpenVPN gibt. So zögerte ich, mich mit WireGuard vertraut zu machen.

Vor ein paar Tagen ging die Nachricht durch die IT-Ressourcen, dass WireGuard endlich in den Linux-Kernel ab Version 5.6 integriert werden wird. Wie immer lobten die Nachrichtenartikel WireGuard. Ich begann erneut, nach Alternativen zum guten alten OpenVPN zu suchen. Diesmal stieß ich auf diesen Artikel. Darin ging es um die Erstellung eines Ethernet-Tunnels über L3 mithilfe von GRE. Dieser Artikel weckte Hoffnung in mir. Unklar blieb, was mit dem UDP-Protokoll zu tun ist. Meine Suche führte mich zu Artikeln über die Verwendung von socat in Verbindung mit SSH-Tunneln, um einen UDP-Port weiterzuleiten, jedoch wurde angemerkt, dass dieser Ansatz nur im Modus einer Verbindung funktioniert, was bedeutet, dass der Betrieb mehrerer VPN-Clients nicht möglich wäre. Mir kam die Idee, einen VPN-Server auf einem VPS zu betreiben und GRE für die Clients zu konfigurieren, aber wie sich herausstellte, unterstützt GRE keine Verschlüsselung, was dazu führen würde, dass, wenn Dritte Zugriff auf den Server erhalten, der gesamte Verkehr zwischen meinen Netzwerken in ihren Händen wäre, was für mich grundsätzlich inakzeptabel war.

Erneut fiel die Entscheidung zugunsten überschüssiger Verschlüsselung, indem ein VPN über VPN nach folgendem Schema verwendet wird:

VPN der ersten Ebene:
VPS ist Server mit der internen Adresse 192.168.30.1
MC ist Client VPS mit der internen Adresse 192.168.30.2
MK2 ist Client VPS mit der internen Adresse 192.168.30.3
MK3 ist Client VPS mit der internen Adresse 192.168.30.4

VPN der zweiten Ebene:
MC ist Server mit der externen Adresse 192.168.30.2 und der internen 192.168.31.1
MK2 ist Client MC mit der Adresse 192.168.30.2 und hat die interne IP 192.168.31.2
MK3 ist Client MC mit der Adresse 192.168.30.2 und hat die interne IP 192.168.31.3

* MC — Router-Server in Wohnung 1, MK2 — Router in Wohnung 2, MK3 — Router in Wohnung 3
* Die Konfigurationen der Geräte sind im Spoiler am Ende des Artikels veröffentlicht.

So, die Pings zwischen den Knoten des Netzwerks 192.168.31.0/24 laufen, es ist an der Zeit, mit der Einrichtung des GRE-Tunnels zu beginnen. Zuvor, um den Zugriff auf die Router nicht zu verlieren, sollten SSH-Tunnel zur Weiterleitung des Ports 22 auf dem VPS eingerichtet werden, sodass beispielsweise der Router aus Wohnung 2 über den Port 10022 auf dem VPS erreichbar ist und der Router aus Wohnung 3 über den Port 11122. Die Weiterleitungseinrichtung sollte am besten mit sshtunnel erfolgen, da es den Tunnel im Falle eines Abbruchs wiederherstellt.

Tunnel eingerichtet, man kann sich über den weitergeleiteten Port per SSH verbinden:

ssh root@MEIN_VPS -p 10022

Danach sollte OpenVPN deaktiviert werden:

/etc/init.d/openvpn stop

Jetzt richten wir den GRE-Tunnel im Router aus Wohnung 2 ein:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set grelan0 up

Und wir fügen die erstellte Schnittstelle dem Bridge hinzu:

brctl addif br-lan grelan0

Das gleiche Verfahren führen wir am Server-Router durch:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set grelan0 up

Und auch hier fügen wir die erstellte Schnittstelle der Bridge hinzu:

brctl addif br-lan grelan0

Von diesem Moment an beginnen die Pings erfolgreich in das neue Netzwerk zu gehen und ich gehe mit Zufriedenheit einen Kaffee trinken. Um zu bewerten, wie das Netzwerk am anderen Ende funktioniert, versuche ich, mich per SSH mit einem der Computer in Wohnung 2 zu verbinden, aber der SSH-Client "hängt", ohne ein Passwort einzugeben. Ich versuche, mich mit diesem Computer über Telnet auf Port 22 zu verbinden und sehe eine Zeile, aus der ich entnehmen kann, dass die Verbindung hergestellt wird, der SSH-Server antwortet, aber aus irgendeinem Grund wird mir nicht angeboten, mich einzugeben.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Ich versuche, mich auch über VNC zu verbinden und sehe einen schwarzen Bildschirm. Ich überzeuge mich, dass es am entfernten Computer liegt, denn ich kann mich problemlos über die interne Adresse mit dem Router aus dieser Wohnung verbinden. Dennoch beschließe ich, mich über den Router mit SSH zu diesem Computer zu verbinden und stelle überrascht fest, dass die Verbindung erfolgreich ist und der entfernte Computer ganz normal funktioniert, aber auch nicht mit meinem Computer verbinden kann.

Ich nehme das Gerät grelan0 aus der Bridge und starte OpenVPN auf dem Router in Wohnung 2, und stelle fest, dass das Netzwerk wieder funktioniert und die Verbindungen nicht abreißen. Bei meiner Suche stoße ich auf Foren, in denen Leute sich über ähnliche Probleme beschweren und ihnen geraten wird, MTU zu erhöhen. Gesagt, getan. Allerdings kam es, solange MTU nicht groß genug eingestellt war – 7000 für gretap-Geräte – entweder zu Verbindungsabbrüchen bei TCP oder zu einer niedrigen Übertragungsgeschwindigkeit. Wegen des hohen MTU für gretap wurde das MTU für die WireGuard-Verbindungen der ersten und zweiten Ebene auf 8000 und 7500 eingestellt.

Ich habe eine ähnliche Konfiguration auch am Router in Wohnung 3 vorgenommen, mit dem einzigen Unterschied, dass am Server-Router eine zweite gretap-Schnittstelle mit dem Namen grelan1 hinzugefügt wurde, die ebenfalls der Bridge br-lan hinzugefügt wurde.

Es funktioniert alles. Jetzt kann das gretap-Setup in den Autostart gelegt werden. Dazu:

Ich habe diese Zeilen in /etc/rc.local auf dem Router in Wohnung 2 eingefügt:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.2
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Ich habe dies in /etc/rc.local auf dem Router in Wohnung 3 hinzugefügt:

ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

Und auf dem Router-Server:

ip link add grelan0 type gretap remote 192.168.31.2 local 192.168.31.1
ip link set dev grelan0 mtu 7000
ip link set grelan0 up
brctl addif br-lan grelan0

ip link add grelan1 type gretap remote 192.168.31.3 local 192.168.31.1
ip link set dev grelan1 mtu 7000
ip link set grelan1 up
brctl addif br-lan grelan1

Nach dem Neustart der Client-Router stellte ich fest, dass sie aus irgendeinem Grund keine Verbindung zum Server herstellen konnten. Nachdem ich mich per SSH eingeloggt hatte (zum Glück hatte ich vorher einen sshtunnel dafür eingerichtet), stellte ich fest, dass WireGuard anscheinend eine Route für das Endpunkt erstellt, jedoch fehlerhaft. So war für 192.168.30.2 in der Routing-Tabelle eine Route über das Interface pppoe-wan angegeben, das heißt über das Internet, obwohl die Route zu ihm über das Interface wg0 gehen sollte. Nachdem ich diese Route gelöscht hatte, war die Verbindung wiederhergestellt. Ich konnte keine Anleitungen finden, wie man WireGuard davon abhält, diese Routen zu erstellen. Noch mehr, ich verstand nicht, ob dies eine Eigenheit von OpenWRT oder WireGuard selbst war. Um nicht lange an diesem Problem herumzutüfteln, fügte ich einfach auf beiden Routern im Skript, das zeitgesteuert wiederholt wird, eine Zeile hinzu, die diese Route löschte:

route del 192.168.30.2

Zusammenfassend

Ich habe bisher keinen vollständigen Verzicht auf OpenVPN erreicht, da ich manchmal mit meinem Laptop oder Telefon eine neue Verbindung herstellen muss, und die Einrichtung eines gretap-Geräts auf diesen im Allgemeinen nicht möglich ist. Trotzdem habe ich einen Geschwindigkeitsvorteil beim Datentransfer zwischen den Wohnungen erhalten, und zum Beispiel verursacht die Nutzung von VNC jetzt keine Beschwerden. Der Ping hat sich nur geringfügig verringert, ist aber stabiler geworden:

Bei Verwendung von OpenVPN:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=133 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=125 ms

--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19006ms
rtt min/avg/max/mdev = 124.722/126.152/136.907/3.065 ms

Bei Verwendung von WireGuard:

[r0ck3r@desktop ~]$ ping -c 20 192.168.10.110
PING 192.168.10.110 (192.168.10.110) 56(84) bytes of data.
64 bytes from 192.168.10.110: icmp_seq=1 ttl=64 time=124 ms
...
64 bytes from 192.168.10.110: icmp_seq=20 ttl=64 time=124 ms
--- 192.168.10.110 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 19003ms
rtt min/avg/max/mdev = 123.954/124.423/126.708/0.675 ms

Dabei beeinflusst ihn stärker der hohe Ping zu VPS, der etwa 61,5 ms beträgt.

Die Geschwindigkeit hat sich jedoch erheblich erhöht. In der Wohnung mit dem Router-Server habe ich eine Internetgeschwindigkeit von 30 Mbit/s, während die anderen Wohnungen jeweils 5 Mbit/s haben. Dabei gelang es mir während der Nutzung von OpenVPN nicht, eine Datenübertragungsrate zwischen den Netzwerken von mehr als 3,8 Mbit/s nach den Anzeigen von iperf zu erreichen, während WireGuard diese auf die gleichen 5 Mbit/s steigerte.

WireGuard-Konfiguration auf VPS[Schnittstelle]
Adresse = 192.168.30.1/24
ListenPort = 51820
PrivateKey =

[Peer]
PublicKey =
AllowedIPs = 192.168.30.2/32

[Peer]
PublicKey =
AllowedIPs = 192.168.30.3/32

[Peer]
PublicKey =
AllowedIPs = 192.168.30.4/32

WireGuard-Konfiguration auf MK (wird in /etc/config/network hinzugefügt)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.2/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МС'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option route_allowed_ips '1'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - сервер
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option listen_port '51821'
        list addresses '192.168.31.1/24'
        option auto '1'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list allowed_ips '192.168.31.2'

config wireguard_wg1ip link add grelan0 type gretap remote 192.168.31.1 local 192.168.31.3

        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list allowed_ips '192.168.31.3'

WireGuard-Konfiguration auf MK2 (wird in /etc/config/network hinzugefügt)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.3/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК2'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК2'
        list addresses '192.168.31.2/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

WireGuard-Konfiguration auf MK3 (wird in /etc/config/network hinzugefügt)

#VPN первого уровня - клиент
config interface 'wg0'
        option proto 'wireguard'
        list addresses '192.168.30.4/24'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_1_МК3'
        option auto '1'
        option mtu '8000'

config wireguard_wg0
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_1_VPS'
        option endpoint_port '51820'
        option persistent_keepalive '25'
        list allowed_ips '192.168.30.0/24'
        option endpoint_host 'IP_АДРЕС_VPS'

#VPN второго уровня - клиент
config interface 'wg1'
        option proto 'wireguard'
        option private_key 'ЗАКРЫТЫЙ_КЛЮЧ_VPN_2_МК3'
        list addresses '192.168.31.3/24'
        option auto '1'
        option listen_port '51821'
        option mtu '7500'

config wireguard_wg1
        option public_key 'ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МС'
        option endpoint_host '192.168.30.2'
        option endpoint_port '51821'
        option persistent_keepalive '25'
        list allowed_ips '192.168.31.0/24'

In den beschriebenen Konfigurationen für VPN der zweiten Ebene weise ich WireGuard-Clients den Port 51821 zu. Theoretisch ist dies nicht notwendig, da der Client eine Verbindung von jedem freien, unprivilegierten Port herstellen kann. Ich habe es jedoch so gemacht, dass alle eingehenden Verbindungen auf den Schnittstellen wg0 aller Router, mit Ausnahme der eingehenden UDP-Verbindungen auf Port 51821, verboten werden können.

Ich hoffe, dass der Artikel für jemanden nützlich sein wird.

P.S. Ich möchte auch mein Skript teilen, das mir PUSH-Benachrichtigungen auf mein Telefon in die App WirePusher sendet, wenn ein neues Gerät in meinem Netzwerk erscheint. Hier ist der Link zum Skript: github.com/r0ck3r/device_discover.

UPDATE: OpenVPN-Server- und Client-Konfiguration

OpenVPN-Server

client-to-client

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/vpn-server.crt
dh /etc/openvpn/server/dh.pem
key /etc/openvpn/server/vpn-server.key

dev tap
ifconfig-pool-persist /etc/openvpn/ipp.txt 0
keepalive 10 60
proto tcp4
server-bridge 192.168.10.1 255.255.255.0 192.168.10.80 192.168.10.254
status /var/log/openvpn-status.log
verb 3
comp-lzo

OpenVPN-Client

client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Ändere zur externen IP deines Routers
resolv-retry infinite
nobind

ca client/ca.crt
cert client/client.crt
key client/client.key
dh client/dh.pem

comp-lzo
persist-tun
persist-key
verb 3

Zur Generierung der Zertifikate habe ich easy-rsa verwendet.

Quelle: habr.com

60GB SSD 8Gb DDR4