Дисклеймер. Автор статьи никоим образом не призывает к чему-либо, что противоречит законодательству РФ и других благословенных государств. Юзкейс этой статьи родился в быту: был я, значит, в командировке в одной из стран ближайшего (дружественного) зарубежья, а там wireguard почему-то плохо работал, а без него связь с офисом в Москве встала — удалёнка не работает. Вот и пришлось изобретать…
О чём речь
В этой статье вы узнаете как подключиться к VPN-серверу wireguard через I2P, завернув в VPN весь нужный трафик устройства, при этом приложение I2P (i2pd) будет работать штатно через домашнего интернет-провайдера. Представленная конфигурация описана для Linux-систем, в частности для дистрибутивов, основанных на Debian (с другими принципиальных проблем тоже быть не должно).
Описанный механизм может быть легко перенесен на похожие случаи с другими приложениями, в том числе без использования сети I2P. Если вы хорошо знакомы с возможностями сетевой конфигурации Linux, вряд ли узнаете что-то принципиально новое.
Сервер
Команды приведены от рута (без sudo).
Устанавливаем wireguard:
apt install wireguard
Конфигурируем wireguard в качестве принимающего сервера. Чтобы не заниматься консольными танцами, можно воспользоваться онлайн-генератором конфигов. Обратите внимание на CIDR (адрес сети), чтобы он не конфликтовал с другими вашими сетями. В примере я использую 10.20.25.0/24. Серверную часть ложим в /etc/wireguard/wg0.conf
(строки PostUp и PostDown выбрасываем, это лишнее). Также не забудьте сохранить клиентский конфиг.
В моем случае серверный конфиг рассчитан на одного клиента и выглядит примерно так (можете использовать, если сеть не конфликтует с другими вашими сетями, и не забудьте подставить ключи):
[Interface] Address = 10.20.25.1/24 ListenPort = 51820 PrivateKey = *** [Peer] PublicKey = *** AllowedIPs = 10.20.25.2/32
Wireguard не имеет настройки для биндинга на конкретный адрес, поэтому слушает на всех сетевых интерфейсах. Если это вас не устраивает, воспользуйтесь фаерволом.
Поднимаем интерфейс wireguard и добавляем его в автозагрузку:
systemctl start wg-quick@wg0 systemctl enable wg-quick@wg0
Включаем форвардинг трафика. В файле /etc/sysctl.conf
раскомментируем строку net.ipv4.ip_forward = 1
(если такой строки нет, просто добавьте ее в начало файла). Применяем изменения командой
sysctl -p
Если видите ошибку о том, что команда не найдена, воспользуйтесь whereis sysctl
и вызовите утилиту по полному пути /usr/sbin/sysctl
.
Чтобы система умела не только пересылать пакеты, но и делать это корректно между разными сетями, включаем маскарадинг (на Debian 12 в качестве фаервола по умолчанию используется nftables). В конец файла /etc/nftables.conf
добавляем
table ip nat { chain postrouting { type nat hook postrouting priority 100; policy accept; iifname "wg0" masquerade } }
Обратите внимание, что эта конфигурация включает маскарадинг только для запросов, которые приходят через интерфейс wireguard (wg0). Чтобы включить маскарадинг во всех направлениях, оставьте в строке только слово masquerade
.
На свежей системе nftables.conf примет такой вид:
#!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority filter; } chain forward { type filter hook forward priority filter; } chain output { type filter hook output priority filter; } } table ip nat { chain postrouting { type nat hook postrouting priority 100; policy accept; iifname "wg0" masquerade } }
После изменения конфига, перезапускам nftables:
systemtl restart nftables
Базовая настройка системы в качестве VPN-сервера завершена. Теперь переходим к экзотической части.
Устанавливаем i2pd по гайду из доки:
apt-get install apt-transport-https gpg wget -q -O - https://repo.i2pd.xyz/.help/add_repo | bash -s - apt-get update apt-get install i2pd
Создаем серверный туннель для приема подключений через сеть I2P. Файл /etc/i2pd/tunnels.conf
очищаем от лишнего и приводим к следующему виду:
[WG-TUNNEL] type = udpserver address = 127.0.0.1 host = 127.0.0.1 port = 51820 inport = 51820 inbound.length = 0 inbound.quantity = 1 outbound.length = 0 outbound.quantity = 1 keys = wg-tun.dat
Обратите внимание: приведена конфигурация с туннелями нулевой длины. Это значит, что любой человек или бот, который знает I2P-адрес VPN-туннеля, с легкостью определит сервер, на котором он хостится, т.к. концы входящего и исходящего туннелей будут иметь один постоянный IP-адрес.
Если по каким-то причинам вам надо скрыть сервер от вымышленного наблюдателя, установите длину туннелей в один транзитный узел и увеличьте их «ширину», используя эти значения:
inbound.length = 1 inbound.quantity = 16 outbound.length = 1 outbound.quantity = 16
Подробнее про туннели I2P можете почитать тут.
Перезапускаем i2pd и на всякий случай дублируем автозапуск сервиса, который при установке уже был добавлен туда автоматически:
systemctl restart i2pd systemctl enable i2pd
Последнее, что нам требуется на сервере — узнать I2P-адрес нашего туннеля. Самый простой способ — зайти в веб-интерфейс i2pd. Я покажу как это делается через консольный веб-браузер:
apt install lynx lynx 127.0.0.1:7070
Навигация стрелками на клавиатуре. Выбираем пункт «I2P tunnels» и оттуда копируем адрес *.b32.i2p
под заголовком из конфига (WG-TUNNEL
в примере выше).
Клиент
Сначала устанавливаем i2pd и wireguard аналогично тому, как это было сделано на сервере. Конфиги пока что не трогаем.
Если сейчас запустить VPN с маршрутом 0.0.0.0/0
, то есть в качестве сетевого шлюза системы, i2pd вместе с другими приложениями будет ходить через туннель wireguard. Нюанс в том, что нам надо завернуть трафик wireguard в i2pd, а остальные приложения пускать через WG. Вопрос!
Если VPN маршрутизирует какую-то частную сеть, проблем не будет. Но разберем случай с VPN в качестве основного шлюза. После прочтения вы поймете как упростить эту инструкцию, опустив все танцы у костра, если ваш случай именно про маршрутизацию одной приватной подсети.
Попытки разрешить через фаервол какие-то отдельные порты или адреса для прямого выхода i2pd через домашнего провайдера упрутся в тупик: I2P-роутер общается с огромным количеством случайных адресов и по разным портам. Даже протоколы разные: полноценно используются TCP и UDP.
Решение в том, чтобы организовать изолированное сетевое пространство имен, создать там виртуальный сетевой интерфейс, который будет ходить через физический сетевой адаптер в интернет через домашнего провайдера без всяких VPN. Через специальную виртуальную сеть мы вытащим туннель i2pd в основное сетевое пространство ОС и подключим к нему клиент wireguard. Чтобы вся система была максимально секьюрна, в основном сетевом пространстве имен на сетевом интерфейсе приколотим статический локальный адрес и намеренно не зададим настройки шлюза. Матёрый killswitch получится!
Постарался на схеме изобразить суть, чтобы помимо конфигурационных строчек была почва для простого понимания. Ниже те самые строчки, которые надо скопировать и положить в файлик setup_network.sh
в любом удобном месте.
Обратите внимание, что в переменной IP_ADDRESS
надо указать свободный адрес вашей локальной сети — с ним будет создан изолированный сетевой интерфейс в пространстве имен i2pd, который станет равноценным участником вашей локалки помимо основного интерфейса.
#!/bin/bash # acetone, 2024 # Set your default gateway settings INTERFACE="eth0" IP_ADDRESS="192.168.0.99/24" GATEWAY="192.168.0.1" # Nothing below this line should be changed unless you know what you are doing! # Create i2pd network namespace ip netns add i2pd_ns ip netns exec i2pd_ns ip link set lo up # Create macvlan interface (gateway for i2pd_ns) ip link add macvlan0 link $INTERFACE type macvlan mode bridge ip link set macvlan0 netns i2pd_ns # Activate the macvlan interface in the i2pd namespace ip netns exec i2pd_ns ip link set macvlan0 up # Configuring the IP address and route for i2pd_ns ip netns exec i2pd_ns ip addr add $IP_ADDRESS dev macvlan0 ip netns exec i2pd_ns ip route add default via $GATEWAY dev macvlan0 # Create virtual interfaces for i2pd to communicate with the main system ip link add bri2pd_external type veth peer name bri2pd_internal ip link set bri2pd_external up ip link set bri2pd_internal netns i2pd_ns up ip addr add 10.10.10.1/30 dev bri2pd_external ip netns exec i2pd_ns ip addr add 10.10.10.2/30 dev bri2pd_internal
Запускаем скрипт, чтобы создать в системе изолированную сеть и прочие прелести (от рута).
chmod +x ./setup_network.sh ./setup_network.sh
Я использую systemd-сервис, чтобы скрипт отрабатывал всегда при старте системы и без моего участия. Если хотите также, создайте файл /etc/systemd/system/setup-network-ns.service
со следующим содержимым (исправьте строку ExecStart):
[Unit] Description=Setup Network Namespace After=network.target Wants=network.target [Service] Type=oneshot User=root ExecStart=/path/to/your/setup_network.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target
Когда файл сервиса создан, добавляем его в автозагрузку:
systemctl enable setup-network-ns
Сетевое пространство имен создано. Чтобы мы смогли без прав суперпользователя и ввода пароля запускать в нем приложения, поставим утилиту netns-exec
:
apt install git build-essential git clone --recursive https://github.com/freeacetone/netns-exec cd netns-exec make make install
Финишная прямая! Конфигурируем i2pd и wireguard.
В /etc/i2pd/tunnels.conf
убираем лишнее и создаем туннель до сервера (замените значение в строке destination
):
[WG-CLIENT] type = udpclient address = 10.10.10.2 host = 10.10.10.2 port = 51820 destination = ***.b32.i2p destinationport = 51820 inbound.length = 1 inbound.quantity = 16 outbound.length = 1 outbound.quantity = 16 keys = transient-vpn
Приведен конфиг с длиной туннелей в 1 транзитный узел. Это значит, что ваше устройство не будет обращаться напрямую на IP-адрес сервера. Всегда будут рандомные транзитные узлы. Если хотите подключаться напрямую, замените значения на
inbound.length = 0 inbound.quantity = 1 outbound.length = 0 outbound.quantity = 1
Теперь нужно внести небольшое изменение в файл сервиса i2pd, чтобы i2pd запускался в изолированном сетевом пространстве. В файле /lib/systemd/system/i2pd.service
исправляем строку ExecStart, добавляя в ее начало /usr/local/bin/netns-exec i2pd_ns
systemctl daemon-reload systemctl restart i2pd
Если все было сделано верно, i2pd работает в отдельной сети и уже предоставляет туннель до VPN сервера. Работу в отдельной сети легко проверить через консольный браузер:
apt install lynx lynx 127.0.0.1:7070
Ошибка — это правильно! i2pd работает в изолированном пространстве имен. Если запустить браузер в том же пространстве (i2pd_ns), все будет ок:
netns-exec i2pd_ns lynx 127.0.0.1:7070
Наконец, конфигурируем туннель wireguard. Создаем файл /etc/wireguard/wg0.conf
, вставляем в него клиентский конфиг (подставьте ключи и замените значение Address в зависимости от конфига на сервере):
[Interface] PrivateKey = *** Address = 10.20.25.2/24 DNS = 94.140.14.14 [Peer] PublicKey = *** Endpoint = 10.10.10.2:51820 AllowedIPs = 0.0.0.0/0, ::/0
В AllowedIPs
важно вставлять IPv6 маршрут по умолчанию (::/0
) даже если сервер VPN его не поддерживает — страховка от того, что IPv6 потечет мимо VPN.
Директива «DNS» не будет работать, если в системе не установлен resolvconf. Установить его просто:
apt install resolvconf
Готово! Поднимаем туннель wireguard и добавляем его в автозагрузку:
systemctl start wg-quick@wg0 systemctl enable wg-quick@wg0
Важно: чтобы настроить киллсвитч (предотвращение утечки пакетов при отключенном VPN), после завершения всех действий, когда убедитесь, что VPN работает, задайте статические настройки вашего основного сетевого интерфейса, убрав gateway.
Экспириенс
Саспенс — это слово почему-то просится быть первым после «экспириенс» в данном контексте.
Несколько замеров на загрузку большого файла через wget
на кабеле 100Мб/сек показали, что при туннелях нулевой длины скорость падает примерно в два-четыре раза с редкими возможными скачками до 80% от реальной пропускной способности канала (верю в светлое будущее, где новые релизы i2pd улучшат показатель). При туннелях с ненулевой длиной стабильный замер практически невозможен: промежуточные узлы — кот в мешке. Видео грузятся и ладно. Стабильным такое подключение назвать нельзя, но и нерабочим — тоже, и это главное. VPN через I2P, Карл!
Возможны ли случайные утечки трафика? При приведенной конфигурации — нет. Сетевое пространство имен для i2pd изолировано от основной системы на уровне ядра ОС, при этом в доступном для пользователя пространстве нет маршрутов по умолчанию кроме VPN-туннеля. Если wireguard по каким-то причинам упадет, ПК останется оффлайн даже при том, что i2pd продолжит штатную работу.
Высокотехнологичный костыль красивее родной ноги.
ссылка на оригинал статьи https://habr.com/ru/articles/869816/
Добавить комментарий