Linux에서 포워딩을 켠 뒤 IPv6 기본 경로가 사라졌다
IPv6 포워딩을 켜면 커널이 업링크의 라우터 광고를 무시하고, 학습한 기본 경로가 만료됩니다. accept_ra로 고치십시오.
VPN 클라이언트 트래픽을 통과시키려고 Debian 게이트웨이에 net.ipv6.conf.all.forwarding=1을 설정했는데, 약 반 시간 뒤 그 장비에는 IPv6 기본 경로가 남아 있지 않았다. 상위 라우터는 살아 있었고, link-local 이웃은 여전히 응답했고, 업링크도 글로벌 주소를 그대로 갖고 있었다. 멈춘 것은 그 인터페이스에서 라우터 광고를 계속 받아들이려는 커널의 태도였다. 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는 134 형식의 ICMPv6 패킷이며, 홉 제한 255로 link-local 출발지에서 전송됩니다. 커널이 그것을 쓰기 전에 인터페이스의 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은 Debian과 Ubuntu에서 ndisc6 패키지에 들어 있습니다. 출력에서 다른 무엇을 바꾸기 전에 라우터 수명과 우선순위를 보십시오. 라우터 수명이 0인 광고는 기본 라우터를 제거하라는 지시이며, 어떤 accept_ra 값도 그것을 쓸 수 있는 경로로 만들지 않습니다. 브리지 모드의 상위 CPE가 프리픽스만 나눠 주고 자신을 라우터로 내놓지 않는 경우도 이렇게 잡힙니다.
업링크만 허용 인터페이스로 만드십시오
상위 쪽이 기본 라우터여야 한다면, 포워딩 중에도 거기서만 광고를 받아들이고 다른 곳에서는 받지 마십시오:
# /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범위를 정하는 것이 중요한 이유는 Linux의 IPv6 포워딩이 링크마다 하나가 아니라 하나의 전역 스위치이기 때문입니다. net.ipv6.conf.wg0.forwarding에 1을 쓰고 나서 net.ipv6.conf.all.forwarding을 읽으면 전역 값이 뒤집히고 모든 인터페이스가 포워딩을 시작합니다. 터널에서는 라우터, LAN에서는 평범한 호스트일 수는 없습니다. 좁힐 수 있는 것은 받아들이는 범위입니다. accept_ra=2을 업링크에 두고 터널과 LAN 인터페이스는 1이나 0으로 두어, 터널로 들어온 길 잃은 광고가 그쪽을 가리키는 기본 경로를 설치하지 못하게 하십시오.
일시적인 sysctl -w은 다음 재부팅까지 가지 못하고, systemd-networkd와 NetworkManager 모두 자기 설정에서 이 값을 씁니다. networkd에서는 업링크의 .network 파일에 IPv6Forwarding=yes과 IPv6AcceptRA=yes을 설정하십시오. networkd가 IPv6Forwarding을 전역으로 적는 것도 같은 커널 쪽 이유입니다. NetworkManager에서는 업링크의 ipv6.method=auto이 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이 줄기만 한다면 광고가 아직 어딘가에서 버려지고 있고, 흔한 범인은 부팅 시점의 sysctl이 이미 실행된 뒤 accept_ra을 다시 쓰는 네트워크 관리자입니다.
마무리하기 전에 네 가지를 확인하십시오. 기본 경로가 proto ra이고 갱신되고 있는지, accept_ra=2이 업링크에만 적용되는지, 재부팅 뒤와 관리자 재시작 뒤에도 포워딩이 1인지, 그리고 IPv6 ping을 게이트웨이가 아니라 클라이언트가 완료하는지. 경로가 건강한데도 클라이언트가 실패한다면 다음 용의자는 반환 경로나 상위 방화벽이며, 광고가 아닙니다.