WSL 2의 resolv.conf: VPN을 연결하면 DNS가 죽는다
WSL은 볼 수 있는 Windows 어댑터에서 resolv.conf를 다시 생성하므로 VPN의 리졸버가 끝내 도착하지 않을 수 있다. 생성을 끄고 나서 사내 이름을 시험해 보라.
배포판 안에서의 탐색은 되는데, 터널이 올라오는 순간 첫 내부 호스트 이름이 실패한다. 반사적으로 공용 리졸버를 추가하면 인터넷은 돌아오지만 사내 이름은 하루 종일 풀리지 않는다. WSL 2에서 /etc/resolv.conf은 설정이 아니라 생성된 산출물이며, 이해할 만한 메커니즘은 바로 이것이다. 고칠 것은 더 나은 리졸버가 아니라 파일의 소유권이다.
파일은 설정되는 것이 아니라 생성된다
WSL 2는 시작할 때 그 시점에 보이는 Windows 어댑터에서 파일을 쓰고, 맨 위에 그렇다고 말하는 주석을 인쇄한다. 나중에 VPN 클라이언트가 어댑터를 추가하거나 다시 쓰더라도 배포판이 반드시 무언가를 다시 생성하지는 않으며, 파일은 더 이상 존재하지 않는 네트워크를 계속 설명한다.
두 번째 실패 방식은 더 조용하다. WSL이 일부 어댑터에서만 서버를 복사할 수 있다. 물리 어댑터에 이미 IPv6 리졸버가 있으면 VPN 어댑터가 제공하는 IPv4 서버가 추가되지 않고 버려질 수 있고, 파일은 완전해 보이지만 내부 이름에 응답하는 바로 그 서버를 빠뜨린다.
Windows 쪽 보기와 Linux 쪽 보기를 비교하라
편집하기 전에 양쪽을 읽는다. 배포판 안에서 파일에 무엇이 있는지, 일반 파일인지 링크인지 본다. Windows에서는 VPN이 만든 어댑터를 포함해 각 어댑터의 리졸버를 나열한다:
ls -l /etc/resolv.conf
cat /etc/resolv.conf
Get-DnsClientServerAddress -AddressFamily IPv4
Get-NetAdapter | Where-Object Status -eq 'Up'
VPN 어댑터가 사내 서버를 보여 주고 Linux가 다른 것을 보여 주면, 불일치는 도달 가능성이 아니라 생성에 있다. 어댑터 목록과 주소를 함께 비교하라. 어댑터가 빠지면 서버가 빠진 이유가 설명되기 때문이다. 이 구분이 WSL을 고치는지 방화벽을 고치는지를 결정하며, 둘은 공통점이 없다.
생성을 끄고 직접 파일을 써라
WSL이 파일을 다시 쓰지 못하게 하는 문서화된 설정이 하나 있으며 /etc/wsl.conf에 있다. 그 파일에 네트워크 절을 추가한다:
[network]
generateResolvConf = false
그런 다음 Windows에서 wsl --shutdown로 배포판을 종료하고 다시 시작한다. 경로가 일반 파일이 아니라 심볼릭 링크라면 직접 내용을 쓰기 전에 링크를 제거하라. 링크를 통해 쓰면 다음 시작에서 생성된 대상이 다시 만들어질 수 있기 때문이다. 그 시점부터 파일은 당신 것이고 아무것도 다시 쓰지 않는다.
nameserver 172.28.4.10
nameserver 172.28.4.11
search site.corp.example
options timeout:1 attempts:2 rotate
검색 도메인이 없으면 정규화되지 않은 호스트 이름이 공용 루트로 채워져 그런 도메인이 없다는 결과로 돌아온다. timeout은 죽은 첫 서버가 모든 조회를 막지 못하게 하고, attempts은 한 조회가 쓰는 시도 횟수를 제한하며, rotate는 항상 맨 위에서 시작하는 대신 재시도를 분산한다. 대가는 리졸버 주소가 세션마다 바뀌는 VPN을 파일이 더 이상 따라가지 않는다는 것이다.
움직이는 리졸버를 다루고 나서 검증하라
일부 클라이언트는 세션별 리졸버를 주므로 정적 파일은 다음 연결에서 깨진다. 두 접근이 방어 가능하다. 주소가 바뀔 때마다 작은 스크립트로 파일을 쓰거나, 생성을 켜 둔 채 WSL이 복사하는 어댑터가 사내 서버를 갖도록 하라. 후자는 훅이 필요 없고 생성이 VPN 어댑터를 건너뛸 때마다 실패한다. 둘 다 먼저 IPv6 충돌을 해결해야 한다.
Windows는 자체 이름 정책도 적용한다. 접미사 검색 목록이나 특정 도메인에 대한 확인 정책 같은 것인데, 어댑터 주소를 복사해도 그 규칙이 재현되지 않는다. 어떤 이름이 Windows에서는 풀리고 같은 서버로 배포판에서는 풀리지 않으면, 터널을 탓하기 전에 접미사 처리를 비교하라.
패킷이 아니라 이름으로 시험하라. getent hosts sensor-access0.corp.example은 리졸버 스택을 지나가지만 ping은 캐시되거나 문자 그대로의 주소에 대해 성공할 수 있다. 그런 다음 연결을 끊고 다시 연결한 뒤 반복하라. 한 번 동작하고 재개할 때 다시 생성되는 설정은 고쳐진 적이 없으므로, 이전 내용을 저장하고 그 머신에서 이 경로를 소유한 구성 요소를 적어 두어 다음 변경이 증거에서 시작되게 하라.