Делегирование префикса IPv6 через VPN между площадками: контрольный список
Проверки маршрутизации делегированного префикса IPv6 через VPN между площадками: карта префиксов, селекторы трафика, пересылка, MTU, обратный путь и перенумерация.
Поднять туннель — это простая половина. Я видел, как связь между площадками оставалась установленной днями, а каждый хост в удалённой локальной сети получал в ответ тишину, потому что делегированный префикс за этим шлюзом был настроен на интерфейсе, но так и не был маршрутизирован в туннель. Адреса туннеля всё это время отвечали на 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=startconn площадки 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 } acceptMTU стоит за этим. Туннель уменьшает доступный MTU ниже 1500, а IPv6 требует, чтобы каждое звено несло не менее 1280. Малые ping проходят, сеанс SSH замирает на большой пачке, а /proc/net/snmp6 показывает сообщения packet-too-big, которые так и не возвращаются. Задайте MTU туннеля явно или ограничьте TCP MSS в таблице mangle и позвольте ICMPv6, сообщающему о меньшем MTU, вернуться.
Проверяйте обратный путь, а не адрес туннеля
Сбой, который отнимает больше всего времени, — односторонняя маршрутизация. Каждый шлюз маршрутизирует удалённый префикс в туннель, но хосты отвечают через свой собственный шлюз по умолчанию, потому что именно там живёт их /64. Доставить пакет до места назначения — это половина пути.
| What you see | Likely cause | First check |
|---|---|---|
| Tunnel up, every host silent | remote prefix not routed into the tunnel | ip -6 route get on both gateways |
| Handshake renews, no replies | source prefix missing from selectors or AllowedIPs | ipsec statusall, wg show allowed-ips |
| Small pings pass, transfers stall | MTU or ICMPv6 packet-too-big filtered | /proc/net/snmp6 counters |
| Old prefix still works | stale /64 left in routes or selectors | delegation 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 должны совпадать, контрольные суммы корректируются, а приложения с буквальными адресами всё равно ломаются. Если вы сохраняете адреса провайдера от края до края, зафиксируйте поведение аренды и процедуру изменений в плане адресации.
Завершите тестом, который выдерживает время: разрешённый хост в каждой локальной сети достигает сервиса в другой сети, ответ возвращается через туннель, и та же пара работает после перезапуска туннеля и продления делегирования. Если последняя часть не проходит, проект зависит от состояния, которое не переживёт неделю.