Категория > Новости > Trickster VPN. Разбираемся с WireGuard и делаем свой умный VPN - «Новости»

Trickster VPN. Разбираемся с WireGuard и делаем свой умный VPN - «Новости»


10-09-2022, 00:00. Автор: Наталья
род­ными средс­тва­ми мож­но нас­тро­ить авто­мати­зацию, которая будет запус­кать VPN, ког­да откры­ваешь опре­делен­ные при­ложе­ния (нап­ример, Twitter), а ког­да выходишь из них — вык­лючать обратно. Но это кос­тыль, а хочет­ся все сде­лать кра­сиво, да еще и про­качать навык работы с сетью.

По­это­му мы сей­час поп­робу­ем «вклю­чать чуть‑чуть VPN».



info


При таком исполь­зовании это ско­рее прок­си, а не VPN, но любые методы обхо­да бло­киро­вок теперь называ­ют VPN, так что, сде­лав эту ого­вор­ку, даль­ше рас­сла­бим­ся и будем делать как все.



За­одно чуть улуч­шим качес­тво свя­зи с локаль­ными ресур­сами: необ­ходимость тас­кать тра­фик сна­чала до VPN вне стра­ны, а потом обратно до сер­вера внут­ри нее дра­матич­но ска­зыва­ется если не на ско­рос­ти, то на задер­жке точ­но. Даже на про­вод­ном интерне­те пинг в 4 мс до Яндекса лег­ко прев­раща­ется в 190 мс, а на мобиль­ном интерне­те — из 80 мс в 240 мс. Допол­нитель­ный хоп внут­ри стра­ны чуть ухуд­шит дело, но далеко не так дра­матич­но.


Де­лать все мы будем на осно­ве WireGuard — это отно­ситель­но новая (раз­рабаты­вает­ся с 2016 года, в отли­чие от OpenVPN и IPsec: пер­вый — это двух­тысяч­ные, а вто­рой еще рань­ше) тех­нология VPN. Соз­дал ее, по сути, один человек — zx2c4, которо­го в миру зовут Джей­соном Донен­фель­дом. Плю­сы WG — ско­рость (осо­бен­но для Linux, где он может работать как модуль ядра, начиная с Kernel 5.6, и Windows, где модуль для ядра выпус­тили око­ло недели назад), низ­кие задер­жки, сов­ремен­ная крип­тогра­фия и прос­тая нас­трой­ка и исполь­зование конеч­ным юзе­ром.


Ах да, еще UDP. UDP для тун­нелей — это хорошо, потому что у TCP уже есть механиз­мы, которые поз­воля­ют ему работать на неидеаль­ных соеди­нени­ях, а UDP пред­став­ляет собой имен­но такое соеди­нение. А ког­да ты засовы­ваешь TCP в TCP, то отка­зыва­ешь­ся от боль­шей час­ти этих механиз­мов (инкапсу­лиро­ван­ный TCP-пакет будет гаран­тирован­но дос­тавлен дру­гой сто­роне, хотя про­токол допус­кает недос­тавку), но все еще несешь весь овер­хед вида «хен­дшейк соеди­нения для отправ­ки хен­дшей­ка».


Читайте также - SuperMega Market — агрегатор и сервис поиска товаров в интернет-магазинах и сравнения цен. Наш портал охватывает самые разнообразные категории товаров: одежда, обувь, электроника, компьютеры, бытовая техника, автотовары, оборудование для ремонта и строительства, туристическое снаряжение, детские товары и многое другое, интернет магазин supermega market по доступным ценам.

Не говоря уж о том, что инкапсу­лиро­вать UDP в TCP — ничуть не луч­шая идея, потому что сра­зу рушит все пред­положе­ния вся­ких скай­пов о том, что луч­ше про­пус­тить пару пакетов, чем умень­шить задер­жку: каж­дый UDP-пакет в этом слу­чае будет при­нуди­тель­но пос­лан заново и дос­тавлен кор­рек­тно, не счи­таясь с зат­ратами вре­мени.


