Migracja z OpenVPN do WireGuard w celu konsolidacji sieci w jedną sieć L2

Migracja z OpenVPN do WireGuard w celu konsolidacji sieci w jedną sieć L2

Chciałbym podzielić się swoim doświadczeniem z łączenia sieci w trzech odległych geograficznie mieszkaniach, z których każde wykorzystuje routery z OpenWRT jako bramą, w jedną wspólną sieć. Wybierając metodę łączenia sieci między L3 z routingiem podsieci i L2 z mostowaniem, gdy wszystkie węzły sieci będą w tej samej podsieci, preferowano drugą metodę, która jest trudniejsza do skonfigurowania, ale daje większe możliwości, ponieważ jest przezroczysta w tworzonej sieci zaplanowano wykorzystanie technologii Wake-on-Lan oraz DLNA.

Część 1: Tło

OpenVPN został pierwotnie wybrany jako protokół do realizacji tego zadania, ponieważ po pierwsze może stworzyć urządzenie dotykowe, które można bez problemu dodać do mostka, a po drugie OpenVPN obsługuje działanie na protokole TCP, co było również ważne, ponieważ żadne z mieszkań nie miało dedykowanego adresu IP, a ja nie mogłem używać STUN, bo z jakiegoś powodu mój ISP blokuje przychodzące połączenia UDP z ich sieci, podczas gdy protokół TCP pozwalał mi na przekierowanie portu serwera VPN na wynajętym VPS przez SSH. Owszem, takie podejście niesie ze sobą duże obciążenie, ponieważ dane są szyfrowane dwukrotnie, ale nie chciałem wprowadzać VPS-a do mojej sieci prywatnej, ponieważ wciąż istniało ryzyko przejęcia nad nim kontroli przez osoby trzecie, dlatego posiadanie takiego urządzenie w sieci domowej było wyjątkowo niepożądane i zdecydowano zapłacić za bezpieczeństwo dużym kosztem.

Do przekierowania portu na routerze, na którym planowano zainstalować serwer, wykorzystano program sshtunnel. Nie będę opisywał zawiłości jego konfiguracji – robi się to dość łatwo, zaznaczam tylko, że jego zadaniem było przekierowanie portu TCP 1194 z routera na VPS. Następnie skonfigurowano serwer OpenVPN na urządzeniu tap0, które zostało podłączone do mostka br-lan. Po sprawdzeniu połączenia z nowo utworzonym serwerem z laptopa stało się jasne, że pomysł przekierowania portów się usprawiedliwił i mój laptop stał się członkiem sieci routera, choć fizycznie w nim go nie było.

Sprawa pozostała niewielka: trzeba było rozdzielić adresy IP w różnych mieszkaniach, aby nie kolidowały i skonfigurować routery jako klientów OpenVPN.
Wybrano następujące adresy IP routera i zakresy serwerów DHCP:

  • 192.168.10.1 z zasięgiem 192.168.10.2 - 192.168.10.80 dla serwera
  • 192.168.10.100 z zasięgiem 192.168.10.101 - 192.168.10.149 dla routera w mieszkaniu nr 2
  • 192.168.10.150 z zasięgiem 192.168.10.151 - 192.168.10.199 dla routera w mieszkaniu nr 3

Konieczne było również przypisanie dokładnie tych adresów do routerów klienckich serwera OpenVPN poprzez dodanie do jego konfiguracji linii:

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

i dodanie następujących linii do pliku /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

gdzie flat1_id i flat2_id to nazwy urządzeń określone podczas generowania certyfikatów do połączenia z OpenVPN

Następnie na routerach skonfigurowano klientów OpenVPN, do mostka br-lan dodano urządzenia tap0 na obu. Na tym etapie wszystko wydawało się być w porządku, ponieważ wszystkie trzy sieci widzą się i działają jako całość. Okazało się jednak niezbyt przyjemny szczegół: czasami urządzenia mogły uzyskać adres IP nie ze swojego routera, ze wszystkimi wynikającymi z tego konsekwencjami. Z jakiegoś powodu router w jednym z mieszkań nie zdążył na czas odpowiedzieć na DHCPDISCOVER i urządzenie otrzymało zły adres. Zdałem sobie sprawę, że muszę filtrować takie żądania w tap0 na każdym z routerów, ale jak się okazało, iptables nie może współpracować z urządzeniem, które jest częścią mostu i ebtables powinien przyjść mi z pomocą. Żałuję, że nie było tego w moim oprogramowaniu i musiałem odbudować obrazy dla każdego urządzenia. Robiąc to i dodając te linie do /etc/rc.local każdego routera, problem został rozwiązany:

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

Taka konfiguracja trwała trzy lata.

Część 2: Przedstawiamy WireGuard

Ostatnio w internecie coraz częściej mówi się o WireGuardzie, zachwycając się prostotą jego konfiguracji, dużą szybkością transferu, niskim pingiem przy porównywalnym bezpieczeństwie. Poszukiwanie dalszych informacji na jego temat uświadomiło mi, że nie obsługuje on ani pracy jako członek mostu, ani pracy na protokole TCP, co utwierdziło mnie w przekonaniu, że nadal nie ma dla mnie alternatywy dla OpenVPN. Odłożyłem więc poznanie WireGuard.

