내부 이름 하나를 요청할 때 터널이 열리고, 다음 앱이 똑같이 절실할 때는 닫힌 채로 남는다. 이것은 앱의 버그가 아니라 도메인 규칙의 형태다. Apple의 on-demand 구성은 연결을 만들기 위한 조건을 기술하고, 그 조건의 도메인 형태는 패킷 하나가 움직이기 전에 시스템 리졸버에게 질문을 던진다. 늘 뒤섞이는 두 질문이 있다. 터널이 언제 올라와야 하는가, 그리고 존재하는 터널이 무엇을 나르는가. 전자는 트리거이고 후자는 경로와 리졸버 정책이며, 하나의 프로필이 보통 둘 다 같은 payload에 설정하기 때문에 올바른 도메인 규칙도 잘못된 네트워크에 머물게 할 수 있다.

트리거와 트래픽 선택은 다른 계층에 있다

on-demand 규칙은 VPN payload의 on-demand 사전에 산다. 순서가 있는 규칙 목록이며 각 규칙은 동작과 일치 조건 집합을 갖는다. 시스템은 연결성이 바뀌거나 무언가 네트워크에 도달하려 할 때 이를 평가하고, 동작은 터널을 올릴지, 평가할지, 끊을지, 무시할지 결정한다. 이 모든 일은 앱이 소켓을 갖기 전에 플랫폼의 네트워크 계층에서 일어난다.

그다음은 별도의 키 그룹이다. 터널의 IPv4 및 IPv6 설정, 포함 및 제외 경로, DNS 서버 주소, 그리고 iOS와 iPadOS에서 어떤 앱이 터널을 쓸 수 있는지 정하는 앱별 매핑이다. 프로필은 넓은 트리거를 좁은 경로와 짝지을 수도 있고, 좁은 트리거를 기본 경로와 짝지을 수도 있다. 한쪽만 읽으면 다른 쪽이 고장처럼 보인다.

내 연구실 프로필은 내부 도메인 아래 무언가가 요청될 때마다 연결하지만 터널로는 /16 하나만 보낸다. payload에 적힌 대로 정확히 동작하며, 티켓을 만드는 유형의 프로필이기도 하다. 사람들은 연결된 터널이면 트래픽이 그 안에 있다고 가정한다.

도메인 규칙이 실제로 리졸버에 묻는 것

흔히 connect-if-needed라 불리는 규칙의 도메인 형태는 패킷 payload를 검사하지 않고 URL도 보지 않는다. 이름이 해석될 때 시스템은 그것을 규칙의 도메인과 비교하고, 일치하면 그 이름이 터널이 제공하는 DNS 서버로 해석될 수 있는지 묻는다. 터널의 리졸버가 답하면 이름은 내부로 간주되어 연결이 시작된다. 대신 로컬 리졸버가 답하면 이름은 외부로 취급되어 터널이 나타나지 않는다. Apple의 배포 개요는 이를 네트워크 감지 후 연결 평가로 설명한다.

두 가지 결과가 따른다. 프로필은 터널 안의 DNS 서버를 지정해야 한다. 터널 리졸버가 없는 도메인 규칙은 비교할 것이 없으므로 평가가 기대하는 일치를 만들 수 없다. 그리고 조회는 시스템 리졸버에 도달해야 한다. 자체 암호화 DNS를 실행하는 앱이나 브라우저, 로컬에서 응답하는 확장, 리터럴 주소로의 연결은 규칙이 기다리던 이름 해석을 결코 만들어내지 않는다. 내가 보낸 가장 긴 오후 중 하나는 터널 앞의 클라이언트가 DNS over HTTPS를 쓰고 있다는 것을 발견했을 때 끝났다.

캐시도 트리거를 없앤다. 이미 캐시에 있는 이름은 터널을 시작했을 프로브 없이 응답될 수 있어서, 어제 작동하던 규칙이 재부팅 후나 터널이 한동안 올라와 있을 때 실패한다. macOS에서는 sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder가 상태를 재설정하고, iOS에서는 비행기 모드를 껐다 켜거나 기기를 재시작하면 비슷한 깨끗한 상태가 된다.

일치 범위: 이름, 앱, 네트워크

도메인 일치는 여러 유형 중 하나다. 규칙은 인터페이스 유형(Wi-Fi, 셀룰러, Ethernet)과 특정 SSID에도 일치할 수 있고, 앱별 또는 Safari 도메인 항목은 터널을 하나의 워크플로에 묶는다. 이 묶음이 한 앱만 다른 모든 것과 다르게 동작하는 이상한 경험을 설명한다. 다른 앱은 터널 범위 밖이라 터널 아이콘이 연결됨이라고 해도 로컬 경로를 계속 쓴다.

순서는 사람들이 생각하는 것보다 중요하다. 규칙은 순서대로 평가되고 처음 일치하는 것이 동작을 제공하므로, 좁은 도메인 규칙 위에 놓인 넓은 '아무 Wi-Fi에서나 연결' 규칙은 조용히 이겨 도메인 규칙을 테스트할 수 없게 만든다. 도메인 목록을 다시 쓰기 전에 이전 규칙이 이미 일치하지 않았는지 확인하라.

