스플릿 터널 문서에는 모든 경로 옆에 DNS 규칙이 필요하다
경로는 주소로 결정하고 리졸버는 이름으로 결정한다. 흐름마다 두 선택자를 모두, 각각 하나의 테스트와 함께 기록하라. 그렇지 않으면 DNS가 바뀔 때 메모가 무너진다.
"사무실 트래픽은 VPN을 통과한다"고 적은 스플릿 터널 메모는 결정 하나를 문서화하고 나머지 셋을 암시했을 뿐이다. 패킷 계층에서는 라우팅 테이블이 목적지 주소로 인터페이스를 고르고, 이름 계층에서는 리졸버가 질의로 서버를 고르며, 이 두 선택은 서로 독립적으로 이루어진다. 그래서 올바르게 문서화된 프리픽스도 내부 이름을 공용 주소로 해석하거나, 경로는 완벽해 보이는데 아무것도 해석하지 못하는 장비를 만들 수 있다.
두 선택자, 한 번의 연결 시도
애플리케이션이 files.corp.example 에 연결할 때 패킷이 생기기 전에 두 번의 조회가 일어난다. 리졸버는 검색 도메인, 링크별 라우팅 도메인 또는 명시적 프로필 규칙으로 어느 서버가 질의를 받을지 정한다. 그다음 라우팅 테이블이 목적지와의 최장 프리픽스 일치로 결과 주소의 목적지를 정한다.
그 두 결정을 잇는 것은 없다. 사설 영역은 10.20.4.11 로 응답할 수 있고, 라우팅 테이블은 10.20.0.0/16 을 터널로 보내며, 연결은 동작한다. 둘 중 하나만 뒤집어도 다른 쪽처럼 보이는 방식으로 실패한다. DNS 정책이 맞고 경로가 없으면 이름은 해석되지만 시간 초과가 나고, 경로가 맞고 공용 리졸버를 쓰면 깔끔하게 엉뚱한 곳으로 라우팅되는 주소가 나온다.
분할 지평선 DNS는 이를 더 날카롭게 만든다. 같은 이름이 내부 리졸버에서는 사설 주소를, 인터넷을 향한 리졸버에서는 공용 주소를 돌려줄 수 있으므로, 프리픽스만 기록한 메모로는 클라이언트가 실제로 어느 주소를 쓸지 예측할 수 없다. 리졸버 경로를 적어 두지 않으면 주소는 추측일 뿐이다.
경로만 적은 메모가 빠뜨리는 것
경로만 적은 기록은 스플릿 터널의 가장 흔한 장애인 이름에 쓸모가 없다. 사용자는 인트라넷이 로드되지 않는다고 보고하고, 터널은 올라와 있으며, 프리픽스도 있다. 티켓을 넘겨받은 사람에게는 어느 리졸버가 응답했어야 하는지에 대한 기록도, 잘못된 검색 접미사를 차단된 서버와 구분할 방법도, 비교할 기준선도 없다.
두 번째 누락은 예외 목록이다. 스플릿 터널 설계는 터널 안으로 들어오는 것만큼 터널 밖에 남는 것으로도 규정되며, 제외된 범위가 보통 가장 먼저 깨진다. 더 구체적인 로컬 경로나 클라이언트 측 필터가 프로필을 건드리지 않고 의도를 덮어쓸 수 있기 때문이다.
세 번째는 터널의 반대편이다. 클라이언트 경로는 패킷을 회선에 올릴 뿐이고, 게이트웨이는 여전히 그것을 전달하고 돌아오는 경로를 가져야 한다. strongSwan의 전달 안내서 는 게이트웨이의 전달 및 방화벽 규칙이 기능의 일부이지 당연히 여길 수 있는 배관 작업이 아니라고 상기시킨다.
메모를 실행 가능하게 만드는 필드
흐름마다 한 행, 그리고 흐름은 목적지 더하기 이름 더하기 소유자다. 실제 사고와 맞닥뜨렸을 때 살아남는 필드는 다음과 같다.
| Field | Why it has to be written down |
|---|---|
| Destination prefix and address family | The route is per family; an IPv4 note says nothing about a AAAA answer |
| Selected tunnel or direct path | Names the decision, not the symptom |
| Private namespace and resolver | Which domain, which server, which search suffix |
| Public name path | Confirms public names do not accidentally use the private resolver |
| Where the rule lives | Client profile, server push, OS policy or management tool |
| Owner and review date | Namespaces change owner more often than routes change |
"어디에 사는가" 행이 사람들이 건너뛰는 행이다. 서버가 밀어 넣은 프리픽스, 클라이언트 프로필이 추가한 경로, 셸에 입력한 경로는 누가 바꿀 수 있는지와 재연결 후에도 남는지가 다르다. 그 필드가 없으면 다음 엔지니어는 셋 중 무엇을 보는지 알 수 없다.
규칙마다 하나의 테스트, 터널마다가 아니라
각 행에는 무해한 확인이 둘 필요하다. 경로를 시험하는 것과 이름을 시험하는 것이다. 경로의 경우 터널을 반드시 지나야 하는 것을 요청하고 도달성 대신 경로를 확인한다. 예를 들어 tracert -d 10.20.4.11 을 Windows에서, 또는 ip route get 10.20.4.11 을 Linux에서 쓰고, 이름의 경우 사설 이름을 질의해 어느 서버가 응답했는지 기록하고, 메모가 지목한 리졸버에 대해 resolvectl query files.corp.example 또는 dig files.corp.example 을 사용한다.
부정적 기대도 추가한다. 터널이 내려갔을 때 어떻게 되어야 하는가이다. VPN 없이 차단이 켜진 Android 또는 iOS 기기의 제외된 앱은 아예 연결이 없을 수 있고, 데스크톱 클라이언트는 터널이 재연결되는 동안 같은 앱을 계속 동작시킬 수 있다. 의도된 답을 기록하면 "VPN이 내 앱을 망가뜨렸다"가 검증 가능한 주장이 된다.
기록을 구성과 함께 유지하라
메모는 그것이 설명하는 프로필 옆에 두고 그 프로필과 함께 버전을 매긴다. 아무도 갱신하지 않는 위키 문서는 소문일 뿐이다. 밀어 넣은 경로와 리졸버 정책이 있는 같은 저장소의 표라면 같은 변경에서 검토할 수 있다.
무언가 깨지면 또 다른 예외를 추가하기 전에 적용된 경로와 실제 적용 중인 리졸버를 기록과 비교한다. 흔한 세 원인 중 둘 — 오래된 이름 공간 규칙과 앱 정책 밖의 도우미 프로세스 — 은 VPN 장애처럼 보이며, 메모가 프리픽스만 나열하면 보이지 않는다.
메모를 끝났다고 하기 전에 다음에 서면으로 답하는지 확인한다. 어떤 프리픽스가 어떤 주소 체계를 위한 것인지, 어떤 사설 이름 공간을 어느 리졸버가 응답하는지, 어떤 이름이 의도적으로 공개로 남는지, 각 규칙이 어디에 구성되고 누가 소유하는지, 그리고 경로를 증명하는 명령 하나와 이름을 증명하는 명령 하나. 하나라도 빠지면 다음 사고는 처음부터 진단될 것이다.