패킷이 노트북을 떠나 VPN 게이트웨이에 닿지 않는데 방화벽 카운터는 전혀 움직이지 않는다. 라우팅 테이블이 이미 패킷의 운명을 결정했다. blackhole 항목이 일치했고 커널이 어떤 인터페이스도 보기 전에 패킷을 버린 것이다. 이 동작은 목적지가 닫힌 상태로 실패해야 할 때 유용하지만, 범위가 좁은 라우팅 동작이다. 이를 완전한 킬 스위치로 취급하는 것이 설계가 틀어지는 지점이다.

버리기 동작이 실제로 일치시키는 것

경로 조회는 테이블을 고르고, 그 안에서 가장 긴 일치 프리픽스를 고른다. blackhole 경로는 동작이 버리기인 일반 항목이므로, 전체 결정을 거친 뒤 그 항목을 선택했을 패킷에만 영향을 준다. 정책 규칙으로 테이블을 바꾸거나 더 구체적인 프리픽스를 추가하면 버리기는 더 이상 적용되지 않는다.

그래서 blackhole의 범위는 정확하고 설명하기 쉽다. 해당 주소 패밀리에 대해 테이블 안의 프리픽스를 덮는다. 다른 테이블이 이길 목적지는 덮지 않고, IPv4 프리픽스를 버린다는 이유만으로 IPv6를 덮지도 않는다.

ip route get 는 무엇이든 배포하기 전에 테이블과 경로 유형을 포함한 결정을 보여준다. 그 출력을 읽는 것이 실패한 요청에서 어느 규칙이나 프리픽스가 작동했는지 추론하는 것보다 빠르다.

blackhole은 unreachable이나 prohibit와 같지 않다

리눅스는 버리기와 비슷한 세 가지 경로 유형을 제공하며, 송신자가 관찰하는 내용이 서로 다르다. blackhole은 응답 없이 패킷을 버리므로 클라이언트는 시간 초과를 본다. unreachable 경로는 ICMP unreachable 메시지를 반환하므로 연결이 호스트 또는 네트워크 오류로 빠르게 실패한다. prohibit 경로는 관리적 금지 오류를 반환하며, 의도적인 정책 거부에 더 가깝다.

애플리케이션에 보여 주고 싶은 동작을 고르라. 정책을 드러내고 싶지 않을 때는 조용한 버리기가 적절하고, 사용자가 목적지를 쓸 수 없는 이유를 이해해야 할 때는 즉각적인 오류가 낫다. 네트워크 전반에서 유형을 섞으면 같은 정책을 세 가지 다른 장애로 설명하는 지원 티켓이 생긴다.

연결을 진단할 때 모든 버리기 항목이 서로 바꿔 쓸 수 있다고 가정하지 말라. 오류 문구, 시점, 패킷 캡처가 다르고 테이블의 경로 유형이 어느 것을 보고 있는지 알려 준다. ip-route 설명서에는 유형과 오류 시 동작이 나열되어 있다.

킬 스위치와의 비교

킬 스위치는 패킷 필터링이다. 터널 밖으로 나갈 송신 트래픽을 버리는 방화벽 규칙이다. blackhole 경로는 스택에서 더 이른 단계에 내려지는 포워딩 결정이다. 둘 다 트래픽을 막을 수 있지만 보는 것이 다르고 놓치는 경우도 다르다.

MechanismWhat it blocksWhat it missesHow failure looks
Blackhole routeDestinations matching the prefix and tableOther tables, other address families, traffic with a different routeSilent timeout
Firewall kill switchEgress not bound to the tunnel interfaceRules that are too broad can break the endpoint or DHCPDropped packets with counters
WireGuard AllowedIPsDestinations not routed into the interfaceTraffic that never enters the interface at allNo tunnel route, direct egress

비교가 중요한 지점은 적용 범위다. 방화벽은 소유자, 포트, 인터페이스를 일치시켜 엔드포인트를 도달 가능하게 두면서 애플리케이션을 차단할 수 있지만 경로는 그럴 수 없다. 반대로 경로는 패킷 필터를 하나도 올리지 않고 전체 프리픽스를 버리기로 보낼 수 있으며, 이는 최소 시스템에서 유용하다.

WireGuard의 AllowedIPs는 암호 키 라우팅이지 방화벽이 아니다. 어떤 목적지 프리픽스를 인터페이스로 받아들일지 결정하며, 터널 서브넷만 나열한 프로필은 다른 목적지를 일반 기본 경로에 그대로 맡긴다. 그래서 전체 터널 프로필이 0.0.0.0/0을 쓰고, 그래서 wg-quick도 가능할 때 방화벽 규칙을 설치한다.

터널 엔드포인트를 버리기 밖에 두라

엔드포인트의 외부 주소는 물리 인터페이스를 통해 도달 가능하게 남아 있어야 한다. 그 주소까지 잡는 버리기는 핸드셰이크가 나가는 것을 막고 터널은 결코 올라오지 않으며, 이는 라우팅 정책이 아니라 VPN 장애처럼 보인다. 변경 전후로 엔드포인트 경로를 확인하라.

관리 접근도 같은 검토에 속한다. 라우터나 클라이언트로 가는 유일한 길이 터널이라면, 지나치게 넓은 버리기가 그것을 제거할 수 있게 해 줄 머신에서 당신을 잠글 수 있다. 문서화된 대역 외 경로, 콘솔, 또는 시간 제한 롤백을 유지하라.

IPv6는 자체 항목과 자체 검토가 필요하다. IPv4를 blackhole로 보내면서 IPv6를 기본 경로에 남기는 설계는 정책이 막으려던 트래픽을 그대로 유출하며, 그 실수는 IPv4만 시험하는 테스트에서 보이지 않는다.

타이머와 롤백으로 단계적으로 적용하라

짧은 자동 제거와 함께 경로를 적용해 실수가 재부팅을 넘어 남지 않게 하라. 아래 명령은 문서용 대역을 사용한다. 설계가 실제로 버리는 프리픽스로 바꿔라.

sudo ip route replace blackhole 10.0.0.0/8
ip route get 10.1.2.3
sudo systemd-run --on-active=60 /sbin/ip route del blackhole 10.0.0.0/8

두 번째 명령은 blackhole 경로와 그것이 나온 테이블을 보고해야 한다. 세 번째는 일 분 뒤 제거를 예약하며, 정책을 확인하기에 충분한 시간이고 원격 호스트에서 실수에서 복구하기에 충분히 짧다. 동작이 확인되면 다른 경로를 소유한 같은 구성 관리로 항목을 영구적으로 만들어라.

프리픽스, 테이블, 주소 패밀리, 롤백 방법을 기록하여 변경을 마무리하라. 버리기는 라우팅 설계에서 의도적인 예외이며, 다음 엔지니어는 그것이 여전히 필요한지 결정하기 전에 어떤 트래픽을 막기 위한 것인지 알아야 한다.

관련 글