Когато добавите префикс IPv6 към тунел между обекти, пакетът не пътува както подсказва диаграмата. Локалният шлюз взема целия пакет IPv6, шифрова го и поставя пред него външен IP заглавка, чието семейство адреси се определя от адресите на крайните точки, а не от това, което е вътре. Отдалеченият шлюз премахва тази външна заглавка и препраща оригиналния пакет към своята LAN, където той отново е обикновен пакет IPv6. Външният тунел и вътрешният трафик са два отделни разговора, които споделят ключ, двойка крайни точки и нищо друго.

Две заглавки, две семейства адреси

В режим на тунел IPsec вътрешният пакет IPv6 става полезен товар зад ESP заглавка. Външната заглавка, която носи този ESP пакет, може да бъде IPv4 или IPv6 и следва local_addrs и remote_addrs. WireGuard прави същото с по-малко церемонии: вътрешният пакет е полезният товар на UDP дейтаграма към крайната точка на партньора. И двете оставят вътрешната заглавка недокосната, затова отдалечената страна може да го маршрутизира след декапсулация.

Пътят между обектите вижда само UDP 4500, когато IPsec използва преминаване през NAT, или UDP 51820 за слушател WireGuard по подразбиране. Всеки маршрутизатор по пътя може да е само IPv4 и трафикът IPv6 все пак преминава, защото на този път никога не се появява като пакет IPv6. Това дава чисто първо разделяне: tcpdump -ni eth0 udp port 51820 показва шифрования път, tcpdump -ni wg0 ip6 показва вътрешния трафик. Зает външен запис с мълчалив вътрешен означава, че ядрото не поставя IPv6 в тунела; това е маршрутизиране или политика, а не състояние на връзката.

Шлюзът също намалява вътрешния Hop Limit при препращане, така че крайните точки се броят за маршрутизатори по пътя IPv6. Външният брой скокове и вътрешният Hop Limit се движат независимо, а пакет, който умира на отдалечения шлюз, е умрял при препращането, не при шифроването.

Селекторите и AllowedIPs са списъкът с разрешения

IKEv2 договаря кои вътрешни префикси може да носи child SA. На strongSwan 5.9 и по-нови изричното им записване в swanctl.conf изглежда така:

children {
  net6 {
    local_ts  = 2001:db8:aa::/48
    remote_ts = 2001:db8:bb::/48
    mode = tunnel
    esp_proposals = aes256gcm16-prfsha384-ecp384
    start_action = trap
  }
}

Ако пропуснете local_ts и remote_ts, strongSwan ги извежда от подмрежите на избрания интерфейс. На хост с dual-stack този пряк път често дава двойка само IPv4: SA се вдига и IPv6 се отхвърля, преди да стигне до кода ESP. Записването на двата префикса прави SA способен да ги носи, а start_action = trap го вдига при първия подходящ пакет.

WireGuard има един списък, който върши две работи. В блока на партньора AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48 е едновременно маршрутът, инсталиран при изпращане, и филтърът, прилаган при получаване: дешифриран пакет, чийто вътрешен източник падне извън списъка на този партньор, тихо се изхвърля. wg-quick добавя маршрут за всеки запис, затова блокът на партньора по-долу не се нуждае от отделна команда ip -6 route.

[Interface]
Address = 2001:db8:aa:ff::1/64, fd00:aa:ff::1/64
ListenPort = 51820

[Peer]
PublicKey = <site-b-public-key>
Endpoint = 203.0.113.20:51820
AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48

Двата списъка трябва да са огледални: обект B приема префикса на обект A като отдалечен селектор и го маршрутизира обратно, и тунелът работи само когато двете посоки съвпадат. Асиметричният списък дава симптома, който поглъща най-много време — здраво ръкостискане, броячи, движещи се от една страна, и ping от A към B, който успява, докато нищо от B не достига до A.

Препращане, маршрути и връщащ префикс

Linux не препраща IPv6, докато не кажете, и настройката важи за пространство от имена, а не за интерфейс:

sysctl -w net.ipv6.conf.all.forwarding=1
ip -6 route add 2001:db8:bb::/48 dev wg0
ip -6 route get 2001:db8:bb::10 from 2001:db8:aa::10

Вторият ред е този, който хората забравят в схеми, базирани на маршрути. IPsec, базиран на политики, инсталира XFRM политика, съответстваща на префиксите, но конфигурация, базирана на маршрути с vti6 или WireGuard, се нуждае от истински маршрут IPv6, сочещ към това устройство. Запазете sysctl под /etc/sysctl.d/; иначе рестарт тихо връща препращането в изключено състояние.

Препращането има страничен ефект, който си струва да се знае: ядрото тогава игнорира обявленията на маршрутизаторите, освен ако net.ipv6.conf.<wan>.accept_ra не е 2, затова шлюз, чийто WAN адрес пристига през SLAAC, може да загуби маршрута си по подразбиране в момента, в който включите препращането. Задайте accept_ra = 2 на този интерфейс в същия файл и маршрутът оцелява. Ядрото на обект B също трябва да научи 2001:db8:aa::/48 от шлюза на тунела, чрез статичен маршрут или протокол за маршрутизиране върху тунела, иначе отговорът умира вътре в собствената мрежа на B.

Проверка в четири стъпки, която локализира прекъсването

Работете в този ред и спрете на първата стъпка, която се провали, защото всяка следваща стъпка зависи от предишните.

  1. Селектори: swanctl --list-sas трябва да покаже двойката префикси IPv6 на child SA, или wg show wg0 allowed-ips отдалечения префикс със свеж latest-handshakes.
  2. Маршрут на ядрото: ip -6 route get 2001:db8:bb::10 трябва да отговори с устройството на тунела, а не с интерфейса WAN.
  3. Вътрешен запис: tcpdump -ni wg0 ip6 докато правите ping между истински хостове на LAN. Пакети, които излизат, но нито един не се връща, сочат към маршрута или защитната стена на B; пълната липса на пакети сочи обратно към стъпка 1 или 2.
  4. Предназначение: на хоста B ss -6 -ltn потвърждава, че услугата слуша на IPv6, а локалните броячи на защитната стена показват дали пакетът е бил приет или изхвърлен.

MTU влиза в същия проход. Маршрутизаторите IPv6 не фрагментират, затова прекалено големият пакет се изхвърля и Packet Too Big се връща на подателя. Ако ръкостисканията и малките ping работят, но пренасянето на файл засяда, намалете полезния товар, докато не премине: ping -6 -s 1400 -c 3 2001:db8:bb::10. Интерфейсите WireGuard по подразбиране имат MTU 1420 байта, а IPsec върху IPv4 отнема повече, затова задаването на вътрешния MTU е по-добре от надеждата за откриване на MTU на пътя през защитна стена, която изхвърля ICMPv6.

Режими на отказ, които изглеждат като проблеми със защитна стена

Най-честият съвсем не е защитна стена: услугата се свързва с 0.0.0.0 вместо с ::, записът AAAA съществува, и клиентът получава бърз отказ през IPv6, който браузър с dual-stack скрива, като се връща към IPv4. Ако се провалят само някои приложения, проверете семейството на слушане, преди да пипате набор от правила.

Вторият е филтриране на ICMPv6. Neighbor Discovery и Packet Too Big са част от нормалната работа, а не от диагностиката, и политика, която изхвърля целия ICMPv6, създава тунел, който се свързва, удостоверява и после засяда на всичко по-голямо от малък пакет. Разрешете типовете, от които зависи пътят, и оставете броячите включени, за да се вижда изхвърлянето.

Третият е префикс, добавен към тунела, но никога към адресния план на обекта, който го притежава, затова нито един маршрутизатор не го обявява и нито един хост не може да отговори от него. Започнете с един префикс и една двойка хостове, докажете двете посоки с четирите стъпки, след което добавете останалото; счупеният префикс остава един ред в конфигурация вместо преработка. Единствената официална препратка, която си струва да остане отворена, е RFC 8200, която определя заглавката, която тунелът носи.

Подобни статии