Осо­бен­но для оди­ноко­го поль­зовате­ля‑хакера при­ятна работа с шиф­ровани­ем: нет необ­ходимос­ти ни в сер­тифика­тах и удос­товеря­ющих цен­трах, ни в логинах‑паролях, все, что нуж­но, — обме­нять­ся пуб­личны­ми клю­чами с пиром, с которым ты хочешь уста­новить соеди­нение. Для боль­ших ком­паний это, конеч­но, будет ско­рее минусом, как и то, что WG — это толь­ко базовая часть пол­ноцен­ной боль­шой инфраструк­туры VPN. Но имен­но WireGuard исполь­зовали, к при­меру, в Cloudflare для сво­его WARP, прав­да, написав его собс­твен­ную реали­зацию — boringtun.


Еще один минус WG — то, что тра­фик не обфусци­рован и глу­бокая инспек­ция пакетов (DPI) выявит и поз­волит заб­локиро­вать такое соеди­нение (не говоря уж о бло­киров­ке UDP сов­сем, что поч­ти не меша­ет работать с вебом, но гаран­тирован­но лома­ет WireGuard). Для скры­тия тра­фика рекомен­дует­ся исполь­зовать спе­циали­зиро­ван­ное ПО — Cloak, Obfsproxy, Shadowsocks, Stunnel, SoftEther, SSTP или, в кон­це кон­цов, прос­той SSH. Часть из этих инс­тру­мен­тов может работать сов­мес­тно с WG, а часть спо­соб­на его заменять в качес­тве инс­тру­мен­та сте­ганог­рафии: WG изна­чаль­но соз­давал­ся под ско­рость и крип­тогра­фичес­кую защищен­ность.


Ес­ли очень упро­щать, клю­чи работа­ют сле­дующим обра­зом: у нас есть зак­рытый (при­ват­ный) ключ, из которо­го мож­но сге­нери­ровать откры­тый, или пуб­личный. Наобо­рот, из откры­того клю­ча получить зак­рытый мы никак не можем. Затем мы шиф­руем с помощью зак­рытого клю­ча какую‑то стро­ку, а при помощи откры­того рас­шифру­ем ее и тем самым убе­дим­ся, что у собесед­ника точ­но есть зак­рытый ключ, а зна­чит, он тот, за кого себя выда­ет. Таким обра­зом, мы можем без проб­лем переда­вать откры­тый ключ — он все­го лишь поз­воля­ет про­верить под­линность авто­ра, но не прит­ворить­ся им.


Это как в SSH — пуб­личный ключ лежит на сер­вере, где его потеря — неболь­шая беда: все, что смо­жет сде­лать с ним зло­умыш­ленник, — это положить его на свой сер­вер, что­бы ты мог под­клю­чить­ся к нему с помощью зак­рытого клю­ча.


Так вот, в WG на пер­вом эта­пе под­клю­чения каж­дая сто­рона с помощью зашиф­рован­ного при­ват­ным клю­чом сооб­щения доказы­вает собесед­нику, что она имен­но она: это про­веря­ется пуб­личным клю­чом.


Вто­рой этап — соз­дание с помощью этих клю­чей и матана сим­метрич­ных клю­чей для шиф­рования самого тра­фика. Бла­года­ря тому что рас­шифро­вать зашиф­рован­ное пуб­личным клю­чом нель­зя без при­ват­ного, мы смо­жем соз­дать ключ для сим­метрич­ного шиф­рования и отпра­вить его по защищен­ному каналу. Этот шаг необ­ходим потому, что сим­метрич­ное шиф­рование гораз­до менее ресур­соем­кая опе­рация, а минус у нее толь­ко один: необ­ходимо син­хро­низи­ровать ключ меж­ду сто­рона­ми, при том что перех­ват клю­ча треть­ей сто­роной ведет к воз­можнос­ти рас­шифров­ки тра­фика.


Но эта проб­лема реша­ется с помощью асим­метрич­ной схе­мы. Это называ­ется про­токол Диф­фи — Хел­лма­на — спо­соб защищен­ного получе­ния обще­го сек­ретно­го клю­ча. В WG исполь­зует­ся ECDH — вари­ация Диф­фи — Хел­лма­на на эллипти­чес­ких кри­вых. Пер­вые два эта­па в тер­минах WG называ­ются рукопо­жати­ем или хен­дшей­ком.
За­тем сим­метрич­ные клю­чи исполь­зуют­ся для шиф­рования тра­фика. Раз в две минуты про­исхо­дит новое рукопо­жатие и сес­сион­ные клю­чи меня­ются.


