연결할 때마다 입력하는 경로는 그 순간을 해결할 뿐 한 주를 해결하지 못한다. macOS에서 지속적인 선택은 보통 VPN 서비스와 함께 저장된 프리픽스이며, 서비스가 연결할 때마다 그것을 다시 설치하고 내려가면 제거하기 때문이다. 대안은 시험용 일시적 route add와 협상 후에만 알 수 있는 주소를 위한 연결 훅이다.

경로가 서비스에 속하는지 세션에 속하는지 결정한다

프리픽스가 무엇에 의존하는지 물어라. 네이티브 VPN 서비스 뒤의 고정 사설 네트워크라면 경로는 그 서비스에 속한다. 연결마다 바뀌는 피어 주소에 의존한다면 훅이나 상태 기반 작업이 더 나은 소유자일 수 있다. 다음 오 분 동안만 경로를 확인한다면 일시적 경로로 충분하다.

서비스에 묶인 경로가 가장 깨끗한 수명 주기를 가진다. 서비스와 함께 나타나고 서비스가 연결되지 않으면 사라지므로, 가리키는 터널보다 오래 살 수 없다. 그 속성은 한 줄 명령의 편리함보다 값지다.

세션에 묶인 경로는 인터페이스에 속하며 그 번호는 예고 없이 바뀐다. 재연결은 이전 세션이 쓴 것과 다른 utun 이름을 터널에 줄 수 있고, 그러면 하드코딩된 명령이 아무것도 가리키지 않거나 더 나쁘게는 다른 터널을 가리키는 경로가 된다.

현재 경로와 서비스 상태를 읽는다

시스템이 실제로 사용하는 이름부터 시작한다. 네트워크 설정의 서비스 이름이 아래 명령의 식별자이고, 현재 경로 표는 연결된 클라이언트가 무엇을 설치했는지 보여 준다. 터널이 올라와 있는 동안 둘 다 읽는다.

scutil --nc list
networksetup -listnetworkserviceorder
netstat -rn | head -30
route get 10.20.5.5

그 조회는 커널이 지금 이 주소에 대해 어떤 게이트웨이와 인터페이스를 고를지 보여 준다. 이미 터널을 고른다면 프리픽스가 덮여 있고 새 경로는 중복일 것이다. 로컬 라우터를 고른다면 터널에 그 프리픽스가 없는 것이다.

연결된 동안 피어 주소를 적어 둔다. 그것이 서비스에 묶인 경로의 게이트웨이 값이 되며, 보통 netstat -rn에서 터널의 기본 경로에 대해 표시되는 목적지다.

networksetup으로 프리픽스를 저장한다

networksetup 도구는 네트워크 서비스에 추가 경로를 붙이며, OfficeVPN이라는 서비스와 터널 피어를 통해 도달하는 사설 프리픽스의 경우 형식은 다음과 같다.

sudo networksetup -setadditionalroutes OfficeVPN 10.20.0.0 255.255.0.0 10.8.0.6
networksetup -getadditionalroutes OfficeVPN

서비스 이름 뒤의 각 삼중항은 목적지, 그 넷마스크, 게이트웨이로서의 터널 피어를 준다. 한 번의 호출이 여러 프리픽스를 실을 수 있고, 빈 호출은 저장된 목록을 지운다. 읽기 쪽이 검증 단계이며, 목록이 비어 있다면 설정이 생각하는 서비스에 적용되지 않은 것이다.

게이트웨이는 터널 피어여야 하며 물리 라우터가 아니다. 로컬 게이트웨이를 지정하는 경로는 사설 프리픽스를 물리 인터페이스 밖으로 보내는데, 이는 단계만 늘어난 원래의 실패다. 오래된 피어는 올바로 보이는 경로가 결코 트래픽을 나르지 못하는 가장 흔한 이유다. 오래된 메모에서 주소를 복사하지 말고 연결 상태에서 피어를 다시 읽는다.

route add는 시험에만 사용한다

직접 경로는 프리픽스를 영구적으로 만들기 전에 작동함을 증명하는 데 유용하며, 인터페이스 형식은 게이트웨이 조회를 피한다.

sudo route -n add -net 10.20.0.0/16 -interface utun4

경로는 다음 재연결에서 사라지고 오늘 존재하는 인터페이스 번호에 의존한다. 그래서 이것은 진단이지 배포가 아니다. 시험은 되고 서비스에 묶인 경로가 안 된다면 먼저 게이트웨이 값을 비교해야 하며, 그것이 가장 자주 틀리는 필드다.

분할 동작을 강제하려고 VPN의 기본 경로를 바꾸는 조언을 조심하라. 전체 터널을 강제하는 클라이언트는 재연결이나 정책 새로 고침 후 경로를 다시 설치할 수 있으므로 수동 변경은 조용히 되돌려진다. 몇 개의 사설 프리픽스는 라우팅 문제이며, 전체 터널 정책에 맞서 모든 인터넷 트래픽을 로컬로 유지하는 것은 서버 측 결정이다.

주소가 협상될 때만 훅을 고른다

PPP 기반 링크, 예를 들어 L2TP의 경우 macOS는 링크가 설정되면 /etc/ppp/ip-up를 실행한다. 스크립트는 인터페이스 이름과 협상된 로컬 및 원격 주소를 받으므로 서버가 할당한 피어에 의존하는 경로를 추가할 수 있다. 고정 서비스 경로가 표현할 수 없는 바로 그 경우다.

IKEv2와 공급업체 클라이언트는 그 PPP 경로를 전혀 쓰지 않을 수 있으며, 그러면 스크립트는 세션 내내 조용할 수 있다. 그럴 때는 scutil --nc status를 조회하고 상태 변화에 반응하는 launchd 작업이 동등한 메커니즘이며, 약간의 지연이 따른다.

어떤 훅을 쓰든, 멱등하게 만들고 자기가 만든 경로만 제거하게 하라. 터널을 언급하는 모든 경로를 지우는 스크립트는 결국 VPN 서버에 대한 도달 가능성을 유지하는 경로도 지우게 되고, 연결은 성공하는 순간 끊어진다.

사설 목적지, 일반 브라우징, 재연결 또는 절전 주기를 확인하며 마무리한다. 그다음, 이름 확인은 별개의 정책이며 경로가 작동한다고 해서 사설 이름이 확인되는 것은 아니므로 scutil --dns를 점검하라.

관련 글