WSL2는 기업 VPN을 상속하지 않는다, 그리고 그것이 버그다
WSL2는 자체 가상 네트워크에서 실행되며 호스트의 VPN 스택을 결코 상속하지 않습니다. resolv.conf를 편집하기 전에 이름 실패와 경로 실패를 분리하십시오.
사내 위키는 Edge에서 열리는데 배포판 안의 git clone은 시간 초과된다. 이 단일 관찰은 보통 «VPN이 WSL2를 막고 있다»로 읽히고, 다음 한 시간은 /etc/resolv.conf을 편집하는 데 쓰인다. 더 유용한 해석은 WSL2에 호스트의 네트워크 경로가 애초에 없었다는 것이다. 그것은 자체 어댑터, 자체 경로, 그리고 Windows가 생성하는 resolver 파일을 가진 유틸리티 VM에서 실행된다. 이후의 모든 것은 이 세 가지 중 무엇이 실제로 빠졌는지에 달려 있다.
그 VM은 자체 스택과 메트릭과 resolver를 가진다
기본 NAT 모드에서 배포판은 가상 스위치 뒤에 있고 호스트를 통해 인터넷에 도달하지만, 호스트의 어댑터를 보지는 못한다. ip addr은 사설 주소를 가진 인터페이스 하나를 보여 주고, ip route은 그 스위치를 통한 기본 경로를 보여 주며, /etc/resolv.conf은 Windows가 선택한 stub resolver를 가리키는 생성 파일이다. Windows 쪽에서 VPN 클라이언트가 시작되었다고 해서 이 중 어느 것도 바뀌지 않는다.
그래서 «브라우저는 된다»는 너무 적게 증명한다. 브라우저는 호스트 스택, 터널, 호스트의 resolver 정책을 쓴다. 여러분의 셸은 우연히 물리 NIC를 공유하는 다른 스택을 쓴다. 둘은 좋은 경우에 일치하고, VPN이 필터를 설치하거나 DNS 목록을 다시 쓰거나 가상 스위치의 서브넷에 경로를 추가할 때 정확히 갈라진다.
어느 세계에 있는지는 두 가지 테스트로 결정되며, 둘 다 배포판 안에서 실행해야 한다.
getent hosts example.com
curl -sS -m 8 -o /dev/null -w "%{http_code}\n" 1.1.1.1
ip route
cat /etc/resolv.conf
리터럴 주소는 응답하는데 이름이 실패하면 resolver 문제다. 이름과 주소가 함께 실패하면 경로 문제이며, resolver 편집으로는 닿지 않는다. 다음은 Windows 쪽 증거다. Get-NetAdapter | Get-DnsClientServerAddress과 route print -4은 터널이 VM이 사는 서브넷을 점유했는지 보여 준다.
첫 번째 속설: 기업 DNS 서버가 해결해 준다
resolver 파일 편집은 고전적인 조언이며 절반쯤 맞다. 맞을 때는 구체적인 이유가 있다. 생성 파일이 공개 이름만 아는 resolver를 가리키므로, 경로가 멀쩡해도 intranet.example.internal에 대한 질의는 존재하지 않는 것으로 돌아온다.
VPN 서버를 고정한다는 것은 Windows가 파일을 다시 생성하지 못하게 하는 것이다. 손으로 쓴 파일은 다음 시작 시 교체되기 때문이다.
[network]
generateResolvConf = false
그것을 /etc/wsl.conf으로 저장하고, Windows에서 wsl --shutdown을 실행한 뒤 배포판을 시작하고 /etc/resolv.conf을 쓰되 터널 서버를 먼저, 공용 resolver는 예비로만 둔다. 이것은 유지보수 비용이 있는 영구 변경이다. 파일이 더 이상 호스트를 따르지 않으므로, 기업 DNS 주소가 바뀌면 배포판은 계속 옛 주소를 묻는다. 누군가 그 파일의 주인이 되어야 한다.
실패가 더 넓을 때도 아무것도 하지 않는다. curl에서 1.1.1.1로 시간 초과가 나면 터널 클라이언트가 가상 스위치를 필터링하거나 VM 서브넷을 터널로 라우팅하는 것이고, 올바른 resolver는 여전히 닿을 수 없는 이름만 준다.
두 번째 속설: 메트릭 변경은 유지된다
이름은 풀리는데 트래픽이 물리 어댑터로 나가면 인터페이스 메트릭이 지렛대다. VPN 어댑터에 높은 비용을, WSL 스위치에 낮은 비용을 주라.
Get-NetAdapter | Where-Object InterfaceDescription -Match "AnyConnect" | Set-NetIPInterface -InterfaceMetric 4000
Get-NetIPInterface -InterfaceAlias "vEthernet (WSL)" | Set-NetIPInterface -InterfaceMetric 1
그다음 많은 클라이언트 빌드에서 터널 어댑터가 연결할 때마다 다시 만들어지고 메트릭이 기본값으로 돌아간다는 것을 기억하라. 일회성 명령은 조용히 만료되는 수정이며, 보통 주말을 넘기고 티켓은 «지난주에는 됐다»로 돌아온다. VPN 이벤트로 시작되는 예약 작업이나 사용자가 연결 후 실행하는 스크립트가 이 수리의 정직한 형태다.
같은 만료가 고집 센 프리픽스 하나를 위해 추가한 호스트 경로에도 적용된다. 진단으로서는 가치가 있다. 문제가 목적지 하나인지 경로 전체인지 알려 주기 때문이다. 그러나 아키텍처는 아니다.
세 번째 속설: 한 가지 수정이 모든 Windows 빌드를 덮는다
| Approach | What it actually does |
|---|---|
| Resolver pin | Fixes private names only; no effect on path failures |
| Sidecar distribution | Forwards traffic over a socket to a helper VM, so the switch's filter no longer matters |
| Mirrored networking | Gives the distribution the host's interface set; also enables DNS tunnelling |
wsl-vpnkit은 sidecar 패턴이다. 작은 배포판이 호스트 쪽 경로를 소유하고 가상 소켓을 통해 다른 배포판을 위해 전달하므로, 애플리케이션 트래픽이 필터링된 스위치에 의존하지 않게 된다. 표준 경로가 동작해야 하며, 즉 networkingMode과 dnsTunneling 재정의를 %UserProfile%\.wslconfig에서 제거하고, 각 동작하는 배포판에서 generateResolvConf = true을 복원하고, 로그인 시 서비스를 시작해야 한다.
미러 모드는 Windows 11 22H2 이상의 내장 대안이며, 설정 하나와 종료 하나면 된다.
[wsl2]
networkingMode=mirrored
배포판 안에서 ip addr은 호스트 어댑터를 나열하고, 터널이 그중에 나타날 수 있으며, DNS 터널링은 클라이언트가 DNS 목록을 다시 써도 Windows resolver를 통해 조회를 전달한다. 보편적이지는 않다. 일부 필터 드라이버는 여전히 미러 경로를 버리고, Hyper-V 방화벽 규칙에 명시적 허용이 필요할 수 있다. Microsoft의 WSL 네트워킹 가이드는 더 새 버전을 위해 쓰인 레시피를 적용하기 전에 자신의 빌드와 대조해야 할 페이지다.
변경할 때마다 세 가지를 시험하라
머신마다 한 가지 메커니즘을 골라 적어 두라. 둘은 나쁘게 결합한다. 미러 모드 위에 sidecar를 두면 전달이 두 배가 되고, .wslconfig에 오래된 sidecar 항목이 있는 미러 호스트는 업그레이드 전이 아니라 후에 실패하는 경향이 있다.
무엇을 고르든 인수 테스트는 배포판 안의 같은 세 요청이다. 내부 이름, 공개 이름, 원시 주소. 그다음 터널을 끊었다 다시 연결한 뒤, 그리고 wsl --shutdown 이후에 반복하라. 내부 이름만 실패하면 resolver 정책이고, 내부와 공개 이름이 함께 실패하면서 주소는 동작하면 여전히 resolver 정책이며, 모두 실패하면 경로다.
내부 호스트 하나만 실패하고 나머지가 동작하면 resolver를 보는 것을 멈추고 그 프리픽스에 빠진 경로를 찾아라. 다음 재연결까지 모두 동작한다면 런타임 상태에 의존하는 수정을 찾은 것이며, 자동으로 다시 적용하거나 위의 두 메커니즘 중 하나로 바꿔야 한다.