10.04.2022

Шпаргалка по Wireguard

Возникла необходимость предоставить доступ из интернета устройству за NAT. Самый простой способ - заказать у провайдера выделенный IP адрес. Но это не всегда возможно. Самый простой способ - арендовать дешёвый виртуальный сервер и настроить с ним соединение через VPN. Это позволит направлять запросы из интернета на необходимый узел внутри вашей локальной сети. При этом можно предоставить статический IP адрес даже для ноутбука, который будет доступен извне по одному IP адресу, как бы он не подключился к интернету. Об этом и пойдёт речь в этой заметке.

Что такое VPN

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

Всё очень просто. VPN - это просто виртуальный кабель между двумя машинами. Сервер - это то место, куда вы можете включить свой виртуальный кабель, клиент - это вы с кабелем. При этом, в отличие от реального мира, сервер и клиент могут быть расположены на разных концах света. Всё, что вам нужно, чтобы клиент имел возможность соединиться с сервером.

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

Почему Wireguard?

Этот вопрос бы у вас не возник, если вы пробовали настроить, например, OpenVPN. Вереница параметров конфигурации клиента и сервера, создание ключей и прочее. Настройки Wireguard намного проще. Он использует современную криптографию и имеет высокую производительность.

Установка необходимых компонентов

Для дальнейшей настройки необходим пакет wireguard-tools. Он доступен в репозиториях Ubuntu 20.04 LTS и Fedora 35 под этим именем. В других дистрибутивах названием может отличаться. Пакет включает в себя команды wg и wg-quick, которые нам понадобятся.

Создание ключей

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

Сформировать необходимую пару ключей, согласно документации, можно с помощью команды

wg genkey | tee private.key | wg pubkey > public.key

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

wg genkey формирует закрытый ключ, команда tee private.key сохраняет этот ключ в файл private.key и передаёт по цепочке следующей команде - wg pubkey, которая генерирует на базе закрытого ключа открытый ключ. Далее этот открытый ключ сохраняется в файле public.key. После генерации ключей лучше скрыть private.key от чужих глаз установив разрешения 600 на файл

chmod 600 private.key

Каждый из ключей закодирован с помощью base64 кодировки, которая представляет из себя строку из нескольких десятков символов латиницы и цифр. Например:

tDxPhycF7mRLga9e5U/YQgE1FZpZjdKcNkwxIfZikXI=

Настройка сервера и клиента

Wireguard может быть настроен как вручную с использованием команды wg, так и с помощью утилиты wg-quick и написания файлов конфигурации для неё, которые будут содержать все необходимые настройки. В данной заметке рассматривается второй способ с использованием wg-quick. Кроме этого, в современных дистрибутивах wq-quick может быть легко запущена автоматически с нужной конфигурацией с помощью systemd или скриптов для системы инициализации вашего дистрибутива.

Настройки wg-quick в Ubuntu и Fedora находятся в папке /etc/wireguard. В других дистрибутивах путь может отличаться. В этой папке необходимо создать файл с расширением conf и именем сетевого интерфейса для соединения. Пример файла wg0.conf для сервера:

[Interface]
Address = 192.168.0.1/24
PrivateKey = SERVER_PRIVATE_KEY
ListenPort = 51820

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 192.168.0.2

В данной конфигурации создаётся виртуальная сеть с адресацией 192.168.0.0/24, адрес сервера в этой сети 192.168.0.1. Параметр ListenPort указывает на то, что это сервер и он будет прослушивать порт 51820 на сетевых интерфейсах для входящих подключений. Сервер будет использовать закрытый ключ SERVER_PRIVATE_KEY, который в реальном файле конфигурации необходимо заменить на соответствующую строку с закрытым ключом сервера.

Секция [Peer] описывает клиента и может быть использована несколько раз для разных клиентов. В секции указан публичных ключ клиента (CLIENT_PUBLIC_KEY) и адреса узлов, которые могут присылать пакеты через соединение (AllowedIPs), в данном случае, это адрес удалённой машины. Вместо CLIENT_PUBLIC_KEY укажите строку с публичным ключом клиента.

Пример файла конфигурации wg0-client.conf для клиента:

[Interface]
Address = 192.168.0.2
PrivateKey = CLIENT_PRIVATE_KEY

[Peer]
PublicKey = SERVER_PUBLIC_KEY
AllowedIPs = 192.168.0.0/24
Endpoint = SERVER_NAME:51820
PersistentKeepalive = 20

Клиентская конфигурация незначительно отличается от серверной. В секции [Interface] указан IP адрес или несколько адресов клиента, в том числе IPv6, в виртуальной сети и закрытый ключ клиента (CLIENT_PRIVATE_KEY). Секция [Peer] содержит публичный ключ сервера (SERVER_PUBLIC_KEY). В AllowedIPs указываются диапазоны сетей, которые будут маршрутизироваться через данное соединение. В данном случае указана сеть, которая формируется сервером Wireguard - 192.168.0.0/24. Endpoint указывает на адрес (SERVER_NAME) и порт сервера. Параметр PersistentKeepalive необходим для стабильного соединения, если вы находитесь за брандмауэром или NAT. Клиент будет периодически отправлять пакет на сервер, что обеспечит обновление данных об активных соединениях. Вместо значений CLIENT_PRIVATE_KEY, SERVER_PUBLIC_KEY и SERVER_NAME необходимо указать соответствующие строковые значения.

Проверяем подключение

Протестировать соединение можно с помощью утилиты wg-quick, например:

