Пераход з OpenVPN на WireGuard для аб'яднання сетак у адну сетку L2

Пераход з OpenVPN на WireGuard для аб'яднання сетак у адну сетку L2

Жадаў бы падзяліцца досведам аб'яднання сетак у трох геаграфічна выдаленых кватэрах, у кожнай з якіх у якасці шлюза выкарыстоўваюцца роўтэры з OpenWRT, у адну агульную сетку. Пры выбары спосабу аб'яднання сетак паміж L3 з маршрутызацыяй падсетак і L2 з брыджынгам, калі ўсе вузлы сеткі будуць знаходзіцца ў адной падсеткі, было аддадзена перавага другому спосабу, больш складанаму ў наладзе, але які дае вялікія магчымасці, бо ў стваранай сетцы планавалася празрыстае выкарыстанне тэхналогій. Wake-on-Lan і DLNA.

Частка 1: Перадгісторыя

У якасці пратаколу для рэалізацыі гэтай задачы першапачаткова быў абраны OpenVPN, бо, па-першае, ён можа ствараць прыладу tap, якое без праблем дадаецца ў мост, а па-другое, OpenVPN падтрымлівае працу па пратаколе TCP, што было таксама немалаважна, бо ні ў адной з кватэр не мелася вылучанага IP-адрасы, а выкарыстоўваць STUN мне не атрымалася, бо мой правайдэр чамусьці блакуе ўваходныя падлучэнні па пратаколе UDP са сваіх сетак, у то час як пратакол TCP дазваляў мне пракінуць порт VPN-сервера на арандуемы VPS пры дапамозе SSH. Так, такі падыход дае вялікую нагрузку, бо дадзеныя шыфруюцца двойчы, але ўводзіць VPS у сваю прыватную сетку я не захацеў, бо заставаўся рызыка атрымання трэцімі асобамі кантролю над ім, такім чынам, мець у хатняй сетцы такая прылада з'яўлялася вельмі непажаданым і было вырашанае заплаціць за бяспеку вялікім аверхадам.

Для пракіду порта на роўтары, на якім планавалася разгарнуць сервер, была скарыстана праграма sshtunnel. Апісваць тонкасці яе канфігурацыі не буду - гэта робіцца досыць лёгка, проста адзначу, што яе задачай быў пракід TCP-порта 1194 з роўтара на VPS. Далей быў наладжаны сервер OpenVPN на прыладзе tap0, якое заводзілася ў мост br-lan. Праверыўшы падлучэнне да толькі што створанага сервера з наўтбука - стала зразумела, што ідэя з пракідам порта сябе апраўдала і мой наўтбук стаў чальцом сеткі роўтара, хоць фізічна ў ёй не знаходзіўся.

Справа заставалася за малым: трэба было размеркаваць IP-адрасы ў розных кватэрах так, каб яны не канфліктавалі і наладзіць маршрутызатары ў якасці OpenVPN-кліентаў.
Былі абраныя такія IP-адрасы маршрутызатараў і дыяпазоны DHCP-сервераў:

  • 192.168.10.1 з дыяпазонам 192.168.10.2 - 192.168.10.80 для сервера
  • 192.168.10.100 з дыяпазонам 192.168.10.101 - 192.168.10.149 для маршрутызатара ў кватэры №2
  • 192.168.10.150 з дыяпазонам 192.168.10.151 - 192.168.10.199 для маршрутызатара ў кватэры №3

Таксама было неабходна прызначыць менавіта гэтыя адрасы для маршрутызатараў-кліентаў OpenVPN-сервера, шляхам дадання ў яго канфігурацыю радка:

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

і даданнем наступных радкоў у файл /etc/openvpn/ipp.txt:

flat1_id 192.168.10.100
flat2_id 192.168.10.150

дзе flat1_id і flat2_id – гэта імёны прылад, якія паказваюцца пры стварэнні сертыфікатаў для падлучэння да OpenVPN