Ра­зуме­ется, в реаль­нос­ти все нем­ного слож­нее: нап­ример, отправ­ляют­ся не сами клю­чи, а сге­нери­рован­ные на их осно­ве эфе­мер­ные клю­чи, которые уда­ляют­ся сра­зу пос­ле опе­рации. Заин­тересо­вав­шихся под­робнос­тями отправ­ляю к крат­кому опи­санию на сай­те WireGuard.


Мы же перей­дем к более прак­тичес­ким дей­стви­ям.


 

Шаг 1. Создаем и настраиваем два сервера


Один сер­вер будет внут­ри стра­ны — через него тра­фик пой­дет на локаль­ные ресур­сы, а вто­рой — за гра­ницей. Даль­ше я их буду называть local и external.


Иде­аль­но, если local будет в тво­ей домаш­ней сети, потому что при этом тра­фик на внеш­ние ресур­сы не отли­чает­ся от тво­его домаш­него тра­фика. Но для это­го нужен какой‑то хост дома, белый IP и воз­можность проб­росить порт. У меня это вир­туал­ка на домаш­нем сер­вере, но, навер­ное, подой­дет и Raspberry Pi или ана­логич­ный одноплат­ник.



info


Ва­риант с одноплат­ником я не тес­тировал и не уве­рен, что он сра­бота­ет. Raspberry Pi при­дет­ся мар­шру­тизи­ровать весь тра­фик с устрой­ств и дер­жать в памяти око­ло 11 тысяч мар­шру­тов; ресур­сов на это может не хва­тить.



Ес­ли дома хос­та нет, мож­но взять любой сер­вер у хос­тера VDS. Увы, некото­рые сай­ты бло­киру­ют под­сети хос­теров, опа­саясь ботов, так что это менее пред­почти­тель­ный вари­ант.


А вот внеш­нюю машину мож­но арен­довать и у хос­тера. К при­меру, у RU VDS и VDSina есть зарубеж­ные пло­щад­ки. А мож­но выб­рать инос­тран­ного хос­тера, если най­дешь спо­соб опла­чивать его услу­ги. Нап­ример, я исполь­зую исланд­ский 1984.hosting, соз­данный спе­циаль­но для парано­иков.


Счи­таем, что на обо­их сер­верах у нас Debian 11.


Ста­вим нуж­ные нам пакеты:


apt update && apt install -ywireguard iptables ipcalc qrencode curl jq traceroute dnsutils ufw

Вклю­чаем перенап­равле­ние тра­фика: в этом слу­чае сер­вер, получив пакет, который не пред­назна­чает­ся ни одно­му из его IP-адре­сов, не отбро­сит его, а попыта­ется перенап­равить в соот­ветс­твии со сво­ими мар­шру­тами.


echo "net.ipv4.ip_forward=1" > >/etc/sysctl.conf
echo "net.ipv4.conf.all.forwarding=1" > >/etc/sysctl.conf
sysctl -p/etc/sysctl.conf

Оп­циональ­но (но очень удоб­но) сра­зу поменять hostname обо­их сер­веров, что­бы не запутать­ся, где какая кон­соль:


hostnamectl set-hostname trickster-internal
hostnamectl set-hostname trickster-external
 

Шаг 2. Настраиваем WireGuard для связи двух серверов


Для начала генери­руем клю­чи. Запус­каем два раза wg genkey и получа­ем два при­ват­ных клю­ча:


root@trikster-internal:~# wg genkey
kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8=
root@trikster-internal:~# wg genkey
6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28=

Ути­лита wg genkey не дела­ет ничего вол­шебно­го, это прос­то ана­лог чего‑то в таком духе:


Толь­ко навер­няка более слу­чай­ное: мы прос­то генери­руем 32 бай­та слу­чай­ных зна­чений и пред­став­ляем их в виде Base64.


Соз­даем два кон­фига. Один на internal:


