VPN 피어가 다른 인터페이스로 핑을 보내는 이유는 로컬이기 때문이다
로컬 라우팅 테이블은 호스트가 보유한 모든 주소로 패킷을 보내며, 그 주소가 어느 인터페이스에 있든 상관하지 않는다. 포워딩 설정은 그 경로에 결코 개입하지 않는다.
WireGuard 클라이언트가 연결되어 전혀 다른 인터페이스의 주소로 핑을 보내면 응답이 돌아온다. 캡처에는 요청이 터널에만 나타난다. 고장 난 것은 없고, 신중하게 비활성화한 포워딩 설정은 이와 아무 관련이 없다. 이것은 다이어그램에서는 비슷해 보이지만 커널에서는 완전히 다른 두 경로의 비교다.
한 경로는 다른 누군가를 위해 패킷을 포워딩하고, 다른 경로는 패킷을 호스트 자신에게 전달한다.
호스트로 향한 패킷은 호스트에 머문다
원격 클라이언트는 호스트가 보유한 주소로 IP 패킷을 보낸다. 라우팅은 그 패킷에 대해 한 가지를 묻는다. 이 목적지가 로컬인가? 호스트가 가진 모든 주소는 로컬 라우팅 테이블에 나타나고, 그 테이블은 메인 테이블보다 먼저 조회된다, 그래서 패킷은 다른 인터페이스로 나가지 않고 호스트 자신의 스택으로 간다. 응답은 로컬에서 생성되고, 질의가 그곳에서 왔기 때문에 터널을 통해 돌아간다.
이것이 전부다. 포워딩은 일어나지 않고, 인터페이스 상태 변경도 관여하지 않으며, 해당 주소가 다른 어디선가 도달 가능해야 할 필요도 없다.
ip_forward가 적용되지 않는 이유
포워딩은 도착한 인터페이스와 다른 인터페이스로 나가야 하는 패킷을 다룬다. 호스트 자신으로의 핑은 그 경로를 결코 택하지 않는다. 패킷은 로컬에서 소비되고 응답은 로컬에서 생성된다. 따라서 net.ipv4.ip_forward=0 를 설정해도 여기서는 아무것도 바뀌지 않고, 포워드 체인의 규칙은 그 트래픽을 결코 보지 못한다. 올바른 제어는 입력 경로에 있으며, 들어오는 인터페이스나 출발지로 범위가 정해진다.
그래서 포워딩을 끄고 호스트가 격리되어 있다고 가정하는 것은 잘못된 안도감을 낳는다.
결정한 로컬 테이블을 읽어라
ip rule show 은 보통 최우선 순위의 규칙이 모든 조회를 먼저 로컬 테이블로 보낸다고 보고하고, ip route show table local 는 호스트 자신의 주소를 로컬 범위로 나열한다. 그 테이블에는 관리적으로 내려갔지만 여전히 구성된 인터페이스의 주소도 포함된다. 정적으로 할당된 IPv4 주소는 보통 링크 단절에서도 살아남으며, 그래서 내려간 브리지로의 핑이 여전히 성공해 운영자를 놀라게 할 수 있다.
IPv6는 바로 이 점에서 다르다. 링크가 끊기면 그 주소는 보통 철회되며, keep_addr_on_down 이 설정되어 있지 않은 경우에 그렇다. 하나의 규칙이 둘 다를 덮는다고 가정하지 말고 두 체계를 비교하라.
피어가 실제로 도달하는 것
한 세그먼트에서 라우터 자신의 주소로부터 온 응답은 그 세그먼트 뒤의 머신에 대해 아무것도 말해 주지 않는다. 피어는 이 경로로 다른 인터페이스 뒤의 호스트에 도달할 수 없고, 라우터 자신이 보유한 주소에만 도달한다. 라우터의 주소로 핑하는 대신 별도의 LAN 호스트에서 서비스를 시험하는 것이 포워딩이 애초에 허용되는지를 확인한다.
피어를 터널 주소에 바인딩된 서비스로 제한하는 것은 입력 정책의 문제다. 원하는 서비스를 터널 인터페이스에서 허용하고 그것을 사용할 수 있는 출발지를 제한하라. 패킷이 실제로 그곳에 도착하기 때문이다.
폐기하려던 주소도 확인하라. 인터페이스에서 주소를 제거하는 것이 오래된 주소 위에 방화벽 규칙을 쌓는 것보다 신뢰할 만하다.