# wg-quick up wg0-client
[#] ip link add wg0-client type wireguard
[#] wg setconf wg0-client /dev/fd/63
[#] ip -4 address add 192.168.0.2 dev wg0-client
[#] ip link set mtu 1420 up dev wg0-client
[#] ip -4 route add 192.168.0.0/24 dev wg0-client

Из текста сообщений видно, что адрес из значения Address был присвоен интерфейсу туннеля, а диапазон AllowedIPs был использован для создания нового маршрута.

Обеспечить автоматический запуск сервера и/или клиента можно с помощью команды:

systemctl enable --now wg-quick@wg0

При этом wg0 - это имя соединения: wg0 - сервер, wg0-client - клиент. Ключ --now позволит сразу запустит службу после её активации.

При тестировании Wireguard через соединение IPv6 столкнулся с проблемой, что соединение устанавливается, адреса становятся доступными, однако обмена информацией нет. Вся проблема оказалась в блокировке входящих пакетов UDP со стороны провайдера. Если у вас что-то не работает, убедитесь, что UDP пакеты успешно доставляются в обе стороны.

Превращаем сервер в шлюз

По моему мнению, наиболее предпочтительным вариантом будет использование Firewalld. Если вы не желаете его устанавливать, то можете воспользоваться iptables, для чего необходимо в секцию [Interface] сервера добавить следующие параметры:

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE

Настройка Firewalld

Для тех, кто решился воспользоваться Firewalld. Сначала его необходимо установить. В некоторых системах, например, в Fedora, он уже установлен по умолчанию. В Ubuntu 20.04 LTS и 22.04 LTS может быть установлен из репозитория universe с помощью команды

sudo apt install firewalld

Как показала практика, настройки по умолчанию не блокируют порт 22, поэтому даже если Firewalld устанавливается на удалённую машину, доступ к ней вы не потеряете. Кроме этого, можно не активировать сервис firewalld, а только запустить его

sudo systemctl start firewalld

В случае проблем вы можете просто перезагрузить ваш сервер и он запустится без firewalld. Когда вы будете уверены, что всё работает как надо, можете включить сервис:

sudo systemctl enable firewalld

После этого, при следующей перезагрузке, он будет запущен автоматически.

Чтобы включить NAT, необходимо на сетевом интерфейсе, который смотрит в интернет, включить режим masquerade. Это можно сделать вручную выполнив команду

firewall-cmd --permanent --zone=ZONE --add-masquerade

где ZONE - это имя зоны, в которой находится внешний интерфейс. Однако делать этого не обязательно, потому что firewalld имеет типовые настройки для часто встречающихся вариантов. Например, зона external соответствует нашим требованиям. Просто необходимо добавить наш сетевой интерфейс в эту зону и разрешить из неё доступ к Wireguard

firewall-cmd --permanent --zone=external --add-interface ens3
firewall-cmd --permanent --zone=external --add-service wireguard

Если вы используете Firewalld до версии 1.0 или нестандартный номер порта, например, 35053, то вместо использования имени службы необходимо указать номер порта:

firewall-cmd --permanent --zone=external --add-port 35053/udp

Для VPN сети можно выбрать зону internal

firewall-cmd --permanent --zone=internal --add-interface wg0

Чтобы изменения вступили в силу, выполняем

firewall-cmd --reload

Начиная с Firewalld 1.0 по умолчанию блокируется транзитный трафик между зонами. Необходимо разрешить его с помощью policy object, например, создав правило client-to-inet:

firewall-cmd --permanent --new-policy client-to-inet
firewall-cmd --permanent --policy client-to-inet --set-target ACCEPT
firewall-cmd --permanent --policy client-to-inet --add-ingress-zone internal
firewall-cmd --permanent --policy client-to-inet --add-egress-zone external
firewall-cmd --reload

Теперь все пакеты, которые будут проходить из зоны internal в external будут подвергнуты NAT. При необходимости, на Wireguard клиенте разрешить получение любых пакетов через соединение с помощью параметра AllowedIPs

AllowedIPs = 0.0.0.0/0

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

Ещё немного о Firewalld

Наиболее часто используемую зону можно использовать в качестве зоны по умолчанию, тогда её можно не указывать в командах

firewall-cmd --set-default-zone=external

После запуска Firewalld могут возникнуть проблемы с доступом к другим службам на сервере. Для них необходимо открыть доступ. Наиболее оптимальный путь - разрешить необходимые вам службы. Список служб можно получить с помощью команды

firewall-cmd --get-services

Детальная информация об этих службах содержится в XML файлах в папке /usr/lib/firewalld/services. Разрешите доступ, например, к вашему веб-серверу по HTTP и HTTPS протоколам

firewall-cmd --permanent --zone=external --add-service=http
firewall-cmd --permanent --zone=external --add-service=https

Если подходящих вариантов не нашлось, то можно открыть порт непосредственно по номеру, например, 1080 по протоколу TCP

firewall-cmd --permanent --zone=external --add-port 1080/tcp

Передача настроек на смартфон

Клиент Wireguard для смартфона умеет считывать qr-код с конфигурацией. Чтобы сгенерировать код не нужен даже графический режим. Просто создайте файл конфигурации для вашего клиента и отобразите его в виде QR-кода в консоли с помощью команды qrencode, которая в Ubuntu и Fedora устанавливается с помощью пакетов с именем qrencode.

qrencode -t ansiutf8 < wg-client.conf

wg-client.conf - это имя файла содержимым конфигурации, которую необходимо передать на другое устройство.

Заключение

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


Если данная заметка оказалась вам полезной, можете поблагодарить автора финансово на сервисе Boosty или любой суммой через сервис QIWI.