WireGuard VPN туннель между двумя серверами на Debian

Задача

Организовать доступ через интернет к серверу, который находится за NAT на неподконтрольном маршрутизаторе с динамическим серым внешним IP, соответственно проброс портов с этого маршрутизатора невозможен. Перефразируя в реальный пример: нужно открывать сайт, размещенный на сервере в здании московской школы, через интернет. Интернет в здании предоставляется по госконтракту, оборудование сети школой не контролируется.

Решить эту задачу можно с помощью проброса портов через VPN-туннель между самым дешевым VPS в интернете с публичным IP-адресом и сервером/маршрутизатором внутри локальной сети. Туннель будет на основе WireGuard — простого, современного и быстрого VPN-протокола с минимумом настроек без возни с сертификатами и шифрами (привет, OpenVPN).

В статье используются виртуальные машины на Debian 9:

  1. wg-lab-01, 192.168.1.101 — сервер WireGuard «VPS в интернете»
  2. wg-lab-02, 192.168.1.102 — клиент WireGuard «роутер за NAT»
  3. wg-lab-03, 192.168.1.103 — веб-сервер

Пусть ВМ wg-lab-01 имеет публичный IP-адрес и будет использоваться как сервер Wireguard (к нему будут подключаться клиенты) и маршрутизатор для проброса портов на ВМ wg-lab-02, используемую как клиент Wireguard (будет инициализировать подключение к серверу) и маршрутизатор. С ВМ wg-lab-02 те же порты будут перенаправляться на ВМ wg-lab-03, на которой запущен веб-сервер nginx, а в настройках сетевого подключения IP-адрес ВМ wg-lab-02 указан в качестве шлюза по умолчанию (Default gateway).

Трафик должен проходить следующим образом:

посетитель сайта <-> интернет <-> wg-lab-01 <-> [туннель wireguard] <-> wg-lab-02 <-> wg-lab-03

Для упрощения конфигурации, весь трафик wg-lab-02 идет через туннель, а также все ВМ запущены внутри одного VLAN.

Настройка туннеля и маршрутизации

Все настройки выполняются через SSH от имени пользователя root.

На wg-lab-01 и wg-lab-02

# Установить wireguard
echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable-wireguard.list;
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable;
apt update && apt list --upgradable;
apt full-upgrade;
apt install wireguard tcpdump iptables-save;
# Включить маршрутизацию
sed -i 's/^#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf;
sysctl -p;
reboot;
# Сгенерировать ключи wireguard
(umask 077 && printf "[Interface]\nPrivateKey = " | tee /etc/wireguard/wg0.conf > /dev/null);
wg genkey | tee -a /etc/wireguard/wg0.conf | wg pubkey | tee /etc/wireguard/publickey;

На wg-lab-01

Отредактировать файл конфигурации nano /etc/wireguard/wg0.conf

[Interface]
Address = 10.255.255.1/24
SaveConfig = true
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = В ФАЙЛЕ КЛЮЧ УЖЕ ДОЛЖЕН БЫТЬ

[Peer]
PublicKey = публичный ключ с wg-lab-02 # см. в файле /etc/wireguard/publickey
AllowedIPs = 10.255.255.2/32
PersistentKeepalive = 10

На wg-lab-02

Отредактировать файл конфигурации nano /etc/wireguard/wg0.conf

[Interface]
Address = 10.255.255.2/24
SaveConfig = true
PostUp = iptables -A FORWARD -i eth0 -j ACCEPT; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PostDown = iptables -D FORWARD -i eth0 -j ACCEPT; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE
PrivateKey = В ФАЙЛЕ КЛЮЧ УЖЕ ДОЛЖЕН БЫТЬ

[Peer]
Endpoint = 192.168.1.101:51820
PublicKey = публичный ключ с wg-lab-01 # см. в файле /etc/wireguard/publickey
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 10

На wg-lab-01 и wg-lab-02

Включить автозапуск интерфейса wg0

systemctl enable wg-quick@wg0;
wg-quick up wg0;

Проверить, что туннель и маршрутизация работают

На wg-lab-02

  • В выводе команды wg присутствует строка latest handshake
  • Адрес интерфейса wg0 на сервере wg-lab-01 пингуется ping 10.255.255.1
  • В выводе команды traceroute ya.ru первый прыжок на 10.255.255.1
  • Если бы настраивали через реальный VPS в интернете, то команда host myip.opendns.com resolver1.opendns.com показывала бы IP-адрес VPS, а не текущего подключения к интернету

