VM이 호스트 VPN을 쓰는가? 게스트 안에서 검증하라
호스트의 출구 주소는 게스트의 라우트에 대해 아무것도 말해 주지 않는다. 네트워크 모드를 기록하고, 게스트의 라우트와 리졸버를 확인한 뒤 실패 상황을 시험하라.
호스트의 공인 IP를 확인했더니 VPN이 보였고, 그래서 VM도 보호된다고 결론 내린다. 그 결론은 이 검증으로 뒷받침되지 않는다. 게스트는 자체 라우팅 테이블과 자체 리졸버, 자체 인터페이스를 가진다, 그리고 호스트의 출구 주소는 그것들에 대해 아무것도 말해 주지 않는다.
검증은 게스트 내부에서 실행되어야 하고, 무엇을 측정했는지 밝혀야 한다.
호스트 브라우저가 아니라 게스트 내부에서 시작하라
먼저 하이퍼바이저의 네트워크 모드를 기록하라. NAT, 브리지, 호스트 전용, macvtap 중 하나다. NAT 모드에서는 호스트가 게스트의 트래픽을 라우팅하므로, 클라이언트가 라우트를 어떻게 설치하느냐에 따라 호스트의 터널이 적용될 수도 있고 아닐 수도 있다. 브리지 모드에서는 게스트가 물리 LAN의 피어이고 호스트의 터널은 무관하다. 이 두 모드는 같은 호스트 설정에서 정반대의 답을 낸다.
무엇이든 바꾸기 전에 모드를 적어 두라. 결과가 무엇을 의미할 수 있는지를 결정하는 것이 바로 그 모드다.
목적지를 아는 요청을 하나 보내라
자신이 본 출발지 주소를 알려 주는 서비스에 무해한 요청을 보낸다. 그다음 그 목적지에 대한 게스트 자체의 라우팅 결정을 확인하라. ip route get 203.0.113.5는 게스트가 사용할 인터페이스와 게이트웨이를 출력한다.
인터페이스가 게스트의 일반 NIC라면, 그 트래픽은 게스트 내부의 터널을 지나지 않는다.
두 번째 어댑터, 프록시 설정, 게스트 쪽 VPN 클라이언트는 한 애플리케이션의 답을 바꾸면서 다른 애플리케이션의 답은 바꾸지 않을 수 있다. 셸에서 보내는 일반적인 요청이 아니라 실제로 중요한 애플리케이션을 시험하라.
리졸버는 따로 확인하라
출구 주소가 바뀌었다고 해서 어느 리졸버가 그 호스트 이름을 처리했는지는 알 수 없다. 플랫폼에 맞는 도구로 이름을 명시적으로 질의하고, 어느 서버가 응답했는지 기록하라. Split DNS란 리졸버 질문과 라우팅 질문의 답이 서로 다르다는 뜻이다.
이 둘은 어느 방향으로든 어긋날 수 있고, 그 어긋남이 실제 버그인 경우가 많다.
systemd 호스트에서는 resolvectl query가 응답 뒤에 있는 인터페이스와 DNS 서버를 알려 준다. 오래된 구성에서는 서버가 dig 출력에 나타난다. 어느 쪽이든 핵심은 응답이 도착했는지가 아니라 어느 서버가 응답했는지를 보는 것이다.
성공만이 아니라 실패 정책을 시험하라
터널 밖으로 트래픽이 전혀 나가지 않아야 한다는 것이 요구 사항이라면, 요청이 성공했다는 사실은 아무것도 증명하지 못한다. 클라이언트가 지원하는 통제된 실패 시험을 사용하라. 지원되는 방식으로 터널을 멈추고 새 게스트 요청이 차단되는지 확인하라. 호스트 클라이언트의 kill switch가 모든 가상 포워딩 구성까지 포괄한다고 가정하지 마라. 문서화된 범위만이 신뢰할 수 있는 근거다.
터널이 끊겼을 때 물리 NIC로 되돌아가는 게스트는 NAT 모드가 허용하는 바로 그 동작을 하는 것이다.
모드와 범위를 기록하라
하이퍼바이저 모드, 게스트 인터페이스와 라우트, 리졸버, 그리고 시험한 애플리케이션을 적어라. 날짜도 더하라. 스냅샷 복원이나 하이퍼바이저 업데이트로 이 네 가지가 모두 바뀔 수 있기 때문이다.
IPv4가 터널을 따랐다면 그렇게 말하라. 그 주장을 IPv6, 다른 네임스페이스, 다른 네트워크의 다른 VM으로 확장하지 마라.