Далей на роўтэрах былі настроены OpenVPN-кліенты, прылады tap0 на абодвух былі занесены ў мост br-lan. На гэтым этапе здавалася, што ўсё ў парадку, бо ўсе тры сеткі бачаць адна адну і працуюць як адзінае цэлае. Аднак, высветлілася не вельмі прыемная дэталь: часам прылады маглі атрымаць IP-адрас не ад свайго маршрутызатара, з усімі вынікаючымі наступствамі. Па нейкім чынніку, маршрутызатар у нейкай з кватэр не паспяваў адказаць своечасова на DHCPDISCOVER і прылада атрымлівала не свой адрас. Я зразумеў, што мне трэба адфільтраваць такія запыты ў tap0 на кожным з маршрутызатараў, але, як высветлілася, iptables не можа працаваць з прыладай, калі яно з'яўляецца часткай маста і мне на дапамогу павінен прыйсці ebtables. На маю жаль, у маіх прашыўкі яго не аказалася і прыйшлося перазбіраць вобразы для кожнага прылады. Зрабіўшы гэта і дадаўшы такія радкі ў /etc/rc.local кожнага маршрутызатара праблема была вырашана:

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

Такая канфігурацыя праіснавала цягам трох гадоў.

Частка 2: Знаёмства з WireGuard

У апошні час у Інтэрнэце ўсё часцей сталі казаць аб WireGuard, захапляючыся прастатой яго канфігурацыі, высокай хуткасцю перадачы, нізкім пінгам пры супастаўнай бяспецы. Пошук дадатковай інфармацыі аб ім даваў зразумець, што ні праца ў якасці чальца маста, ні праца па пратаколе TCP ім не падтрымліваецца, што наводзіла мяне на думкі аб тым, што альтэрнатыў OpenVPN для мяне па-ранейшаму няма. Так я адкладаў знаёмства з WireGuard.

Некалькі дзён таму па рэсурсах, так ці інакш злучаным з IT, праляцела навіна аб тым, што WireGuard нарэшце будзе ўключаны ў ядро ​​Linux, пачынальна з версіі 5.6. Навінавыя артыкулы, як заўсёды, хвалілі WireGuard. Я зноў пагрузіўся ў пошукі шляхоў замены старога добрага OpenVPN. На гэты раз я напароўся на гэтую артыкул. У ёй гаварылася аб стварэнні Ethernet-тунэля па-над L3 пры дапамозе GRE. Гэты артыкул усяліў у мяне надзею. Заставалася незразумела што рабіць з пратаколам UDP. Пошук прыводзіў мяне да артыкулаў аб выкарыстанні socat у звязку з SSH-тунэлем, для пракіду UDP-порта, аднак, у іх адзначалася, што такі падыход працуе толькі ў рэжыме аднаго злучэння, гэта значыць праца некалькіх VPN-кліентаў апынулася б немагчымай. Мне прыйшла ідэя падняць VPN-сервер на VPS, а для кліентаў наладзіць GRE, але, як аказалася, GRE не падтрымлівае шыфраванне, што прывядзе да таго, што ў выпадку атрымання доступу да сервера трэцімі асобамі, у іх руках аказваецца ўвесь трафік паміж маімі сеткамі. , што мяне не задавальняла ў прынцыпе.

Ізноў было прынята рашэнне ў карысць залішняга шыфравання, шляхам выкарыстання VPN па-над VPN па наступнай схеме:

VPN першага ўзроўню:
VPS з'яўляецца серверам з унутраным адрасам 192.168.30.1
МС з'яўляецца кліентам VPS з унутраным адрасам 192.168.30.2
МК2 з'яўляецца кліентам VPS з унутраным адрасам 192.168.30.3
МК3 з'яўляецца кліентам VPS з унутраным адрасам 192.168.30.4

VPN другога ўзроўню:
МС з'яўляецца серверам са знешнім адрасам 192.168.30.2 і ўнутраным 192.168.31.1
МК2 з'яўляецца кліентам МС з адрасам 192.168.30.2 і мае ўнутраны IP 192.168.31.2
МК3 з'яўляецца кліентам МС з адрасам 192.168.30.2 і мае ўнутраны IP 192.168.31.3

