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

Напишите карту префиксов, прежде чем трогать туннель

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

Для каждой площадки запишите делегированный префикс, фактически используемый в локальной сети /64, адреса туннеля и владельца каждого маршрута. Провайдер делегирует площадке A префикс 2001:db8:a1::/56, которая обслуживает в своей локальной сети 2001:db8:a1:10::/64; площадка B сохраняет 2001:db8:b2::/64. Если площадка A обслуживает только этот единственный /64, обе стороны должны указывать 2001:db8:a1:10::/64, а не весь /56.

Почти всегда проявляются две ошибки. Одна — считать удалённый префикс on-link, объединять его в мост или помещать на интерфейс туннеля, из-за чего шлюз отвечает на запросы соседей за хосты, до которых не может добраться. Другая — анонсировать весь /56, когда настроен только один /64: таблица маршрутов утверждает, что блок достижим, и большинство адресов уходит в чёрную дыру.

Согласуйте селекторы трафика обеих сторон с маршрутами

IKEv2 и WireGuard оба отклоняют несовпадающий трафик, достаточно тихо, чтобы туннель продолжал выглядеть здоровым.

В strongSwan селекторы задаются явно. На площадке A:

conn a-to-b
    left=2001:db8:ff::1
    leftsubnet=2001:db8:a1:10::/64
    right=2001:db8:ff::2
    rightsubnet=2001:db8:b2::/64
    auto=start

conn площадки B зеркально отражает обе подсети. Когда они не совпадают, ответчик отклоняет CHILD_SA с TS_UNACCEPTABLE, поэтому дочерний SA никогда не поднимется, хотя IKE_SA поднялся. С обеих сторон настроенная подсеть должна совпадать с тем, что локальное ядро маршрутизирует в сторону туннеля.

WireGuard несёт ту же информацию в AllowedIPs, с одной особенностью: AllowedIPs — это фильтр источника при приёме и маршрут при отправке. Если запись peer площадки B для площадки A не включает 2001:db8:a1:10::/64, пакеты с площадки A приходят при действительном handshake и отбрасываются как неразрешённые. Отсюда знакомый шаблон: handshake постоянно обновляется, а ответ так и не уходит. Сравните обе стороны с помощью wg show wg0 allowed-ips. Перепроверяйте этот список при каждом изменении делегирования; устаревший /64 держит сеанс живым, а новый префикс — недостижимым.

Сначала исключите пересылку, межсетевой экран и MTU

Прежде чем читать следующую строку журнала, убедитесь, что шлюзы вообще пересылают. sysctl net.ipv6.conf.all.forwarding должен вернуть 1 на обоих, применённый также к интерфейсам туннеля и локальной сети. Есть одна ловушка: после включения пересылки интерфейс с accept_ra=1 перестаёт принимать объявления маршрутизатора от провайдера, поэтому машина может потерять вышестоящий маршрут по умолчанию, хотя внутри туннеля маршрутизирует безупречно. Установите accept_ra=2 там, где объявления провайдера всё ещё нужны.

Затем правила межсетевого экрана должны разрешать префикс в обоих направлениях, а ICMPv6 должен выживать: обнаружение соседей, packet-too-big и destination-unreachable не являются необязательными. Отбросьте их, и обнаружение MTU пути сломается, а вы получите соединения, которые открываются и затем замирают на первом большом ответе. Минимальная пара правил выглядит так:

nft add rule inet filter forward ip6 saddr 2001:db8:a1:10::/64 ip6 daddr 2001:db8:b2::/64 accept
nft add rule inet filter forward ip6 saddr 2001:db8:b2::/64 ip6 daddr 2001:db8:a1:10::/64 accept
nft add rule inet filter forward icmpv6 type { packet-too-big, nd-neighbor-solicit, nd-neighbor-advert } accept

MTU стоит за этим. Туннель уменьшает доступный MTU ниже 1500, а IPv6 требует, чтобы каждое звено несло не менее 1280. Малые ping проходят, сеанс SSH замирает на большой пачке, а /proc/net/snmp6 показывает сообщения packet-too-big, которые так и не возвращаются. Задайте MTU туннеля явно или ограничьте TCP MSS в таблице mangle и позвольте ICMPv6, сообщающему о меньшем MTU, вернуться.

Проверяйте обратный путь, а не адрес туннеля

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

What you seeLikely causeFirst check
Tunnel up, every host silentremote prefix not routed into the tunnelip -6 route get on both gateways
Handshake renews, no repliessource prefix missing from selectors or AllowedIPsipsec statusall, wg show allowed-ips
Small pings pass, transfers stallMTU or ICMPv6 packet-too-big filtered/proc/net/snmp6 counters
Old prefix still worksstale /64 left in routes or selectorsdelegation lease and route table

Две команды решают большую часть. На площадке A ip -6 route get 2001:db8:b2::53 from 2001:db8:a1:10::5 показывает, какой интерфейс использовал бы ответ из этого источника; выполните зеркальную проверку на площадке B. Затем создайте трафик с хоста, а не со шлюза, и сравните счётчики на обоих концах.

Если запрос соседей для удалённого префикса появляется на туннеле, этот префикс где-то является on-link там, где не должен; исправьте это до настройки маршрутов. Proxy NDP покрывает случаи, когда мост действительно необходим, а не заменяет маршрут.

Планируйте смену префикса под собой

Делегирование префикса — это аренда между делегирующим и запрашивающим маршрутизатором, и продление может вернуть другой блок: другой /56 после миграции провайдера или более короткую аренду, чем время работы туннеля. Каждое место, называющее старый префикс, устаревает сразу: маршруты, селекторы, AllowedIPs, правила межсетевого экрана, записи DNS и любой мониторинг, в котором зашиты буквальные адреса. Поток сообщений описан в RFC 8415.

Там, где ожидается перемещение префикса, держите внутренний план адресации, не зависящий от него, и транслируйте на границе. NPTv6 — вариант без состояния, он сохраняет читаемость внутренней политики, но это трансляция префикса, а не волшебный слой: границы /64 должны совпадать, контрольные суммы корректируются, а приложения с буквальными адресами всё равно ломаются. Если вы сохраняете адреса провайдера от края до края, зафиксируйте поведение аренды и процедуру изменений в плане адресации.

Завершите тестом, который выдерживает время: разрешённый хост в каждой локальной сети достигает сервиса в другой сети, ответ возвращается через туннель, и та же пара работает после перезапуска туннеля и продления делегирования. Если последняя часть не проходит, проект зависит от состояния, которое не переживёт неделю.

Похожие статьи