서버는 경로를 밀어 넣었다고 하고, 클라이언트는 연결되었다고 하며, 목적지는 여전히 도달할 수 없다. 바로 이 그림을 만드는 세 가지 원인이 있다. 장치가 존재하기 전에 경로 추가가 실행되었거나, 클라이언트에 테이블을 바꿀 권한이 없었거나, 정책이 클라이언트에게 밀어 넣은 옵션을 무시하라고 지시한 것이다.

밖에서 보면 똑같아 보이지만 필요한 수정은 다르다. 경로 결정이 내려지는 지점에서 클라이언트 로그를 읽어라.

경로가 고장 난 것이 아니라 없다는 것을 증명하라

경로가 고장 난 것이 아니라 없다는 것을 증명하는 것으로 시작하라. Linux에서는 ip route show dev tun0 가 클라이언트가 터널 장치에 설치한 내용을 나열한다. Windows에서는 route print 또는 Get-NetRoute 가 같은 내용을 표 형식으로 보여 준다.

존재하지만 트래픽을 전달하지 않는 경로는 다른 문제다. 그것은 조사를 경로 설치가 아니라 전달과 방화벽 규칙으로 옮긴다.

타이밍: 장치가 존재하기 전에 추가가 실행되었다

클라이언트는 제어 채널이 올라오고 인터페이스를 구성한 뒤에 서버의 PUSH_REPLY 를 분석한다. 그때서야 플랫폼이 제공하는 방식으로 라우팅 테이블을 건드린다. Linux는 netlink를 거치고, Windows는 승격된 토큰이 필요한 API를 사용한다. 구성을 읽자마자 경로를 추가하는 스크립트나 클라이언트는 TUN/TAP 장치가 생기기 전에 실행될 수 있고, 커널은 그 추가를 거부한다.

같은 경쟁이, 입력할 때쯤이면 인터페이스가 이미 올라와 있기 때문에 손으로 입력한 경로는 작동하고 자동 경로는 작동하지 않는 이유를 설명한다.

이런 경우를 위해 route-delay 가 있고, route-up 는 인터페이스와 경로가 구성된 뒤에 실행되는 스크립트를 지정한다. 터널 주소에 의존하는 경로는 이른 단계가 아니라 그 훅에 두어라.

권한: 누가 테이블을 바꿀 수 있는가

Windows 라우팅 테이블을 바꾸려면 승격된 토큰이 필요하다. 표준 사용자가 시작한 GUI는 서비스를 통해 어댑터 주소를 설정할 수 있어도 경로를 추가하지 못할 수 있다. 그러면 로그는 푸시가 없는 대신 접근 거부 형태의 오류를 보여 준다.

GUI를 관리자로 시작하거나 서비스 기반 클라이언트를 사용하면 그 결과가 달라진다. 필요한 토큰 없이 클라이언트를 시작하는 예약 작업은 그렇지 않다.

무엇이든 바꾸기 전에 클라이언트가 실제로 어떤 계정으로 실행되는지 확인하라. 버전과 서비스 모드가 어떤 원인이 가능한지를 결정하므로 둘 다 경로 출력 옆에 기록하라.

정책: 밀어 넣은 경로는 의도적으로 버려질 수 있다

route-nopull 는 터널 주소는 계속 받아들이면서 서버가 밀어 넣는 경로(밀어 넣은 기본 경로 포함)를 클라이언트가 무시하게 만든다. 밀어 넣은 DNS와 DHCP 옵션도 같은 지시로 버려진다. 그런 클라이언트는 결함이 아니라 자기 구성에 명시적인 경로 줄을 기대하는 것이다.

route-noexec 는 다른 제어로, 클라이언트가 경로 변경을 아예 실행하지 못하게 한다. 클라이언트가 매핑할 수 없는 토폴로지도 비슷한 결과를 낼 수 있으며, 경로는 추가된 것이 아니라 거부된 것으로 기록된다. 세 가지 중 어느 것이 적용되는지 추측하는 대신 결정을 보고하는 로그 줄을 읽어라. 그다음, 가져오기 도구나 관리 도구가 사용자가 편집한 적 없는 옵션을 추가했을 수 있으므로 유효 프로필을 확인하라.

텍스트 편집기에서 깨끗해 보이는 프로필도 실행 시 추가된 지시를 담고 있을 수 있다.

푸시 목록을 테이블과 비교하라

연결한 뒤 서버의 푸시 목록을 클라이언트 테이블 옆에 두어라. Linux에서는 ip route show dev tun0 이고, Windows에서는 route print 또는 Get-NetRoute 이다. 경로가 없으면 먼저 설치를 고쳐라. 경로가 있는데 트래픽이 실패하면 전달과 방화벽 정책으로 넘어가라.

클라이언트 버전, 실행 계정, 서비스 기반 여부를 기록하라. 이 세 가지 사실이 어떤 원인이 배제되었는지를 다음 사람에게 알려 준다.

관련 글