Kilka dni temu wiadomość rozeszła się po zasobach w taki czy inny sposób związany z IT, że WireGuard zostanie wreszcie włączony do jądra Linuksa, począwszy od wersji 5.6. Artykuły prasowe jak zawsze chwaliły WireGuard. Ponownie pogrążyłem się w poszukiwaniu sposobów na zastąpienie starego, dobrego OpenVPN. Tym razem wpadłem Ten artykuł. Mówiono o stworzeniu tunelu Ethernet przez L3 przy użyciu GRE. Ten artykuł dał mi nadzieję. Pozostało niejasne, co zrobić z protokołem UDP. Wyszukiwanie doprowadziło mnie do artykułów o używaniu socat w połączeniu z tunelem SSH do przekazywania portu UDP, jednak zauważyli, że to podejście działa tylko w trybie pojedynczego połączenia, co oznacza, że ​​wielu klientów VPN byłoby niemożliwych. Wpadłem na pomysł, aby założyć serwer VPN na VPS i skonfigurować GRE dla klientów, ale jak się okazało, GRE nie obsługuje szyfrowania, co spowoduje, że jeśli osoby trzecie uzyskają dostęp do serwera, cały ruch między moimi sieciami jest w ich rękach, co w ogóle mi nie odpowiadało.

Ponownie zdecydowano się na redundantne szyfrowanie, wykorzystując VPN przez VPN według następującego schematu:

VPN warstwy XNUMX:
VPS jest serwer z adresem wewnętrznym 192.168.30.1
MS jest klient VPS z adresem wewnętrznym 192.168.30.2
MK2 jest klient VPS z adresem wewnętrznym 192.168.30.3
MK3 jest klient VPS z adresem wewnętrznym 192.168.30.4

Sieć VPN warstwy XNUMX:
MS jest serwer z adresem zewnętrznym 192.168.30.2 i wewnętrznym 192.168.31.1
MK2 jest klient MS o adresie 192.168.30.2 i wewnętrznym IP 192.168.31.2
MK3 jest klient MS o adresie 192.168.30.2 i wewnętrznym IP 192.168.31.3

* MS - router-serwer w mieszkaniu 1, MK2 - router w mieszkaniu 2, MK3 - router w mieszkaniu 3
* Konfiguracje urządzeń są publikowane w spoilerze na końcu artykułu.

I tak pingi między węzłami sieci 192.168.31.0/24 idą, czas przejść do konfiguracji tunelu GRE. Wcześniej, aby nie stracić dostępu do routerów, warto założyć tunele SSH, aby przekierować port 22 na VPS, tak aby np. router z mieszkania 10022 był dostępny na porcie 2 VPS, a router z mieszkania 11122 będzie dostępny na porcie 3 routera VPS z mieszkania XNUMX. Najlepiej skonfigurować przekierowanie z tym samym sshtunnel, ponieważ przywróci on tunel w przypadku awarii.

Tunel jest skonfigurowany, możesz połączyć się z SSH przez przekierowany port:

ssh root@МОЙ_VPS -p 10022

Następnie wyłącz OpenVPN:

/etc/init.d/openvpn stop

Teraz skonfigurujmy tunel GRE na routerze z mieszkania 2:

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

I dodaj utworzony interfejs do mostka:

brctl addif br-lan grelan0

Wykonajmy podobną procedurę na routerze serwera:

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

A także dodaj utworzony interfejs do mostka:

brctl addif br-lan grelan0

od tego momentu pingi zaczynają pomyślnie przechodzić do nowej sieci a ja z satysfakcją idę napić się kawy. Następnie, aby zobaczyć, jak działa sieć po drugiej stronie przewodu, próbuję połączyć się przez SSH z jednym z komputerów w mieszkaniu 2, ale klient ssh zawiesza się bez pytania o hasło. Próbuję połączyć się z tym komputerem przez telnet na porcie 22 i widzę linię, z której można zrozumieć, że połączenie jest nawiązywane, serwer SSH odpowiada, ale z jakiegoś powodu nie oferuje mi wejścia.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Próbuję połączyć się z nim przez VNC i widzę czarny ekran. Przekonuję się, że sprawa leży po stronie zdalnego komputera, bo z tego mieszkania mogę bez problemu połączyć się z routerem za pomocą adresu wewnętrznego. Decyduję się jednak na połączenie SSH z tym komputerem przez router i ku mojemu zdziwieniu stwierdzam, że połączenie się powiodło, a komputer zdalny działa dobrze, ale nie łączy się też z moim komputerem.

