IPv6 트래픽은 VPN을 거쳐야 할까요, 아니면 직접 가야 할까요?
터널 안에 ::/0을 넣을지 세 가지 조건으로 결정하세요: 출구 지원, 엔드포인트 도달 가능성, 로컬 전용 네트워크.
지난달 두 사람이 저에게 정반대의 결과를 요청했습니다. 한 명은 IPv6가 VPN으로 덮이기를 원했고, 다른 한 명은 사무실 프린터가 계속 작동하기를 원했습니다. 단일 ::/0 경로로는 둘 다를 스스로 충족할 수 없습니다. 그 경로가 터널 안에 속하는지는 세 가지 조건에 달려 있으며, 첫 번째 조건이 대부분의 상용 출구에서 그것을 배제합니다. 출구가 IPv6를 나르지 않는다면, 기본 경로를 그쪽으로 보내는 것은 보낼 곳이 없는 터널 속에 트래픽을 숨기는 것입니다.
세 가지 조건이 답을 결정한다
기본 경로는 한 줄이며 ::/0 이고, 더 구체적인 경로가 없는 모든 IPv6 목적지와 일치합니다(RFC 4291). 설치하는 것은 쉽습니다. 그것을 해야 하는지 결정하는 것은 세 가지 조건으로 귀결됩니다.
조건 하나: 연결하는 출구에 작동하는 IPv6가 있고 그것을 전달할 준비가 되어 있어야 합니다. 조건 둘: 클라이언트가 터널 엔드포인트까지 경로를 유지할 수 있어야 하며, 엔드포인트는 보통 라우팅하려는 범위 안에 있습니다. 조건 셋: 터널 밖에 있어야 할 로컬 IPv6 목적지를 지목할 수 있어야 합니다.
각 조건은 저마다의 방식으로 실패하므로, 추측에는 저녁 한 나절이 듭니다. 실패한 조건 하나는 침묵과 올바르게 보이는 라우팅 테이블을 남깁니다. 실패한 조건 둘은 시작 몇 초 만에 핸드셰이크를 죽입니다. 실패한 조건 셋은 작동하는 터널과 프린터 옆의 불만스러운 동료를 남깁니다.
| What you see | Decision |
|---|---|
| Exit answers IPv6 probes, no local IPv6 devices to protect | Route ::/0 into the tunnel |
| Exit answers IPv6 probes, printer or NAS reachable by a global address | Route ::/0, then give those prefixes a route of their own |
| Exit is IPv4-only inside the tunnel | Do not route ::/0; block IPv6 on the client |
Endpoint is reached over IPv6 and sits inside ::/0 | Install a host route for the endpoint first |
출구가 정말 IPv6를 나르는가?
IPv6 주소가 있는 터널 인터페이스는 반대편에 대해 아무것도 증명하지 않습니다. 많은 상용 프로필은 내부가 IPv4뿐입니다. 서버는 v4 주소를 주고 나머지는 모두 버립니다. 그 위에 AllowedIPs 에서 기본 경로를 설치하면, 커널은 상대방이 결코 보지 못하는 인터페이스로 IPv6를 기꺼이 보냅니다.
터널이 올라와 있는 동안 클라이언트에서 시험하세요. ping -6 -c 3 2001:4860:4860::8888 와 ip -6 route get 2001:4860:4860::8888 는 서로 다른 질문에 답합니다. 응답이 돌아오는지, 그리고 커널이 어느 장치를 골랐는지입니다. 후자가 당신의 터널을 지목하고 전자가 아무것도 돌려주지 않는다면, 문제는 경로가 아니라 출구입니다.
출구를 직접 운영한다면 클라이언트 시험은 통과해도 경로가 막다른 곳에서 끝날 수 있습니다. 게이트웨이에서 net.ipv6.conf.all.forwarding=1 가 켜져 있고 방화벽이 터널에서 전달된 패킷을 받아들이는지 확인하세요. 전달을 거부하는 출구로 올바르게 라우팅된 패킷은 클라이언트 쪽에서 정확히 라우팅 버그처럼 보입니다.
클라이언트가 엔드포인트까지 경로를 유지할 수 있는가?
이것이 IPv6 전용 WireGuard 엔드포인트를 가진 노트북에서 저를 붙잡은 사례입니다. 엔드포인트 주소는 평범한 전역 주소이므로 ::/0 안에 들어갑니다. 전체 프리픽스를 인터페이스로 라우팅하면, 핸드셰이크 패킷은 아직 만들려는 터널 속으로 스스로를 몰아넣습니다. 터널은 결코 올라오지 않고, 클라이언트 출력에는 이유가 나오지 않습니다.
wg-quick 가 Linux에서 이것을 처리합니다. AllowedIPs 에서 경로를 도출해 자체 테이블에 설치하고, 엔드포인트로 가는 트래픽이 먼저 메인 테이블로 해석되도록 정책 규칙을 추가합니다. 바로 suppress_prefixlength 0 규칙이며, ip -6 rule 에서 찾을 수 있습니다. 그래서 wg-quick up 는 손으로 쓴 ip -6 route add default dev wg0 가 연결을 끊는 곳에서 성공합니다.
터널을 올리기 전과 후에 ip -6 route get <endpoint-v6> 로 두 상태를 모두 확인하세요. 답이 터널 장치로 바뀐다면, 터널에 필요한 경로를 제거한 것입니다. 경로를 직접 작성할 때는 원래 게이트웨이를 통해 엔드포인트로 가는 호스트 경로를 추가하거나, IPv4로 엔드포인트에 연결하고 IPv6는 페이로드에 맡기세요.
무엇이 터널 밖에 남아야 하는가?
더 구체적인 경로가 기본 경로를 이기므로, 링크상의 프리픽스나 자체 경로가 있는 ULA 범위는 추가 수고 없이 계속 작동합니다. 이것이 많은 전체 터널 IPv4 구성이 살아남는 조용한 이유입니다. LAN 프리픽스는 기본 경로보다 구체적이어서 터널에 절대 들어가지 않습니다.
로컬 장치가 전역 주소로 도달 가능할 때 깨집니다. 같은 라우터가 공인 프리픽스를 준 프린터, NAS, 텔레비전에서 흔한 일입니다. 그 주소들은 ::/0 와 일치하고 다른 무엇과도 일치하지 않으므로, 나머지와 함께 터널로 옮겨가 사라집니다.
프로토콜이 아니라 목적지별로 결정하세요. 로컬 호스트 두세 대가 중요하다면 그 프리픽스에 물리 인터페이스로 나가는 경로를 주거나, 협상된 집합에서 빼세요. 목록이 계속 늘어난다면 정직한 답은 서면 예외 목록을 갖춘 IPv6용 분할 터널링이며, 계속 덧대는 기본 경로가 아닙니다.
답이 아니오라면 차단하라
IPv6를 경로 없이 두는 것은 그것을 그냥 두는 것과 같지 않습니다. 작동하는 IPv6 기본 경로가 있는 호스트는 터널이 IPv4를 나르는 동안에도 그것을 계속 사용하므로, 트래픽은 VPN 옆으로 나가고 IPv6를 선호하는 모든 서비스가 실제 주소를 봅니다. 그것은 누출이며, 분할 터널이 아닙니다.
하나를 고르고 어느 것을 골랐는지 적어 두세요. 기본 경로를 라우팅하고 위의 절충을 받아들이거나, 터널이 유지되는 동안 IPv6를 비활성화하세요. AllowedIPs 에서 프리픽스를 빼는 것만으로는 충분하지 않습니다. 운영체제가 자체 기본 경로를 유지하기 때문입니다. Linux에서는 거친 버전이 sysctl -w net.ipv6.conf.all.disable_ipv6=1 이고, 더 섬세한 버전은 방화벽 규칙으로 IPv6를 터널 밖으로 떨어뜨립니다. 휴대전화 클라이언트에는 같은 일을 하는 명시적 IPv6 차단 토글이 있습니다.
누출처럼 검증하라
터널을 올리고 토글을 믿는 대신 상태를 읽으세요. ip -6 route show default 은 기본 경로 하나를 보여야 하고, LAN 밖 목적지에 대해 ip -6 route get 는 터널 장치를 지목해야 합니다. 연결이 끊긴 뒤 둘 다 반복하세요. 터널보다 오래 사는 기본 경로가 바로 찾던 버그입니다.
그다음 반대 방향을 시험하세요. 로컬 네트워크의 호스트에서 클라이언트의 로컬 IPv6 주소로 도달하세요. 그것이 작동을 멈춘다면, 당시 라우팅 테이블이 무엇을 주장했든 조건 셋은 결코 충족되지 않았습니다.
결과를 다음 사람이 찾을 곳에 쓰세요. 어떤 프리픽스가 로컬로 남는지, 왜인지, 연결이 끊긴 뒤 클라이언트가 무엇을 하는지. runbook의 두 줄이 다음 엔지니어가 자정에 엔드포인트 루프를 다시 발견하는 일을 막아 줍니다.