* МС - маршрутызатар-сервер у кватэры 1, МК2 - маршрутызатар у кватэры 2, МК3 - маршрутызатар у кватэры 3
* Канфігурацыі прылад апублікаваны ў спойлеры ў канцы артыкула.

І так, пінгі паміж вузламі сеткі 192.168.31.0/24 ходзяць, час перайсці да наладзе GRE-тунэля. Перад гэтым, каб не губляць доступ да маршрутызатараў, варта наладзіць SSH-тунэлі для пракіду 22 порта на VPS, такім чынам, што, напрыклад, на 10022-м порце VPS будзе даступны маршрутызатар з кватэры 2, а на 11122-порту VPS будзе даступны маршрутызатар з кватэры 3. Наладу пракіду лепш за ўсё выканаць усё тым жа sshtunnel, бо ён адновіць тунэль у выпадку яго падзення.

Тунэль настроены, можна падлучацца да SSH праз пракінуты порт:

ssh root@МОЙ_VPS -p 10022

Далей варта адключыць OpenVPN:

/etc/init.d/openvpn stop

Цяпер наладзім GRE-тунэль на маршрутызатары з кватэры 2:

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

І дадамо створаны інтэрфейс у мост:

brctl addif br-lan grelan0

Аналагічную працэдуру выканаем на маршрутызатары-серверы:

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

І, таксама, дадамо створаны інтэрфейс у мост:

brctl addif br-lan grelan0

пачынаючы з гэтага моманту пінгі пачынаюць паспяхова хадзіць у новую сетку і я, з задавальненнем адпраўляюся піць каву. Затым, каб ацаніць, як працуе сетку на іншым канцы провада, я спрабую падлучыцца па SSH да аднаго з кампутараў у кватэры 2, але ssh-кліент "завісае", не прапаноўваючы ўвесці пароль. Спрабую падлучыцца да гэтага кампутара па telnet на 22 порт і бачу радок, з якога можна зразумець, што злучэнне ўсталёўваецца, SSH-сервер адказвае, проста па нейкай прычыне не прапануе мне ўвайсці.

$ telnet 192.168.10.110 22
SSH-2.0-OpenSSH_8.1

Спрабую падлучыцца да яго ж па VNC і бачу чорны экран. Я пераконваю сябе, што справа ў выдаленым кампутары, бо да маршрутызатара з гэтай кватэры я спакойна магу падлучыцца па ўнутраным адрасе. Аднак, я вырашаю падлучыцца да SSH гэтага кампутара праз маршрутызатар і са здзіўленнем выяўляю, што падлучэнне атрымоўваецца, а выдалены кампутар працуе суцэль штатна, але пры гэтым таксама не можа падлучыцца да майго кампутара.

Я выводжу прыладу grelan0 з маста і запускаю OpenVPN на маршрутызатары ў кватэры 2 і пераконваюся, што сетка ізноў працуе як пакладзена і злучэнні не абрываюцца. Пошукам натыкаюся на форумы, дзе людзі скардзяцца на такія ж праблемы, дзе ім раяць падняць MTU. Сказана - зроблена. Аднак, пакуль MTU не быў усталяваны досыць вялікім – 7000 для прылад gretap, назіраліся альбо абрывы злучэнняў TCP, альбо нізкая хуткасць перадачы. З-за высокага MTU для gretap – MTU для злучэнняў WireGuard першага і другога ўзроўню былі выстаўлены ў 8000 і 7500 адпаведна.

Правёў аналагічную настройку і на маршрутызатары з кватэры 3, з той толькі розніцай, што на маршрутызатары серверы дадаўся другі інтэрфейс gretap з імем grelan1, які таксама быў дададзены ў мост br-lan.

Усё працуе. Цяпер можна змясціць зборку gretap у аўтазагрузку. Для гэтага:

