Nastavil jsem net.ipv6.conf.all.forwarding=1 na Debian bráně, aby mohla předávat provoz VPN klientů, a asi za půl hodiny neměl stroj žádnou výchozí trasu IPv6. Upstream router byl v pořádku, link-local soused stále odpovídal a uplink si držel svou globální adresu. Co přestalo, byla ochota jádra nadále přijímat router advertisements na tom rozhraní. Trasa nezmizela ve chvíli, kdy jsem sysctl zadal; zmizela, když vypršela platnost výchozí trasy naučené z RA a nic ji neobnovilo.

Nic nevypadalo na první pohled rozbité. Forwardování fungovalo, klienti procházeli, dokud byla stará trasa v cache, a porucha přišla později než změna, která ji způsobila. Právě kvůli tomu zpoždění se to svádí na upstream nebo na pravidlo firewallu, které s tím nikdy nesouviselo.

Přečtěte si routovací tabulku, než se dotknete jakéhokoli sysctl

Začněte příkazem ip -6 route show default a čtěte atributy, ne jen bránu. Výchozí trasa naučená z RA je označená proto ra, nese preferenci a ukazuje odpočet expires. Trasa přidaná ručně nemá ani jedno, a ten rozdíl vám řekne, který mechanismus trasu vlastní.

$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref medium

Pak se podívejte na adresu: ip -6 addr show dev eth0. Globální adresa s preferovanou a platnou životností v hodinách přežije výchozí trasu, jejíž životnost routeru se měří v minutách. Adresa existuje a výchozí trasa chybí, to je podpis problému s ohlasy. Chybí-li i adresa, musíte nejdřív řešit link, informace o prefixu nebo detekci duplicitních adres.

Proč forwardování vypíná zpracování RA

RA je paket ICMPv6 typu 134, odeslaný z link-local zdroje s limitem skoku 255. Než ho jádro použije, prohlédne accept_ra rozhraní. Výchozí hodnota je 1 a 1 neznamená ano. Znamená: přijímej jen tehdy, dokud tento hostitel nepředává. Nastavte forwarding=1 a tato podmínka selže, takže se ohlás zahodí dřív, než se v něm zváží jakýkoli prefix nebo výchozí router.

Existují tři hodnoty a forwardování přežije jen ta třetí:

accept_raforwarding=0forwarding=1
0ignoredignored
1 (default)acceptedignored
2acceptedaccepted

O dvou dalších příznacích rozhoduje, co se skutečně nainstaluje. accept_ra_defrtr řídí, zda se výchozí router z ohlásu stane trasou, a accept_ra_pinfo řídí, zda se informace o prefixu použijí pro konfiguraci adresy. Vypnutí accept_ra_defrtr je obvyklý způsob, jak na předávajícím hostiteli udržet adresy SLAAC, aniž byste se naučili výchozí trasu. Je to jiná páka než accept_ra a sáhnete po ní, když chcete adresy, ale ne trasu. Reference jádra k IP sysctl uvádí všechny tři.

Ověřte to třemi příkazy

Nejprve si přečtěte živé hodnoty místo souboru, o kterém si myslíte, že je načtený:

sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
       net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtr

Zadruhé dokažte, že ohlasy stále přicházejí. Filtrování podle bajtu typu ICMPv6 stačí a ušetří vám čtení zdi provozu objevování sousedů:

tcpdump -ni eth0 'icmp6 and ip6[40] == 134'

Pokud se během několika minut nic neobjeví, accept_ra není váš problém. Upstream přestal ohlašovat, něco na cestě filtruje ICMPv6, nebo to rozhraní ve skutečnosti není na segmentu, který si myslíte. Zatřetí si vyžádejte ohlás sami a přečtěte jeho pole:

rdisc6 eth0

rdisc6 je v balíčku ndisc6 na Debianu a Ubuntu. Ve výstupu se podívejte na životnost routeru a preferenci, než cokoli dalšího změníte. Ohlás s životností routeru 0 je pokyn k odstranění výchozího routeru a žádná hodnota accept_ra z toho neudělá použitelnou trasu. Také tak zachytíte upstream CPE v režimu mostu, které rozdává prefixy, ale nikdy se nenabídne jako router.

Udělejte z uplinku jediné povolující rozhraní

Pokud má být upstream výchozím routerem, přijímejte tam ohlasy i přes forwardování, a nikde jinde:

# /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

Omezení je důležité, protože IPv6 forwardování je v Linuxu jeden globální přepínač, ne jeden na link. Zapište 1 do net.ipv6.conf.wg0.forwarding a pak přečtěte net.ipv6.conf.all.forwarding: globální hodnota se překlopí a každé rozhraní začne předávat. Nemůžete být router na tunelu a obyčejný hostitel na LAN. Omezit můžete přijímání. Držte accept_ra=2 na uplinku a rozhraní tunelu a LAN nechte na 1 nebo 0, aby zbloudilý ohlás, který dorazí tunelem, nemohl nainstalovat výchozí trasu ukazující do něj.

Dočasné sysctl -w nepřežije další restart a jak systemd-networkd, tak NetworkManager zapisují tyto hodnoty ze své vlastní konfigurace. V networkd nastavte IPv6Forwarding=yes a IPv6AcceptRA=yes v souboru .network uplinku; networkd dokumentuje IPv6Forwarding jako globální ze stejného důvodu v jádru. U NetworkManageru je ipv6.method=auto na uplinku to, co řídí hodnotu accept_ra, takže po nmcli connection up čtěte sysctl znovu, místo abyste věřili první kontrole.

Statická alternativa, ip -6 route add default via fe80::1 dev eth0, opravdu funguje a je rozumnou odpovědí, když má upstream router stabilní link-local adresu. Buďte si jasní v tom, co obětujete. Statická výchozí trasa se nikdy neobnovuje a nikdy neodvolává, takže po výměně upstreamu dál ukazuje na mrtvého souseda. Trasa z RA selhává bezpečně; statická selhává tiše.

Testujte předávaný paket, ne ten od brány

Vlastní pingy brány mohou uspět na trase, kterou žádný klient nemůže použít, a mohou uspět i proto, že brána je zdrojem. Testujte z připojeného klienta, a pak se brány zeptejte, co by udělala pro adresu toho klienta:

# 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

Pak počkejte jednu životnost routeru a podívejte se znovu. Stabilní stav, který chcete, je výchozí trasa označená proto ra, jejíž hodnota expires se stále obnovuje, plus all.forwarding=1. Pokud expires jen odpočítává, ohlasy se někde stále zahazují a obvyklým viníkem je správce sítě, který přepíše accept_ra poté, co sysctl při startu už proběhl.

Než to uzavřete, ověřte čtyři věci: výchozí trasa je proto ra a obnovuje se, accept_ra=2 platí jen pro uplink, forwardování je po restartu a po restartu správce stále 1 a ping IPv6 dokončí klient, ne brána. Pokud klient se zdravou trasou stále selhává, dalším podezřelým je zpáteční cesta nebo upstream firewall, ne ohlás.

Související články