Давным-давно в далекой галактике… в одном из чатов сообщества кто-то поделился PDF-файлом, в котором описывалось создание IPIP-туннеля поверх Yggdrasil. Автор использовал эти технологии для организации VPN-сервера на VPS, когда используемый им ранее протокол Wireguard начала блокировать тёмная сторона…
Здесь будет краткое изложение этой статьи. Ссылка на сам PDF-файл будет приведена в разделе Ссылки. К сожалению, не нашел оригинального сообщения с этим файлом в чате и не помню имени автора, иначе обязательно бы назвал его (e-mail автора есть в PDF-файле).
Да, здесь уже есть статья о настройке GRE-туннеля (технологии похожи), но решил опубликовать и про IPIP, просто для того, чтобы было [в одном месте].
Основные отличия (с точки зрения пользователя) GRE от IPIP - GRE поддерживает Multicast и инкапсулирование любого протокола третьего уровня, IPIP не поддерживает Multicast и инкапсулирует только IP (IPIP - IP over IP).
Примечание: Под IPIP здесь подразумевается IPIP6 (работаем с IPv6 адресами Yggdrasil).
Итак…
Примечание: подразумевается, что Yggdrasil уже установлен и на клиенте и на сервере (VPS), пиры прописаны, доступ к сети есть; Yggdrasil использует интерфейс tun0.
Для начала необходимо уточнить наши IPv6-адреса Yggdrasil.
Выполним команду на клиенте:
ip -br a show tun0
В результате увидим:
tun0 UNKNOWN 200:d4a5:ec3f:5914:274c:8f70::660/7
где 200:d4a5:ec3f:5914:274c:8f70::660
наш IPv6 адрес Yggdrasil.
Выполним ту же команду на сервере, увидим:
tun0 UNKNOWN 200:d4a5:ec3f:5914:274c:8f70::1/7
Здесь, соответственно, видим адрес Yggdrasil на сервере.
Создаём туннель на клиенте:
sudo ip link add name ipip6 type ip6tnl local 200:d4a5:ec3f:5914:274c:8f70::660 remote 200:d4a5:ec3f:5914:274c:8f70::1 mode ipip6
После создания туннеля у нас появятся два новых интерфейса:
ip -br a
ip6tnl0@NONE DOWN tun0 UNKNOWN 200:d4a5:ec3f:5914:274c:8f70::660/7 ipip6@NONE DOWN
Работать мы будем с интерфейсом ipip6.
Включим этот интерфейс:
sudo ip link set ipip6 up
Далее вам нужно будет определиться с адресом подсети IPv4 , которая будет работать внутри туннеля. Это может быть например 192.168.44.0/30. Из этой подсети с такой маской мы можем взять только два адреса (а больше в нашем случае и не нужно). Первый для конца туннеля на локальной машине, второй для конца туннеля на удаленном VPS.
Пускай это будут:
192.168.44.1 #Для удаленного vps 192.168.44.2 #Для локальной машины
Назначим адрес IPv4 для нашего туннеля:
sudo ip address add 192.168.44.2/30 dev ipip6
Теперь нам нужно отправить наш IPv4 трафик на VPS. На локальной машине нам нужно будет создать пару маршрутов.
По первому маршруту нужно пояснить. У вас в Yggdrasil прописан как минимум один peer через которого вы выходите в сеть. Так вот нам нужно что-бы соединение с этим пиром шло обязательно через интернет, не через сеть Yggdrasil. Потому-что мы не можем соединиться с сетью Yggdrasil через неё же саму, получается зацикливание. Из-за этого ничего работать не будет. Поэтому нам и нужен маршрут, который будет всегда «роутить» соединение до пира через обычный интернет. Как раз это правило маршрутизации нам в этом поможет.
Подставьте вместо XX.XX.XX.XX/32
IP-адрес вашего клирнет пира yggdrasil, а вместо YY.YY.YY.YY
IP-адрес вашего домашнего роутера, wifi0
- замените на интерфейс на котором у вас ваша домашняя сеть.
sudo ip route add XX.XX.XX.XX/32 via YY.YY.YY.YY dev wifi0
Далее прописываем следующий маршрут. Этот маршрут будет отправлять весь остальной трафик через наш туннель на VPS.
sudo ip route add 0.0.0.0/0 via 192.168.44.2 dev ipip6
Настройка будет такая же, разница только в IP-адресах. При создании туннеля нужно поменять IPv6 адреса местами Local IP ←→ Remote IP
sudo ip link add name ipip6 type ip6tnl local 200:d4a5:ec3f:5914:274c:8f70::1 remote 200:d4a5:ec3f:5914:274c:8f70::660 mode ipip6
Назначение IPv4-адреса на интерфейс:
sudo ip address add 192.168.44.1/30 dev ipip6
Теперь мы напишем правила для iptables , которые проведут наш трафик из туннеля в интернет.
Вместо eth0
подставьте интерфейс, с которого у вас выход в интернет.
# Эти два правила разрешат пересылку пакетов между интерфейсами sudo iptables -A FORWARD -i eth0 -o ipip6 -j ACCEPT sudo iptables -A FORWARD -i ipip6 -o eth0 -j ACCEPT # Это правило подменит локальный ip адрес (192.168.44.2) при выходе из интерфейса eth0 на внешний ip sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Всё, туннель у нас должен работать. Для проверки работоспособности «попингуйте» друг друга через туннельные ip:
ping 192.168.44.1 #На локальной машине ping 192.168.44.2 #На удаленной машине
Если всё «пингуется» в обе стороны, то туннель успешно работает. Далее проверьте, что интернет работает именно через туннель.
# Здесь мы видим что трафик уходит через ip нашего туннеля > traceroute -n 8.8.8.8 traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets 1 10.100.44.1 93.791 ms 98.394 ms 98.443 ms 2 49.11.8.1 98.441 ms 98.434 ms 98.419 ms ...
После этого у нас на локальной машине должен работать интернет через туннель, который проходит через сеть Yggdrasil.
Стоит напомнить что все эти настройки сбросятся после перезагрузки. Так что, вам необходимо их прописать в конфигурационные файлы ваших дистрибутивов Linux. Для интерфейсов это можно сделать через Systemd-Networkd с помощью файлов netdev. А с помощью файлов network можно назначить IP-адреса на интерфейсы. Для iptables правила можно прописать в файле /etc/iptables/iptables.conf
Оригинальная статья в PDF (RU): VPN через Yggdrasil
Обсуждение
Но кто-то пробовал его "в натуре" повторить??? (я сейчас этим занимаюсь).
По моему, в оригинальной статье есть несколько (2?) опечаток от автора (перекопированные и сюда, естественно).
1. На клиенте (см. выше):
$ sudo ip route add 0.0.0.0/0 via 192.168.44.2 dev ipip6
Роутинг с клиента нам нужен через ipip6 на ретранслятор, т.е. на 192.168.44.1 а не 192.168.44.2
Не?
Не.)
Следующий хоп не может быть где то там за каким то еще ip. Маршрут должен быть именно через ваш локальный 192.168.44.2. Так как ipip6 это интерфейс точка точка, то направив пакет на 192.168.44.2, он придет только на следующий конец тоннеля, а это 192.168.44.1, далее уже на серваке срабатывает локальная таблица маршрутизации и отправляет пакет в инет через маскарадинг.
Ну это как бы и требуется, что бы инет шел не через ваш роутер, а через ygg. Для этого и нужен маршрут - исключение, который будет разрешать ходить до пира ygg через ваш роутер и белый инет, иначе ничего работать не будет.