always-on이 단순히 더 엄격한 on-demand 규칙이 아닌 이유도 여기에 있다. always-on 적용은 별도의 배포 모드이며 자체 감독과 관리 요구 사항이 있다. 이름에 반응하는 대신 터널을 열어 둔다. 절대 끊기지 않는 터널이 필요하다면 도메인 규칙은 잘못된 도구다.

고장 난 규칙처럼 보이는 장애

도메인 규칙이 작동하지 않는다는 보고의 대부분은 다섯 곳 중 하나에 해당하며, 그중 마지막 것만이 규칙의 문구다.

What you seeLayerFirst check
Tunnel comes up, internal site still failsroute or resolver after connectnetstat -rn, scutil --dns
Tunnel never comes up for that nametrigger pathfresh lookup, cache flush, private DNS
Tunnel comes up for every appscope, or an earlier rulerule order, per-app mapping
Tunnel drops and will not return on the same Wi-Fiinterface or SSID match, admissioncaptive portal, SSID string, auth prompt
Tunnel returns after you disconnect itprofile ownershipprofiles show

캡티브 포털은 별도의 줄이 필요하다. 호텔과 공항의 Wi-Fi는 규칙이 의존하는 바로 그 조회를 가로챈다. 포털이 기기를 들여보내기 전까지 터널의 DNS 서버에 닿을 수 없고 프로브는 실패하며, 장애는 도메인 철자가 틀린 것처럼 보인다. 인증도 또 다른 조용한 사례다. 규칙은 발동하고 터널은 연결을 시작할 수 있지만, 만료된 인증서나 다른 디스플레이에 나타난 프롬프트에서 연결이 죽는다.

IPv6는 오진하기 쉬운 변형을 만든다. 두 주소 패밀리를 가진 이름이 먼저 AAAA 레코드로 응답될 수 있는 반면, 터널의 경로 목록은 IPv4만 나른다. 한 브라우저는 성공하고 다른 브라우저는 실패하며, 도메인 목록은 전혀 죄가 없다.

실제 요청으로, 이 순서대로 시험하라

추측하기 전에 정책을 읽어라. macOS에서 sudo profiles show -type configuration는 VPN payload를 포함한 설치된 프로필을 출력하고, scutil --nc list는 서비스 상태를 보여 주며, scutil --nc show <service>는 시스템이 쓰는 on-demand 사전을 출력한다. 관리되는 iPhone이나 iPad에서는 같은 payload가 관리 콘솔이나 MDM 보고서에서 온다. 네트워크 로그는 macOS에서 log stream --predicate 'subsystem == "com.apple.networkextension"'로, 전화가 연결되어 있을 때는 기기 콘솔로 볼 수 있다.

다음으로 이 세션에서 아직 조회하지 않은 호스트 이름으로 시험하라. 터널의 DNS 영역에서 내부적으로 해석된다고 아는 이름을 골라 한 번 요청하고 터널이 나타나는지 지켜보라. 같은 조회를 두 번 실행하라. 두 번째 시도는 캐시 경로를 연습하고, 둘의 차이가 트리거가 해석인지 라우팅인지 알려 준다.

터널이 올라온 뒤 두 계층을 따로 검증하라. netstat -rn -f inet와 netstat -rn -f inet6는 각 프리픽스가 어디를 가리키는지 보여 주고, scutil --dns는 리졸버 순서와 어느 인터페이스가 각 리졸버를 소유하는지 보여 주며, nettop -m route는 어느 인터페이스가 바이트를 나른지 보여 준다. 터널이 올라와 있고 리졸버가 올바른데 리소스가 계속 실패하면 규칙 편집을 멈추고 서버 측 권한 부여와 반환 경로를 확인하라.

규칙이 다른 사람의 것일 때

연결을 끊은 뒤 터널이 다시 나타나면 규칙은 보통 앱이 아니라 프로필에 속한다. MDM으로 배포된 구성, 남은 개인 프로필, 또는 다른 클라이언트가 설치한 프로필이다. sudo profiles show -type configuration와 on-demand 키 검색으로 좁힐 수 있고, 제거 경로는 프로필이며 메뉴 막대의 스위치가 아니다. 서비스 항목이나 앱을 지워도 규칙은 남고, 다음 설치가 그것을 다시 물려받는다.

한 번의 시험이 소유권을 결정한다. 연결을 끊고 기다린 뒤 내부 이름을 다시 요청하라. 터널이 돌아오면 트리거는 설계대로 작동하며, 남은 질문은 누가 관리하는지와 그 범위가 원하는 것인지다.

이것을 버그로 보고하기 전에 같은 다섯 가지 확인을 거쳐라. payload에 터널 리졸버 주소가 있는가, 캐시되지 않은 이름인가, 이전 규칙이 이미 일치하지 않았는가, 경로 목록이 AAAA 경로를 덮는가, 앱이 터널 범위 안에 있는가. 다섯 가지가 모두 성립하면 규칙은 제 일을 하고 있고 결함은 경로 더 앞에 있다.

관련 글