Поставив net.ipv6.conf.all.forwarding=1 на Debian порта за да може да препраќа сообраќај од VPN клиенти, и околу половина час подоцна машината немаше стандардна рута IPv6. Горниот рутер работеше, link-local соседот се уште одговараше, а uplink се уште ја држеше глобалната адреса. Она што запре беше подготвеноста на јадрото да продолжува да прима router advertisements на тој интерфејс. Рутата не исчезна во мигот кога го внесов 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_raforwarding=0forwarding=1
0ignoredignored
1 (default)acceptedignored
2acceptedaccepted

Други две знамиња одлучуваат што навистина се инсталира. 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 eth0

rdisc6 доаѓа во пакетот 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 во Linux е еден глобален прекинувач, а не еден по врска. Запишете 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, затоа прочитајте sysctl повторно по nmcli connection up наместо да ѝ верувате на првата проверка.

Статичката алтернатива, ip -6 route add default via fe80::1 dev eth0, навистина работи и е разумен одговор кога горниот рутер има стабилна link-local адреса. Бидете јасни за тоа од што се откажувате. Статичната стандардна рута никогаш не се обновува и никогаш не се повлекува, затоа продолжува да покажува на мртов сосед откако горната страна ќе се замени. Рутата од RA откажува безбедно; статичката откажува тивко.

Тестирајте препратен пакет, а не сопствениот на портата

Сопствените пингови на портата можат да успеат на рута што ниту еден клиент не може да ја користи, а можат да успеат и затоа што портата е изворот. Тестирајте од поврзан клиент и потоа прашајте ја портата што би направила за адресата на тој клиент:

# 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 по подигање и по рестарт на менаџерот, и клиент, а не портата, завршува IPv6 пинг. Ако клиентот продолжува да не успева со здрава рута, следниот сомнителен е повратниот пат или горен огнен ѕид, а не објавата.

Поврзани статии