Wyciągam urządzenie grelan0 z mostka i uruchamiam OpenVPN na routerze w mieszkaniu 2 i upewniam się, że sieć znowu działa poprawnie i połączenia nie są zrywane. Szukając natknąłem się na fora, na których ludzie narzekają na te same problemy, gdzie radzi się im podnieść MTU. Nie prędzej powiedziane niż zrobione. Jednak dopóki MTU nie zostało ustawione na wystarczająco dużą wartość 7000 dla urządzeń gretap, obserwowano zrywane połączenia TCP lub wolne transmisje. Ze względu na wysokie MTU dla gretap, MTU dla połączeń WireGuard pierwszego i drugiego poziomu zostały ustawione odpowiednio na 8000 i 7500.

Zrobiłem podobną konfigurację na routerze z mieszkania 3, z tą różnicą, że do routera serwera dodano drugi interfejs gretap o nazwie grelan1, który również został dodany do mostka br-lan.

Wszystko działa. Teraz możesz umieścić zespół gretap w trybie automatycznego ładowania. Dla tego:

Umieściłem te linie w /etc/rc.local na routerze w mieszkaniu 2:

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

Dodano to do /etc/rc.local na routerze w mieszkaniu 3:

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

A na routerze serwera:

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

Po ponownym uruchomieniu routerów klienckich stwierdziłem, że z jakiegoś powodu nie łączyły się z serwerem. Łącząc się z ich SSH (na szczęście wcześniej skonfigurowałem do tego sshtunnel), odkryto, że WireGuard z jakiegoś powodu tworzy trasę dla punktu końcowego, będąc jednocześnie błędnym. Tak więc dla 192.168.30.2 tablica tras została określona w tablicy tras przez interfejs pppoe-wan, czyli przez Internet, chociaż trasa do niej powinna była zostać skierowana przez interfejs wg0. Po usunięciu tej trasy połączenie zostało przywrócone. Nigdzie nie mogłem znaleźć instrukcji, jak zmusić WireGuard do nie tworzenia tych tras. Co więcej, nawet nie rozumiałem, czy jest to funkcja OpenWRT, czy samego WireGuarda. Nie borykając się z tym problemem przez długi czas, po prostu dodałem do obu routerów w skrypcie zapętlonym przez timer linię, która usunęła tę trasę:

route del 192.168.30.2

Podsumowując

Nie osiągnąłem jeszcze całkowitego odrzucenia OpenVPN, ponieważ czasami potrzebuję połączyć się z nową siecią z laptopa lub telefonu, a skonfigurowanie na nich urządzenia gretap jest generalnie niemożliwe, ale mimo to uzyskałem przewagę w przesyłaniu danych prędkość między mieszkaniami i np. korzystanie z VNC nie jest już uciążliwe. Ping nieznacznie spadł, ale stał się bardziej stabilny:

Podczas korzystania z 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

Podczas korzystania z WireGuarda:

[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

Wpływa na to głównie wysoki ping do VPS, który wynosi około 61.5 ms

Jednak prędkość znacznie wzrosła. Tak więc w mieszkaniu z routerem-serwerem mam łącze internetowe o prędkości 30 Mb / s, aw innych mieszkaniach 5 Mb / s. Jednocześnie, korzystając z OpenVPN, nie udało mi się osiągnąć szybkości przesyłania danych między sieciami większej niż 3,8 Mb/s według iperf, podczas gdy WireGuard „pompował” to do tych samych 5 Mb/s.

Konfiguracja WireGuard na VPS[Interface] Address = 192.168.30.1/24
ListenPort = 51820
PrivateKey = <ЗАКРЫТЫЙ_КЛЮЧ_ДЛЯ_VPS>

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_1_МС>
AllowedIPs = 192.168.30.2/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК2>
AllowedIPs = 192.168.30.3/32

[Peer] PublicKey = <ОТКРЫТЫЙ_КЛЮЧ_VPN_2_МК3>
AllowedIPs = 192.168.30.4/32

Konfiguracja WireGuard na MS (dodana do /etc/config/network)

#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'

Konfiguracja WireGuard na MK2 (dodana do /etc/config/network)

#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'

Konfiguracja WireGuard na MK3 (dodana do /etc/config/network)

#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'

W opisanych konfiguracjach dla VPN drugiego poziomu klientom WireGuard określam port 51821. Teoretycznie nie jest to konieczne, gdyż klient nawiąże połączenie z dowolnego wolnego nieuprzywilejowanego portu, ale zrobiłem to tak, aby wszystkie połączenia przychodzące można odmówić na interfejsach wg0 wszystkich routerów, z wyjątkiem przychodzących połączeń UDP na porcie 51821.

Mam nadzieję, że artykuł przyda się komuś.

PS Ponadto chcę udostępnić mój skrypt, który wysyła mi powiadomienie PUSH na mój telefon w aplikacji WirePusher, gdy w mojej sieci pojawi się nowe urządzenie. Oto link do skryptu: https://github.com/r0ck3r/device_discover.

AKTUALIZACJA: Konfiguracja serwera i klientów OpenVPN

Serwer OpenVPN

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

Klient OpenVPN

client
tls-client
dev tap
proto tcp
remote VPS_IP 1194 # Change to your router's External IP
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

Użyłem easy-rsa do wygenerowania certyfikatów.

Źródło: www.habr.com

Dodaj komentarz