IPv6 tussen twee werwe via ’n bestaande VPN roete
’n WAN met net IPv4 kan steeds innerlike IPv6 dra. Volg selektors, kernroetes, aansturing en die terugkeerprefiks wat antwoorde stil laat val.
Wanneer jy ’n IPv6-prefiks by ’n werf-tot-werf-tonnel voeg, reis die pakket nie soos die diagram voorstel nie. Die plaaslike poort neem die hele IPv6-pakket, versleutel dit en sit ’n buitenste IP-kop voor waarvan die adresfamilie deur die eindpuntadresse bepaal word, nie deur wat binne is nie. Die verre poort stroop daardie buitenste kop af en stuur die oorspronklike pakket na sy LAN, waar dit weer ’n gewone IPv6-pakket is. Buitenste tonnel en binneverkeer is twee aparte gesprekke wat ’n sleutel, ’n eindpuntpaar en niks anders deel nie.
Twee koppe, twee adresfamilies
In IPsec-tonnelmodus word die binne IPv6-pakket die vrag agter ’n ESP-kop. Die buitenste kop wat daardie ESP-pakket dra, kan IPv4 of IPv6 wees, en dit volg local_addrs en remote_addrs. WireGuard doen dieselfde met minder seremonie: die binne pakket is die vrag van ’n UDP-datagram na die eweknie se eindpunt. Albei laat die binne kop onaangeraak, en daarom kan die verre kant dit ná dekapsulering roete.
Die pad tussen die werwe sien net UDP 4500 wanneer IPsec NAT-deurgang gebruik, of UDP 51820 vir ’n standaard WireGuard-luisteraar. Enige router op die pad kan slegs IPv4 wees en die IPv6-verkeer steek steeds oor, want dit verskyn nooit as ’n IPv6-pakket op daardie pad nie. Dit gee ’n skoon eerste skeiding: tcpdump -ni eth0 udp port 51820 wys die versleutelde pad, tcpdump -ni wg0 ip6 wys die binneverkeer. ’n Besige buitenste opname met ’n stil binneste beteken die kernel plaas nie IPv6 in die tonnel nie; dit is roetering of beleid, nie skakeltoestand nie.
Die poort verlaag ook die binne Hop Limit terwyl dit aanstuur, so die eindpunte tel as routers op die IPv6-pad. Buitenste hopgetal en binne Hop Limit beweeg onafhanklik, en ’n pakket wat by die verre poort sterf, het in aansturing gesterf, nie in versleuteling nie.
Selektors en AllowedIPs is die toestemmingslys
IKEv2 onderhandel watter binne prefikse ’n child-SA mag dra. Op strongSwan 5.9 en later lyk dit so wanneer jy hulle in swanctl.conf uitskryf:
children {
net6 {
local_ts = 2001:db8:aa::/48
remote_ts = 2001:db8:bb::/48
mode = tunnel
esp_proposals = aes256gcm16-prfsha384-ecp384
start_action = trap
}
}
Laat local_ts en remote_ts weg en strongSwan lei hulle af uit die subnetwerke van die koppelvlak wat dit kies. Op ’n dual-stack-gasheer lewer daardie kortpad dikwels ’n paar met net IPv4: die SA kom op en IPv6 word geweier voordat dit die ESP-kode bereik. Om albei prefikse uit te skryf maak die SA geskik om hulle te dra, en start_action = trap bring dit op met die eerste pakket wat pas.
WireGuard het een lys wat twee take doen. In die eweknie-blok is AllowedIPs = 2001:db8:bb::/48, fd00:bb::/48 beide die roete wat by stuur geïnstalleer word en die filter wat by ontvangs toegepas word: ’n ontsleutelde pakket wie se binne bron buite daardie eweknie se lys val, word stil laat val. wg-quick voeg ’n roete per inskrywing by, so die eweknie-blok hieronder het geen aparte ip -6 route-opdrag nodig nie.
[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
Albei lyste moet gespieël wees: werf B aanvaar werf A se prefiks as ’n verre selektor en roete dit terug, en die tonnel werk net wanneer die twee rigtings ooreenstem. ’n Asimmetriese lys gee die simptoom wat die meeste tyd mors — ’n gesonde handdruk, tellers wat aan een kant beweeg, en ’n ping van A na B wat slaag terwyl niks van B A bereik nie.
Aansturing, roetes en die terugkeerprefiks
Linux stuur nie IPv6 aan voordat jy dit sê nie, en die instelling geld per naamruimte eerder as per koppelvlak:
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
Die tweede reël is die een wat mense in roetegebaseerde ontwerpe vergeet. Beleidsgebaseerde IPsec installeer ’n XFRM-beleid wat by die prefikse pas, maar ’n roetegebaseerde opstelling met vti6 of WireGuard het ’n werklike IPv6-roete nodig wat na daardie toestel wys. Maak die sysctl onder /etc/sysctl.d/ volhoubaar; anders sit ’n herbegin die aansturing stil terug op af.
Aansturing het ’n newe-effek wat die moeite werd is om te ken: die kernel ignoreer dan router advertisements tensy net.ipv6.conf.<wan>.accept_ra 2 is, so ’n poort wie se WAN-adres via SLAAC aankom, kan sy standaardroete verloor die oomblik wat jy aansturing aktiveer. Stel accept_ra = 2 op daardie koppelvlak in dieselfde lêer en die roete oorleef. Werf B se kern moet ook 2001:db8:aa::/48 by die tonnelpoort leer, deur ’n statiese roete of ’n roeteringsprotokol oor die tonnel, anders sterf die antwoord binne B se eie netwerk.
’n Vierstapkontrole wat die breuk lokaliseer
Werk in hierdie orde en stop by die eerste stap wat misluk, want elke latere stap hang van die vroeëres af.
- Selektors:
swanctl --list-sasbehoort die IPv6-prefikspaar op die child-SA te wys, ofwg show wg0 allowed-ipsdie verre prefiks met ’n onlangselatest-handshakes. - Kernroete:
ip -6 route get 2001:db8:bb::10moet antwoord met die tonneltoestel, nie die WAN-koppelvlak nie. - Binne-opname:
tcpdump -ni wg0 ip6terwyl jy tussen werklike LAN-gashere ping. Pakkette wat uitgaan maar niks wat terugkom wys na B se roete of vuurmuur; geen pakkette hoegenaamd wys terug na stap 1 of 2. - Bestemming: op die B-gasheer bevestig
ss -6 -ltndat die diens op IPv6 luister, en die plaaslike vuurmuurtellers wys of die pakket aanvaar of laat val is.
MTU hoort in dieselfde deurgang. IPv6-routers fragmenteer nie, so ’n oorgrote pakket word laat val en Packet Too Big kom terug na die sender. As handdrukke en klein pings werk maar ’n lêeroordrag vassteek, verklein die vrag tot dit deurkom: ping -6 -s 1400 -c 3 2001:db8:bb::10. WireGuard-koppelvlakke het by verstek 1420 grepe MTU en IPsec oor IPv4 trek meer af, so om die binne MTU te stel is beter as om te hoop op pad-MTU-ontdekking deur ’n vuurmuur wat ICMPv6 laat val.
Foutmodusse wat soos vuurmuurprobleme lyk
Die mees algemene is glad nie ’n vuurmuur nie: die diens bind aan 0.0.0.0 in plaas van ::, die AAAA-rekord bestaan, en die kliënt kry ’n vinnige weiering oor IPv6 wat ’n dual-stack-blaaier wegsteek deur na IPv4 terug te val. As net sommige toepassings misluk, kyk na die luisterfamilie voordat jy aan ’n reëlstel raak.
Die tweede is ICMPv6-filtering. Neighbor Discovery en Packet Too Big is deel van normale werking, nie diagnostiek nie, en ’n beleid wat alle ICMPv6 laat val lewer ’n tonnel wat koppel, verifieer en dan vassteek op enigiets groter as ’n klein pakket. Laat die tipes toe waarvan die pad afhang en los die tellers aan sodat ’n drupp sigbaar is.
Die derde is ’n prefiks wat by die tonnel gevoeg word maar nooit by die adresplan van die werf wat dit besit nie, so geen router adverteer dit nie en geen gasheer kan daaruit antwoord nie. Begin met een prefiks en een gasheerpaar, bewys albei rigtings met die vier stappe en voeg dan die res by; ’n stukkende prefiks bly een reël in ’n konfigurasie in plaas van ’n herontwerp. Die een amptelike verwysing wat die moeite werd is om oop te hou, is RFC 8200, wat die kop definieer wat die tonnel dra.