Змясціў гэтыя радкі ў /etc/rc.local на маршрутызатары ў кватэры 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

Дадаў гэта ў /etc/rc.local на маршрутызатары ў кватэры 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

І на маршрутызатары-серверы:

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

Пасля перазагрузкі кліенцкіх роўтэраў я выявіў, што яны па нейкім чынніку не падлучаюцца да сервера. Падлучыўшыся да іх SSH (балазе, я папярэдне наладзіў sshtunnel для гэтага) было выяўлена, што WireGuard навошта-тое стварае маршрут для endpoint, пры гэтым няслушны. Так, для 192.168.30.2 у табліцы маршрутаў быў паказаны маршрут праз інтэрфейс pppoe-wan, гэта значыць праз інтэрнэт, хаця маршрут да яго павінен быў быць накіраваны праз інтэрфейс wg0. Пасля выдалення гэтага маршруту злучэнне аднавілася. Знайсці дзесьці інструкцый аб тым, як прымусіць WireGuard не ствараць гэтых маршрутаў мне не ўдалося. Больш за тое, я нават не зразумеў, асаблівасць гэта OpenWRT, альбо самога WireGuard. Не стаўшы доўга разбірацца з гэтай праблемай, я проста дадаў на абодва роўтара ў скрыпт, зацыклены па таймеры, радок які выдаляў гэты маршрут:

route del 192.168.30.2

Падводзячы вынікі

Поўнай адмовы ад OpenVPN я пакуль не дамогся, бо мне трэба часам падлучацца да новай сеткі з наўтбука, альбо тэлефона, а налада gretap прылады на іх у агульным выпадку немагчымая, але, нягледзячы на ​​гэта, я атрымаў перавагу ў хуткасці перадачы дадзеных паміж кватэрамі і, напрыклад, выкарыстанне VNC зараз не дастаўляе нязручнасцяў. Пінг паменшыўся нязначна, але стаў больш стабільным:

Пры выкарыстанні 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

Пры выкарыстанні 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

На яго ў большай ступені ўплывае высокі пінг да VPS, які складае прыкладна 61.5/XNUMX мс.

Аднак хуткасць павялічылася значна. Так, у кватэры з маршрутызатарам-серверам я маю хуткасць падлучэння да Інтэрнэту 30 мбіт/сек, а ў астатніх кватэрах па 5 мбіт/сек. Пры гэтым, падчас выкарыстання OpenVPN мне не ўдавалася дасягнуць хуткасці перадачы дадзеных паміж сеткамі больш за 3,8 мбіт/сек па сведчаннях iperf, у той час як WireGuard "прапампаваў" яе да тых жа 5 мбіт/сек.

Канфігурацыя WireGuard на 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

Канфігурацыя WireGuard на МС (дадаецца ў /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'

Канфігурацыя WireGuard на МК2 (дадаецца ў /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'

Канфігурацыя WireGuard на МК3 (дадаецца ў /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'

У апісаных канфігурацыях для VPN другога ўзроўня я паказваю кліентам WireGuard порт 51821. Па ідэі гэта не трэба, бо кліент усталюе злучэнне з любога вольнага непрывілеяванага порта, але я зрабіў так, каб можна было забараніць усе ўваходныя злучэнні на інтэрфейсах wg0 усіх маршрутызатараў, акрамя уваходных UDP-злучэнняў на порт 51821.

Спадзяюся, што артыкул будзе камусьці карысны.

PS Таксама, хачу падзяліцца сваім скрыптам, які шле мне PUSH-апавяшчэнне на тэлефон у дадатак WirePusher, калі ў маёй сетцы з'яўляецца новая прылада. Вось спасылка на скрыпт: github.com/r0ck3r/device_discover.

UPDATE: Канфігурацыя OpenVPN-сервера і кліентаў

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

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

Для генерацыі сертыфікатаў выкарыстоўваў easy-rsa

Крыніца: habr.com

Дадаць каментар