/etc/wireguard/wg-internal.conf
Address = 10.20.30.1/32ListenPort = 17968PrivateKey = kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8=PostUp = iptables -t nat -A POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADEPostUp = ip rule add from `ip addr show $(ip route awk '/default/ { print $5 }') grep "inet" grep -v "inet6" head -n awk '/inet/ {print $2}awk -F/ '{print $1}'` table mainPostDown = iptables -t nat -D POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADEPostDown = ip rule del from `ip addr show $(ip route awk '/default/ { print $5 }') grep "inet" grep -v "inet6" head -n awk '/inet/ {print $2}awk -F/ '{print $1}'` table main

Вто­рой на external:


/etc/wireguard/wg-external.conf
Address=10.20.30.2/32PrivateKey=6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28=PostUp = iptables -t nat -A POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADEPostDown = iptables -t nat -D POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADE

Сек­ция [Interface] — это нас­трой­ки кон­крет­ного сетево­го интерфей­са WireGuard, того, что будет виден в ip a. Наз­вание интерфей­са берет­ся из наз­вания текуще­го фай­ла кон­фигура­ции. У одно­го интерфей­са всег­да одна клю­чевая пара: у пиров это­го интерфей­са оди­нако­вый пуб­личный ключ.


Но ник­то не меша­ет, если хочет­ся, сде­лать для каж­дого пира отдель­ный кон­фиг и отдель­ный интерфейс (прав­да, на сот­нях кли­ентов это будет неудоб­но).


Уп­равля­ются интерфей­сы обыч­но при помощи ути­литы wg-quick:
wg-quick down wg-external и wg-quick up wg-external



info


Ути­лита wg-quick — это на самом деле 400 строк на баше, которые авто­мати­зиру­ют час­то исполь­зуемые вещи, нап­ример уста­нов­ку мар­шру­тов. Наличие тун­неля само по себе не дает ничего, кро­ме защищен­ной «тру­бы», за которой находит­ся дру­гой пир. Что­бы твой зап­рос в бра­узе­ре попал в интерфейс, сис­теме надо явно ска­зать: «Мар­шру­тизи­руй, пожалуй­ста, пакеты с таким‑то адре­сом наз­начения вот в этот сетевой интерфейс».


Имен­но этим занима­ется wg-quick. Ну еще и нас­трой­кой адре­сов DNS, ука­зан­ных в кон­фиге, уста­нов­кой MTU и еще парой вещей. Но ничего слож­ного в этом нет, дос­таточ­но сде­лать cat /usr/bin/wg-quick, что­бы пос­мотреть на эту логику, и, если надо, пов­торить то же самое руками.





  • Interface-Address — это IP текуще­го пира. Вся адре­сация в WG ста­тичес­кая. С одной сто­роны, это упро­щает нас­трой­ку и бутс­трап, с дру­гой сто­роны, усложня­ет работу, если у тебя очень мно­го кли­ентов.


  • ListenPort — это UDP-порт для под­клю­чения извне. Если не ука­зать, будет прос­лушивать 51820.


  • Interface-PostUp и Interface-PostDown — скрип­ты, которые выпол­няют­ся пос­ле под­нятия и пос­ле оста­нов­ки интерфей­са. Есть еще PreUP и PreDown.


Кро­ме пуб­личных и при­ват­ных клю­чей, есть еще опция PresharedKey, которая обес­печива­ет допол­нитель­ное шиф­рование сим­метрич­ным шиф­ром. Ключ мож­но сге­нери­ровать, нап­ример, коман­дой wg genpsk и добавить в опцию PresharedKey в сек­циях Peer на обо­их пирах. Если не исполь­зовать эту опцию, наг­рузка по шиф­рованию и рас­шифров­ке не вырас­тет: ког­да ключ не ука­зан, исполь­зует­ся нулевое зна­чение клю­ча.


А что­бы по‑нас­тояще­му обес­печить пост­кван­товую безопас­ность (невоз­можность рас­шифров­ки дан­ных кван­товыми компь­юте­рами), раз­работ­чики рекомен­дуют допол­нитель­ный внеш­ний кван­тово‑устой­чивый механизм хен­дшей­ка, нап­ример SIDH, который Microsoft пиарит имен­но в таком кон­тек­сте. Соз­данный им общий ключ мож­но исполь­зовать в качес­тве PresharedKey.


