Как известно, Yggdrasil позволяет дополнительную маршрутизацию IPv4 и IPv6 сетей, помимо сети 0200::/7. Т.е. позволяет “пробросить” любые подсети через сеть Yggdrasil между двумя хостами. Тут опишу, как это сделать на Linux-машинах.

Скажем, у нас есть схема ниже и нужно через Ygg-тоннель наладить связь между хостами А (интерфейс lo с адресом 172.20.18.97/28) и С (интерфес ens18 с адресом 10.0.0.5/24). Хосты B и C в одной локальной сети, а по yggdrasil есть связь между хостами А и B.

ygg_aux_routing

На узле A

Часть конфигурации в yggdrasil, которая отвечает за дополнительную маршрутизацию находится в секции TunnelRouting. Рассмотрим конфиг на стороне узла A:

  TunnelRouting:
  {
    Enable: true
    IPv6RemoteSubnets: {}
    IPv6LocalSubnets: []
    IPv4RemoteSubnets:
    {
      10.0.0.5/32: ca68ae394a1c03bd65642c5da9f28195650e576dceeec5165a12d2d1a62f2c15
    }
    IPv4LocalSubnets:
    [
      172.20.18.97/32
    ]
  }

По пунктам:

  • Enable - для включения дополнительной маршрутизации нужно поставить в true.
  • IPv6RemoteSubnets - удаленные IPv6-сети, которые нужно маршрутизировать через ygg. Заполняется в виде сеть/маска: EncryptionPublicKey. То, что тут не заполнено, не будет маршрутизироваться через ygg.
  • IPv6LocalSubnets - локальные IPv6-сети, которые нужно принимать через ygg. Заполняется в виде сеть/маска. То, что тут не заполнено, будет отброшено.
  • IPv4RemoteSubnets - удаленные IPv4-сети, которые нужно маршрутизировать через ygg. Заполняется в виде сеть/маска: EncryptionPublicKey. То, что тут не заполнено, не будет маршрутизироваться через ygg.
  • IPv4LocalSubnets - локальные IPv4-сети, которые нужно принимать через ygg. Заполняется в виде сеть/маска. То, что тут не заполнено, будет отброшено.

Более конкретно:

    IPv4RemoteSubnets:
    {
      10.0.0.5/32: ca68ae394a1c03bd65642c5da9f28195650e576dceeec5165a12d2d1a62f2c15
    }
  • 10.0.0.5/32 - сеть, которую необходимо маршрутизаровать через yggdrasil в сторону определенного узла. В нашем случае это только один хост 10.0.0.5.
  • ca68ae394a1c03bd65642c5da9f28195650e576dceeec5165a12d2d1a62f2c15 - EncryptionPublicKey удаленного узла, в сторону которого маршрузируется IPv4-сеть. В нашем случае это EncryptionPublicKey узла B, который можно посмореть в конфиге на узле B.
    IPv4LocalSubnets:
    [
      172.20.18.97/32
    ]

172.20.18.97/32 - это адрес, который есть на интефейсe lo на узле A.

~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 172.20.18.97/28 brd 172.20.18.111 scope global lo:42
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

Вроде бы на стороне узла A все настроено, но только вот маршрутизатор системы ничего про какую-то там маршрутизацию в yggdrasil сам не знает, поэтому для “пробрасываемых” сетей еще необходимо добавлять маршруты прямо в туннельный интерфейс yggdrail. Один из вариантов, как это сделать:

ip route add 10.0.0.5/32 dev tun-ygg

Где,

  • ip route add - команда для добавления маршрута;
  • 10.0.0.5/32 - наш пробрасываемый хост;
  • dev tun-ygg - указывает, что хост доступен через интерфейс tun-ygg. В вашем случае название интерфейса для yggddrail может быть другой.

Не забываем перезапустить yggdrasil, чтобы настройки пришли в силу.

На узле B

Теперь переходим к узлу B.

На этой стороне по сути своей конфигурация будет зеркальной и выглядеть так:

  TunnelRouting:
  {
    Enable: true
    IPv6RemoteSubnets: {}
    IPv6LocalSubnets: []
    IPv4RemoteSubnets:
    {
      172.20.18.97/32: 06aac0753717863b01e4ceac0467e72ba168d42dc1c06ff338acf866a3ee9b6b
    }
    [
      10.0.0.5/32
    ]
  }

Маршрут добавляется так же зеркально:

ip route add 172.20.18.97/32 dev tun-ygg

Единственно, что нужно на этом узле вспомнить, что он будет не передавать/принимать пакеты от себя, а маршрутировать между интейфейсами ens18 и tun-ygg, поэтому должна быть включена IPv4 и/или IPv6 маршуратизация.

# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

# sysctl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 1

Обычно на Linux-машинах это включается в файле /etc/sysctl.conf.

Если на машине настроен iptables, то посмотрите нет ли ограничений в цепочке FORWARD.

Не забываем перезапустить yggdrasil, чтобы настройки пришли в силу.

На узле С

Тут все совсем просто. Нужно просто указать, что хост A находится за узлом B:

ip route add 172.20.18.97/32 via 10.0.0.10

Какие могут быть проблемы

Самое неприятное, что может быть - это добавление маршрутов при старте yggdrasil. Есть несколько вариантов, но проще всего в юните systemd для yggdrail сделать что-то вроде такого:

ExecStartPost=/sbin/ip route add 10.0.0.5/32 dev tun-ygg

При этом команд ExecStartPost можно добавить несколько.

Т.е. после старта самого yggdrail, будет добавлен маршрут в туннельный интерфейс. Только вот тогда и yggdrasil должен либо стартовать под рутом, либо юзер, под которым он стартует, должен иметь разрешение на добавление маршрутов.

Не забывайте проверять iptables, если он есть, после добавления новых маршрутов.

Как еще использовать?

Собственно, через yggdrasil можно использовать как полноценный VPN, достаточно пробросить маршрут 0.0.0.0/0 и на стороне узла-выхода в Интернет настроить NAT.

Отдельные IPv4-адреса и сети между узлами можно пробросить для приложений, которые не “понимают” IPv6. Например, это может быть замена Hamachi для онлайн-игр. Только не RealTime-игр, потому что задержки и джиттер через ygg могут быть ужасными.

В моем случае кейс описанный выше - это организация взаимодейсвия между prometheus на машине 10.0.0.5 и моим домашним сервером, для организации мониторинга.