Настройка веб-сервера

На wg-lab-03

  1. Установить и запустить веб-сервер nginx командой apt install nginx, или, если установлен Docker, командой docker run –name nginx -d -p 80:80 –restart unless-stopped nginx:alpine
  2. Проверить доступность веб-сервера по текущему IP-адресу, полученному через DHCP (см. ip a)
  3. Настроить статический IP-адрес и указать шлюз по умолчанию IP сервера wg-lab-02, перезагрузить для применения настроек

Проброс портов

На wg-lab-01

iptables -t nat -A PREROUTING -d 192.168.1.101/32 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 10.255.255.2

На wg-lab-02

iptables -t nat -A PREROUTING -d 10.255.255.2/32 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 192.168.1.103

Настроенные таким образом правила iptables работают до перезагрузки. Чтобы сделать правила постоянными, нужно либо сохранить их с помощью команды iptables-save > /etc/iptables/rules.v4, либо соответствующим образом дополнить строки PostUp и PostDown в файлах /etc/wireguard/wg0.conf на обоих ВМ с Wireguard, чтобы правила применялись при активации интерфейса wg0.

Проверить активные правила можно командой iptables -t nat -L -n -v

Проверить, что проброс портов работает

В браузере открыть IP-адрес wg-lab-01 (192.168.1.101) и убедиться, что открывается страница с веб-сервера на wg-lab-03.

Источники

Как в Экселе…

Когда нужно оформить список работников отдела для поощрения или отчёт о работе менеджеров, многие люди используют Microsoft Excel. А если задача чуть сложнее простого перечисления фамилий в столбик, то постоянно возникает вопрос «Как в экселе сделать что-то».

За время работы у меня собралось несколько полезных формул для обработки ячеек с ФИО и мобильными телефонами, которые постоянно находят своё применение.

Как в Экселе…

…сократить ФИО до инициалов (Фамилия И.О.)
=(ЛЕВСИМВ(A1;ПОИСК(" *";A1)-1)&" "&ПСТР(A1;ПОИСК(" *";A1)+1;1)&"."&ПСТР(A1;ПОИСК(" *";A1;ПОИСК(" *";A1)+1)+1;1)&".")

…переставить последнее слово в ячейке в начало (ФИО → ИОФ)
=СЖПРОБЕЛЫ(ПРАВСИМВ(A1;ДЛСТР(A1)-НАЙТИ(" ";A1))&" "&ЛЕВСИМВ(A1;НАЙТИ(" ";A1)))

…оставить 1 слово с начала строки (Фамилия)
=ЛЕВСИМВ(A1;ПОИСК(" ";A1)-1)

…оставить 2 слова с начала строки (Фамилия Имя или Имя Отчество)
=ЛЕВСИМВ(A1;ПОИСК(" ";A1;ПОИСК(" ";A1)+1)-1)

…расставить дефисы в десятизначном телефонном номере (89991234567 → 8-999-123-45-67)
=ЛЕВСИМВ(A2;1)&"-"&ЛЕВСИМВ(ПРАВСИМВ(A2;10);3)&"-"&ЛЕВСИМВ(ПРАВСИМВ(A2;7);3)&"-"&ЛЕВСИМВ(ПРАВСИМВ(A2;4);2)&"-"&ЛЕВСИМВ(ПРАВСИМВ(A2;2);2)

Скачать таблицу с примерами

Мои проекты

https://gia.devmem.ru — база сотрудников пунктов проведения экзаменов в Москве во время ГИА.
Технологии: javascript, React и Redux

https://gia-api.devmem.ru — API и html-версия интерфейса базы сотрудников ППЭ.
Технологии: python, Django, Django REST Framework, парсер на основе Requests, BeautifulSoup, Openpyxl

https://soft.devmem.ru — автоматически обновляемый список самых необходимых программ для Windows.
Технологии: python, Django, парсер на основе MechanicalSoup

https://github.com/spirkaa/hkbattery — сравнение батарей LiPo на русском складе HobbyKing. Склад закрыли, а код остался.
Технологии: python, Django, парсер на основе aiohttp и BeautifulSoup

https://svadj.ru — сайт мобильного диджея.
Технологии: WordPress, шаблон Impreza

@co1858_bot -Telegram бот для Центра образования №1858. Отправляет расписание детей и учителей, последние новости с сайта, видео с канала YouTube
Технологии: python, aiotg, контент собирается с помощью gspread, aiohttp, BeautifulSoup, selenium.webdriver