Зак­линания в PostUp дос­таточ­но прос­ты. Вот коман­да для под­ста­нов­ки име­ни сетево­го интерфей­са, куда по умол­чанию выпол­няет­ся мар­шру­тиза­ция:


Как пра­вило, это интерфейс, обра­щен­ный к про­вай­деру или роуте­ру.


Та­ким обра­зом, страш­ная коман­да прев­раща­ется в такую:


iptables -t nat -APOSTROUTING -oeth0 -jMASQUERADE

Здесь про­исхо­дит вклю­чение NAT в режиме мас­карада: сер­вер будет отправ­лять при­шед­шие ему пакеты во внеш­нюю сеть, под­меняя адрес отпра­вите­ля сво­им, что­бы отве­ты на эти пакеты тоже при­ходи­ли ему, а не исходно­му отпра­вите­лю.


Вто­рая коман­да уже нем­ного слож­нее, но она под­став­ляет IP-адрес дефол­тно­го мар­шру­та.


Сна­чала мы получа­ем, как и выше, сетевой интерфейс мар­шру­та по умол­чанию:


enp1s0

По­том дан­ные о сос­тоянии это­го интерфей­са:


inet 192.168.88.70/24 brd 192.168.88.255 scope global dynamic enp1s0

И даль­ше вытас­кива­ем отту­да адрес, в дан­ном слу­чае 192.168.88.70.
Ко­ман­да ста­новит­ся такой:


ip rule add from 95.93.219.123 table mainё

Это необ­ходимо для сер­вера internal, потому что ина­че при акти­вации мар­шру­та 0.0.0.0/0 он начина­ет пересы­лать отве­ты на пакеты, при­ходя­щие ему на внеш­ние адре­са через тун­нель WG. Сер­вер на том кон­це, конеч­но, пересы­лает их по наз­начению, но тут уже не готов отпра­витель пакета: он при­сыла­ет что‑то на внеш­ний адрес сер­вера internal, а ответ ему при­ходит с external.


Ес­тес­твен­но, при вклю­чен­ном rp_filter пакет отбра­сыва­ется. В этом слу­чае сер­вер перес­тает быть дос­тупным, нап­ример по SSH сна­ружи. К нему при­дет­ся кон­нектить­ся толь­ко по внут­ренне­му IP WireGuard. Отклю­чать rp_filter — это стре­лять из пуш­ки по воробь­ям, а вот допол­нитель­ное пра­вило исправ­ляет ситу­ацию.



info


Я намерен­но не при­вожу готовые кон­фиги, потому что хочу показать механизм соз­дания кон­фигов в руч­ном режиме. В свое вре­мя я генери­ровал кон­фиги ути­лита­ми типа easy-wg-quick или веб‑сер­висами, которые спра­шива­ют тебя о наз­вании кли­ента и кра­сиво показы­вают QR-код. Это отнюдь не спо­собс­тву­ет понима­нию того, как работа­ет WG на самом деле, и может выз­вать проб­лемы.



Те­перь в оба кон­фига надо добавить сек­цию Peer, что­бы свя­зать сер­веры друг с дру­гом.


Ге­нери­руем из при­ват­ного клю­ча пуб­личный (вот в wg pubkey как раз и про­исхо­дит крип­томагия):


root@:~# echo "kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8="wg pubkey
MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=

Это пуб­личный ключ сер­вера internal, его мы помеща­ем в сек­цию Peer на external:


/etc/wireguard/wg-external.conf
[Peer]
PublicKey=MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=
AllowedIPs=10.20.30.0/24
Endpoint=195.2.79.13:17968
PersistentKeepalive=25

Там же, в Endpoint ука­зыва­ем адрес сер­вера internal и порт, который мы задали в ListenPort.


С AllowedIPs при исполь­зовании wg-quick воз­ника­ет неболь­шая путани­ца. Это имен­но спи­сок IP-адре­сов, с которых мы раз­реша­ем при­нимать пакеты из тун­неля. Если при­летит что‑то с дру­гим src, оно будет отбро­шено.


