Laluan lalai IPv6 hilang selepas mengaktifkan penghantaran di Linux
Mengaktifkan penghantaran IPv6 menyebabkan kernel mengabaikan router advertisement pada uplink, dan laluan lalai yang dipelajari luput. Betulkan dengan accept_ra.
Saya menetapkan net.ipv6.conf.all.forwarding=1 pada get laluan Debian supaya ia dapat menghantar trafik klien VPN, dan kira-kira setengah jam kemudian mesin itu tidak lagi mempunyai laluan lalai IPv6. Penghala huluan hidup, jiran link-local masih menjawab, dan uplink masih memegang alamat globalnya. Yang berhenti ialah kesediaan kernel untuk terus menerima router advertisement pada antara muka itu. Laluan itu tidak hilang ketika saya menaip sysctl; ia hilang apabila hayat laluan lalai yang dipelajari daripada RA tamat dan tiada apa-apa memperbaharuinya.
Sekali pandang tiada apa yang kelihatan rosak. Penghantaran berfungsi, klien masih melepasi selagi laluan lama masih dalam cache, dan kegagalan datang lebih lewat daripada perubahan yang menyebabkannya. Jeda itulah sebabnya masalah ini disalahkan pada huluan atau pada peraturan firewall yang tidak pernah terlibat.
Baca jadual laluan sebelum menyentuh mana-mana sysctl
Mulakan dengan ip -6 route show default dan baca atributnya, bukan hanya get laluan. Laluan lalai yang dipelajari daripada RA ditandai proto ra, membawa keutamaan dan menunjukkan kiraan detik expires. Laluan yang ditambah secara manual tidak mempunyai kedua-duanya, dan perbezaan itu memberitahu anda mekanisme mana yang memiliki laluan itu.
$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref mediumKemudian lihat alamatnya: ip -6 addr show dev eth0. Alamat global dengan hayat pilihan dan sah yang diukur dalam jam akan bertahan lebih lama daripada laluan lalai yang hayat penghalanya diukur dalam minit. Alamat ada tetapi laluan lalai tiada ialah tanda masalah pengiklanan. Jika alamat juga tiada, pautan, maklumat awalan atau pengesanan alamat pendua perlu dikejar dahulu.
Mengapa penghantaran mematikan pemprosesan RA
RA ialah paket ICMPv6 jenis 134, dihantar daripada sumber link-local dengan had hop 255. Sebelum kernel menggunakannya, ia merujuk accept_ra antara muka. Nilai lalai ialah 1, dan 1 tidak bermaksud ya. Ia bermaksud: terima hanya selagi hos ini tidak menghantar. Tetapkan forwarding=1 dan syarat itu gagal, jadi pengiklanan digugurkan sebelum sebarang awalan atau penghala lalai di dalamnya dipertimbangkan.
Terdapat tiga nilai, dan hanya yang ketiga bertahan daripada penghantaran:
accept_ra | forwarding=0 | forwarding=1 |
|---|---|---|
| 0 | ignored | ignored |
| 1 (default) | accepted | ignored |
| 2 | accepted | accepted |
Dua bendera lain menentukan apa yang sebenarnya dipasang. accept_ra_defrtr mengawal sama ada penghala lalai dalam pengiklanan menjadi laluan, dan accept_ra_pinfo mengawal sama ada maklumat awalan digunakan untuk konfigurasi alamat. Mematikan accept_ra_defrtr ialah cara biasa untuk mengekalkan alamat SLAAC pada hos yang menghantar tanpa mempelajari laluan lalai. Ia tuas yang berbeza daripada accept_ra, dan itulah yang digunakan apabila anda mahu alamat tetapi bukan laluan. Rujukan kernel untuk IP sysctl menyenaraikan ketiga-tiganya.
Sahkan dengan tiga arahan
Pertama, baca nilai langsung dan bukannya fail yang anda sangka dimuatkan:
sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtrKedua, buktikan bahawa pengiklanan masih datang. Menapis mengikut bait jenis ICMPv6 sudah memadai, dan ia mengelakkan pembacaan dinding trafik penemuan jiran:
tcpdump -ni eth0 'icmp6 and ip6[40] == 134'Jika tiada apa muncul selama beberapa minit, accept_ra bukan masalah anda. Huluan berhenti mengiklankan, sesuatu di laluan menapis ICMPv6, atau antara muka itu memang tidak berada pada segmen yang anda sangka. Ketiga, minta pengiklanan sendiri dan baca medannya:
rdisc6 eth0rdisc6 terdapat dalam pakej ndisc6 pada Debian dan Ubuntu. Dalam output, lihat hayat penghala dan keutamaan sebelum mengubah apa-apa yang lain. Pengiklanan dengan hayat penghala 0 ialah arahan untuk membuang penghala lalai, dan tiada nilai accept_ra menjadikannya laluan yang boleh digunakan. Dengan cara ini juga anda menangkap CPE huluan dalam mod jambatan yang mengagihkan awalan tetapi tidak pernah menawarkan dirinya sebagai penghala.
Jadikan uplink satu-satunya antara muka yang permisif
Jika huluan sepatutnya menjadi penghala lalai, terima pengiklanan di sana walaupun penghantaran aktif, dan tidak di tempat lain:
# /etc/sysctl.d/60-ipv6-router.conf
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.accept_ra_defrtr = 1Pengehadan itu penting kerana penghantaran IPv6 di Linux ialah satu suis global, bukan satu bagi setiap pautan. Tulis 1 ke net.ipv6.conf.wg0.forwarding dan kemudian baca net.ipv6.conf.all.forwarding: nilai global terbalik dan setiap antara muka mula menghantar. Anda tidak boleh menjadi penghala pada terowong dan hos biasa pada LAN. Yang boleh anda hadkan ialah penerimaan. Kekalkan accept_ra=2 pada uplink dan biarkan antara muka terowong dan LAN pada 1 atau 0, supaya pengiklanan sesat yang tiba melalui terowong tidak boleh memasang laluan lalai yang menunjuk ke dalamnya.
sysctl -w sementara tidak akan bertahan selepas but semula seterusnya, dan kedua-dua systemd-networkd serta NetworkManager menulis nilai-nilai ini daripada konfigurasi mereka sendiri. Dalam networkd, tetapkan IPv6Forwarding=yes dan IPv6AcceptRA=yes dalam fail .network uplink; networkd mendokumenkan IPv6Forwarding sebagai global atas sebab kernel yang sama. Dengan NetworkManager, ipv6.method=auto pada uplink itulah yang memacu nilai accept_ra, jadi baca semula sysctl selepas nmcli connection up dan bukannya mempercayai pemeriksaan pertama.
Alternatif statik, ip -6 route add default via fe80::1 dev eth0, memang berfungsi, dan ia jawapan yang munasabah apabila penghala huluan mempunyai alamat link-local yang stabil. Ketahui dengan jelas apa yang anda lepaskan. Laluan lalai statik tidak pernah diperbaharui dan tidak pernah ditarik balik, jadi ia terus menunjuk kepada jiran yang mati selepas huluan diganti. Laluan RA gagal dengan selamat; yang statik gagal secara senyap.
Uji paket yang dihantar, bukan paket get laluan itu sendiri
Ping get laluan sendiri boleh berjaya pada laluan yang tiada klien boleh gunakan, dan ia juga boleh berjaya kerana get laluan ialah sumbernya. Uji daripada klien yang bersambung, kemudian tanya get laluan apa yang akan dilakukannya untuk alamat klien itu:
# on the VPN client
ping -6 -c 3 2001:4860:4860::8888
# on the gateway, using a client address
ip -6 route get 2001:4860:4860::8888 from fd42:20::2Kemudian tunggu satu hayat penghala dan lihat sekali lagi. Keadaan stabil yang anda mahukan ialah laluan lalai bertanda proto ra yang nilai expires-nya sentiasa ditetapkan semula, tambah all.forwarding=1. Jika expires hanya mengira detik ke bawah, pengiklanan masih digugurkan di suatu tempat, dan punca biasa ialah pengurus rangkaian yang menulis ganti accept_ra selepas sysctl semasa but sudah dijalankan.
Sebelum menutup perkara ini, sahkan empat perkara: laluan lalai ialah proto ra dan diperbaharui, accept_ra=2 hanya terpakai pada uplink, penghantaran masih 1 selepas but semula dan selepas pengurus dimulakan semula, dan klien, bukan get laluan, yang menyelesaikan ping IPv6. Jika klien masih gagal dengan laluan yang sihat, suspek seterusnya ialah laluan balik atau firewall huluan, bukan pengiklanan.