การกำหนดเส้นทาง IPv6 ระหว่างสองไซต์ผ่าน VPN ที่มีอยู่
WAN ที่มีเฉพาะ IPv4 ยังคงพา IPv6 ภายในได้ ติดตามตัวเลือก เส้นทางของเคอร์เนล การส่งต่อ และคำนำหน้ากลับที่ทิ้งคำตอบอย่างเงียบ ๆ
เมื่อคุณเพิ่มคำนำหน้า IPv6 ให้อุโมงค์ระหว่างไซต์ แพ็กเก็ตไม่ได้เดินทางอย่างที่แผนภาพบอก เกตเวย์ท้องถิ่นรับแพ็กเก็ต IPv6 ทั้งหมด เข้ารหัส แล้ววางหัวข้อ IP ภายนอกไว้ข้างหน้า ซึ่งตระกูลแอดเดรสของมันถูกกำหนดโดยแอดเดรสของปลายทาง ไม่ใช่โดยสิ่งที่อยู่ข้างใน เกตเวย์ปลายทางถอดหัวข้อภายนอกนั้นออกและส่งต่อแพ็กเก็ตเดิมไปยัง LAN ของตน ซึ่งที่นั่นมันกลับเป็นแพ็กเก็ต IPv6 ธรรมดา อุโมงค์ภายนอกกับทราฟฟิกภายในเป็นการสนทนาสองอย่างที่แยกกัน ซึ่งแบ่งปันคีย์ คู่ปลายทาง และไม่มีอย่างอื่น
สองหัวข้อ สองตระกูลแอดเดรส
ในโหมดอุโมงค์ IPsec แพ็กเก็ต IPv6 ภายในกลายเป็นเพย์โหลดหลังหัวข้อ ESP หัวข้อภายนอกที่บรรทุกแพ็กเก็ต ESP นั้นอาจเป็น IPv4 หรือ IPv6 และทำตาม local_addrs กับ remote_addrs WireGuard ทำแบบเดียวกันด้วยพิธีน้อยกว่า: แพ็กเก็ตภายในคือเพย์โหลดของดาตาแกรม UDP ไปยังปลายทางของคู่ค้า ทั้งสองปล่อยหัวข้อภายในไว้ไม่แตะต้อง ซึ่งเป็นเหตุผลที่ฝั่งปลายทางกำหนดเส้นทางได้หลังถอดหัวข้อ
เส้นทางระหว่างไซต์เห็นเพียง UDP 4500 เมื่อ IPsec ใช้ NAT traversal หรือ 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 เป็นตัวเลือกระยะไกลและกำหนดเส้นทางกลับ และอุโมงค์จะทำงานก็ต่อเมื่อทั้งสองทิศทางตรงกัน รายการที่ไม่สมมาตรให้อาการที่กินเวลามากที่สุด — แฮนด์เชกที่แข็งแรง ตัวนับที่เดินอยู่ฝั่งเดียว และ ปิงจาก 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 เอง
การตรวจสี่ขั้นตอนที่ระบุตำแหน่งการขาดหาย
ทำงานตามลำดับนี้และหยุดที่ขั้นตอนแรกที่ล้มเหลว เพราะทุกขั้นตอนถัดไปขึ้นกับขั้นก่อนหน้า
- ตัวเลือก:
swanctl --list-sasควรแสดงคู่คำนำหน้า IPv6 บน child SA หรือwg show wg0 allowed-ipsคำนำหน้าระยะไกลพร้อมlatest-handshakesที่ใหม่ - เส้นทางเคอร์เนล:
ip -6 route get 2001:db8:bb::10ต้องตอบด้วยอุปกรณ์อุโมงค์ ไม่ใช่อินเทอร์เฟซ WAN - การดักจับภายใน:
tcpdump -ni wg0 ip6ขณะปิงระหว่างโฮสต์ LAN จริง แพ็กเก็ตที่ออกไปแต่ไม่มีกลับมาชี้ไปที่เส้นทางหรือไฟร์วอลล์ของ B ไม่มีแพ็กเก็ตเลยชี้กลับไปที่ขั้นตอนที่ 1 หรือ 2 - ปลายทาง: บนโฮสต์ B
ss -6 -ltnยืนยันว่าบริการฟังอยู่บน IPv6 และตัวนับไฟร์วอลล์ท้องถิ่นแสดงว่าแพ็กเก็ตถูกยอมรับหรือทิ้ง
MTU อยู่ในรอบเดียวกัน เราเตอร์ IPv6 ไม่แยกส่วน ดังนั้นแพ็กเก็ตที่ใหญ่เกินจะถูกทิ้งและ Packet Too Big กลับมาหาผู้ส่ง หากแฮนด์เชกกับปิงเล็กทำงานแต่การถ่ายโอนไฟล์หยุด ให้ลดเพย์โหลดจนผ่าน: 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 ซึ่งนิยามหัวข้อที่อุโมงค์บรรทุก