Wg-quick разум­но счи­тает, что, если есть какие‑то устрой­ства, которые могут пос­лать пакет, пакеты к этим устрой­ствам надо мар­шру­тизи­ровать туда же, и соз­дает мар­шру­ты на эти адре­са, ука­зыва­ющие на тун­нель пира.


В этих при­мерах AllowedIPs мож­но читать как «адре­са, тра­фик на которые будет мар­шру­тизи­ровать­ся в тун­нель это­го пира и с которых пир смо­жет отпра­вить что‑то в тун­нель». То есть пункт AllowedIPs = 10.20.30.3/32 озна­чает бук­валь­но «толь­ко зап­росы на 10.20.30.3 (адрес пира WG) отправ­лять в тун­нель» — дать дос­туп толь­ко до машины это­го кли­ента.
Пункт AllowedIPs = 192.168.88.0/24 озна­чает, что при зап­росе адре­са из этой под­сети зап­рос уйдет в тун­нель кли­ента, и если у него вклю­чен фор­вардинг и ему дос­тупна эта под­сеть, то к ней мож­но будет получить дос­туп.


AllowedIPs = 0.0.0.0/0 озна­чает, что в тун­нель надо мар­шру­тизи­ровать вооб­ще весь тра­фик. Прав­да, это не отно­сит­ся к тра­фику, нап­ример, локаль­ной сети: при­ори­тет у мар­шру­та, который соз­дает­ся из мас­ки под­сети и адре­са шлю­за, выше, чем у 0.0.0.0/0. Так­же мар­шрут 0.0.0.0/0 перебь­ют мар­шру­ты дру­гих пиров, если они будут в кон­фиге.


В дан­ном слу­чае AllowedIPs=10.20.30.0/24 озна­чает, что тра­фик с external в под­сеть 10.20.30.0–10.20.30.255 будет ухо­дить в тун­нель к internal. В прин­ципе, осо­бой нуж­ды в этом нет, external у нас исклю­читель­но выход­ная нода. Но вдруг мы как‑нибудь захотим зай­ти отту­да по SSH на какую‑нибудь дру­гую машину.


Пов­торя­ем генера­цию пуб­лично­го клю­ча с external:


root@:~# echo "6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28="wg pubkey
FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=

Мы получа­ем пуб­личный ключ сер­вера external и помеща­ем его в сек­цию Peer сер­вера internal.


/etc/wireguard/wg-internal.conf
[Peer] #external node
PublicKey = FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=
AllowedIPs = 10.20.30.2/32, 0.0.0.0/0

AllowedIPs тут 10.20.30.2/32, 0.0.0.0/0. Этим мы ука­зыва­ем, что за тун­нелем находит­ся кон­крет­ный IP 10.20.30.2, и, помимо это­го, проб­расыва­ем весь тра­фик, не свя­зан­ный дру­гими мар­шру­тами, в этот тун­нель: external у нас основная выход­ная нода VPN.


По­это­му по умол­чанию весь тра­фик будет нап­равлять­ся через нее, так как зарубеж­ных мар­шру­тов боль­ше, чем рос­сий­ских, и логич­нее филь­тро­вать имен­но рос­сий­ские, а зарубеж­ный тра­фик пус­тить по умол­чанию через ноду в дру­гой стра­не.


Итак, два кон­фига.


/etc/wireguard/wg-internal.conf
Address = 10.20.30.1/32ListenPort = 17968PrivateKey = kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8=PostUp = iptables -t nat -A POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADEPostUp = ip rule add from `ip addr show $(ip route awk '/default/ { print $5 }') grep "inet" grep -v "inet6" head -n awk '/inet/ {print $2}awk -F/ '{print $1}'` table mainPostDown = iptables -t nat -D POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADEPostDown = ip rule del from `ip addr show $(ip route awk '/default/ { print $5 }') grep "inet" grep -v "inet6" head -n awk '/inet/ {print $2}awk -F/ '{print $1}'` table main#external node[Peer]PublicKey = FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=AllowedIPs = 10.20.30.2/32, 0.0.0.0/0
/etc/wireguard/wg-external.conf
Address = 10.20.30.2/32PrivateKey = 6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28=PostUp = iptables -t nat -A POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADEPostDown = iptables -t nat -D POSTROUTING -o `ip route awk '/default/ {print $5; exit}'` -j MASQUERADE#internal node[Peer]PublicKey = MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=AllowedIPs = 10.20.30.0/24Endpoint = 195.2.79.13:17968PersistentKeepalive = 25

