مسیر پیشفرض IPv6 پس از فعال کردن ارسال بسته در لینوکس ناپدید شد
وقتی ارسال IPv6 فعال میشود، هسته اعلانهای مسیریاب را در uplink نادیده میگیرد و مسیر پیشفرض یادگرفتهشده منقضی میشود. آن را با accept_ra درست کنید.
net.ipv6.conf.all.forwarding=1 را روی یک دروازه Debian گذاشتم تا بتواند ترافیک کارخواهان VPN را عبور دهد، و حدود نیم ساعت بعد ماشین هیچ مسیر پیشفرض IPv6 نداشت. مسیریاب بالادست فعال بود، همسایه link-local هنوز پاسخ میداد و uplink هنوز نشانی جهانی خود را نگه داشته بود. چیزی که متوقف شده بود، آمادگی هسته برای ادامه پذیرش اعلانهای مسیریاب روی آن رابط بود. مسیر همان لحظهای که sysctl را نوشتم ناپدید نشد؛ زمانی ناپدید شد که عمر مسیر پیشفرض یادگرفتهشده از RA به پایان رسید و چیزی آن را تازه نکرد.
در نگاه اول چیزی خراب به نظر نمیرسید. ارسال بسته کار میکرد، کارخواهان تا وقتی مسیر قدیمی در حافظه نهان بود عبور میکردند، و خرابی دیرتر از تغییری رسید که آن را ایجاد کرده بود. همین تأخیر باعث میشود تقصیر را گردن بالادست یا قاعدهای از دیوار آتش بیندازند که هرگز دخالتی نداشت.
پیش از دست زدن به هر sysctl جدول مسیرها را بخوانید
با ip -6 route show default شروع کنید و ویژگیها را بخوانید، نه فقط دروازه را. مسیر پیشفرض یادگرفتهشده از RA با proto ra علامت خورده، ترجیح دارد و شمارش معکوس expires را نشان میدهد. مسیری که دستی افزودهاید هیچکدام را ندارد، و همین تفاوت میگوید کدام سازوکار مالک مسیر است.
$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref mediumسپس به نشانی نگاه کنید: ip -6 addr show dev eth0. نشانی جهانی با عمر ترجیحی و معتبر که با ساعت سنجیده میشود، بیشتر از مسیر پیشفرضی میماند که عمر مسیریابش با دقیقه سنجیده میشود. وجود نشانی همراه با نبود مسیر پیشفرض، امضای یک مشکل اعلان است. اگر نشانی هم نباشد، نخست باید پیوند، اطلاعات پیشوند یا تشخیص نشانیهای تکراری را پی گرفت.
چرا ارسال بسته پردازش RA را خاموش میکند
RA بستهای از ICMPv6 نوع 134 است که از منبعی link-local با حد پرش 255 فرستاده میشود. پیش از آنکه هسته از آن استفاده کند، accept_ra رابط را بررسی میکند. مقدار پیشفرض 1 است و 1 به معنای بله نیست. یعنی: تنها تا زمانی بپذیر که این میزبان ارسال نمیکند. forwarding=1 را تنظیم کنید و آن شرط برآورده نمیشود، پس اعلان پیش از آنکه هر پیشوند یا مسیریاب پیشفرضی در آن بررسی شود دور ریخته میشود.
سه مقدار وجود دارد و تنها سومی از ارسال بسته جان سالم به در میبرد:
accept_ra | forwarding=0 | forwarding=1 |
|---|---|---|
| 0 | ignored | ignored |
| 1 (default) | accepted | ignored |
| 2 | accepted | accepted |
دو پرچم دیگر تعیین میکنند که واقعاً چه چیزی نصب میشود. accept_ra_defrtr کنترل میکند که آیا مسیریاب پیشفرض در اعلان به مسیر تبدیل میشود، و accept_ra_pinfo کنترل میکند که آیا اطلاعات پیشوند برای پیکربندی نشانی به کار میرود. خاموش کردن accept_ra_defrtr روش معمول نگه داشتن نشانیهای SLAAC روی میزبانی است که ارسال میکند بدون آموختن مسیر پیشفرض. این اهرمی متفاوت از accept_ra است و همانی است که وقتی نشانی میخواهید ولی مسیر نه، به کار میبرید. مرجع IP sysctl هسته هر سه را فهرست میکند.
با سه فرمان تأیید کنید
نخست مقادیر زنده را بخوانید، نه فایلی را که فکر میکنید بارگذاری شده است:
sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtrدوم، ثابت کنید که اعلانها هنوز میرسند. پالایش بر پایه بایت نوع ICMPv6 کافی است و شما را از خواندن دیواری از ترافیک کشف همسایه نجات میدهد:
tcpdump -ni eth0 'icmp6 and ip6[40] == 134'اگر چند دقیقه چیزی پیدا نشد، accept_ra مشکل شما نیست. بالادست اعلان را متوقف کرده، چیزی در مسیر ICMPv6 را پالایش میکند، یا آن رابط واقعاً در بخشی که فکر میکنید نیست. سوم، خودتان یک اعلان بخواهید و فیلدهایش را بخوانید:
rdisc6 eth0rdisc6 در بسته ndisc6 روی Debian و Ubuntu هست. در خروجی، پیش از تغییر هر چیز دیگری عمر مسیریاب و ترجیح را ببینید. اعلانی با عمر مسیریاب 0 دستوری برای حذف مسیریاب پیشفرض است و هیچ مقدار accept_ra آن را به مسیری قابل استفاده تبدیل نمیکند. اینگونه CPE بالادست در حالت پل را هم میگیرید که پیشوندها را پخش میکند اما هرگز خود را مسیریاب معرفی نمیکند.
uplink را تنها رابط سهلگیر کنید
اگر بالادست باید مسیریاب پیشفرض باشد، اعلانها را آنجا با وجود ارسال بسته بپذیرید و جای دیگری نه:
# /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 = 1محدوده مهم است چون ارسال IPv6 در لینوکس یک کلید سراسری است، نه یکی برای هر پیوند. 1 را در net.ipv6.conf.wg0.forwarding بنویسید و سپس net.ipv6.conf.all.forwarding را بخوانید: مقدار سراسری برمیگردد و هر رابط شروع به ارسال میکند. نمیتوانید روی تونل مسیریاب و روی LAN میزبان معمولی باشید. چیزی که میتوانید محدود کنید پذیرش است. accept_ra=2 را روی uplink نگه دارید و رابطهای تونل و LAN را روی 1 یا 0 بگذارید تا اعلان سرگردانی که از تونل میرسد نتواند مسیر پیشفرضی به داخل آن نصب کند.
sysctl -w موقت از راهاندازی بعدی جان سالم به در نمیبرد و هر دو systemd-networkd و NetworkManager این مقادیر را از پیکربندی خودشان مینویسند. در networkd، IPv6Forwarding=yes و IPv6AcceptRA=yes را در فایل .network مربوط به uplink تنظیم کنید؛ networkd به همان دلیل هسته، IPv6Forwarding را سراسری مستند میکند. در NetworkManager، ipv6.method=auto روی uplink همان چیزی است که مقدار accept_ra را میراند، پس پس از nmcli connection up دوباره sysctl را بخوانید و به بررسی نخست اعتماد نکنید.
جایگزین ایستا، ip -6 route add default via fe80::1 dev eth0، واقعاً کار میکند و پاسخ معقولی است وقتی مسیریاب بالادست نشانی link-local پایدار دارد. روشن باشید چه چیزی را از دست میدهید. مسیر پیشفرض ایستا هرگز تازه نمیشود و هرگز پس گرفته نمیشود، پس پس از تعویض بالادست همچنان به همسایهای مرده اشاره میکند. مسیر RA امن شکست میخورد؛ ایستا بیصدا شکست میخورد.
بستهای را که عبور داده شده بیازمایید، نه بسته خود دروازه را
pingهای خود دروازه میتوانند روی مسیری موفق شوند که هیچ کارخواهی نمیتواند از آن استفاده کند، و میتوانند موفق شوند چون دروازه منبع است. از یک کارخواه متصل بیازمایید و سپس از دروازه بپرسید برای نشانی آن کارخواه چه میکند:
# 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::2سپس یک عمر مسیریاب صبر کنید و دوباره نگاه کنید. وضعیت پایداری که میخواهید مسیر پیشفرضی با علامت proto ra است که مقدار expires آن پیوسته از نو تنظیم میشود، بههمراه all.forwarding=1. اگر expires فقط شمارش معکوس میکند، اعلانها هنوز جایی دور ریخته میشوند و مقصر معمول مدیر شبکهای است که accept_ra را پس از اجرای sysctl هنگام راهاندازی بازنویسی میکند.
پیش از بستن این پرونده چهار چیز را تأیید کنید: مسیر پیشفرض proto ra است و تازه میشود، accept_ra=2 فقط برای uplink اعمال میشود، ارسال بسته پس از راهاندازی دوباره و پس از راهاندازی دوباره مدیر همچنان 1 است، و کارخواه و نه دروازه یک ping IPv6 را کامل میکند. اگر کارخواه با مسیری سالم همچنان شکست میخورد، مظنون بعدی مسیر بازگشت یا یک دیوار آتش بالادست است، نه اعلان.