Те­перь мож­но под­нять тун­нели на обо­их сер­верах:


root@trikster-external:~# wg-quick down wg-external ;wg-quick up wg-external
root@trikster-internal:~# wg-quick down wg-internal ;wg-quick up wg-internal

Про­веря­ем, что тун­нели активны, коман­дой wg:


root@trikster-internal:~# wg
...
peer:FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=
endpoint:51.159.187.77:36276
allowed ips:10.20.30.2/32,0.0.0.0/0
latest handshake:13 seconds ago
transfer:180 received,92 sent
root@trikster-external:~# wg
...
peer:MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=
endpoint:195.2.79.13:17968
allowed ips:10.20.30.0/24
latest handshake:10 seconds ago
transfer:92 received,180 sent
persistent keepalive:every 25 seconds

Ес­ли видим «latest handshake: ... seconds ago» и бай­ты и в received и в sent, зна­чит, все хорошо. Если бай­ты толь­ко в send, без хен­дшей­ка и получен­ных дан­ных, зна­чит, где‑то в кон­фиге ошиб­ка или сер­веры недос­тупны друг для дру­га.


Ес­ли что‑то пош­ло не так и отва­лил­ся SSH, то дос­таточ­но перезаг­рузить сер­вер — активные тун­нели сбро­сят­ся.


Ес­ли же все хорошо и дос­туп к сер­верам сох­ранил­ся, ста­вим тун­нели в авто­запуск:


root@trikster-internal:~# systemctl enable wg-quick@wg-internal.service
root@trikster-external:~# systemctl enable wg-quick@wg-external.service

Поп­робу­ем пос­мотреть мар­шрут (рекомен­дую замеча­тель­ную ути­литу mytraceroutemtr) без тун­неля:


root@trikster-internal:~# wg-quick down wg-internal && sleep 10 && mtr -rgoogle.com
HOST:trikster-internal.local Loss% Snt Last Avg Best Wrst StDev
1.|-- host-89-22-232-243.hosted 0.0% 10 0.5.0.49.15.6
2.|-- 172.31.0.0.0% 10 0.19.0.122.42.6
3.|-- 109.239.138.90 0.0% 10 1.1.1.3.0.6
4.|-- 91.108.51.0.0% 10 11.11.11.11.0.1
5.|-- 178.18.227.12.ix.dataix.0.0% 10 11.17.11.77.20.8

И с тун­нелем:


root@trikster-internal:~# wg-quick up wg-internal && sleep 10 &&mtr -rgoogle.com
HOST:trikster-internal.local Loss% Snt Last Avg Best Wrst StDev
1.|-- 10.20.30.0.0% 10 51.51.51.51.0.1
2.|-- 10.200.100.0.0% 10 51.51.51.51.0.1
3.|-- 10.197.37.65 0.0% 10 52.52.52.52.0.2
4.|-- 10.197.0.41 0.0% 10 52.52.52.52.0.1
5.|-- 10.197.0.44 0.0% 10 52.52.51.52.0.1

Все хорошо, тра­фик идет через внеш­ний сер­вер — сна­чала на 10.20.30.2, который у нас наз­начен выход­ной нодой, а потом через его мар­шру­тиза­торы.


У нас получи­лась при­мер­но сле­дующая схе­ма.


 

Шаг 3. Добавляем конфиг клиента


Соз­даем кон­фиг кли­ента, конеч­ного устрой­ства — поль­зовате­ля VPN. За осно­ву берем wg-external.conf, потому что это точ­но такой же кли­ент, который под­клю­чает­ся к internal: раз­ница толь­ко в том, что external будет получать пакеты, а наш кли­ент — отправ­лять.



Перейти обратно к новости