WSL 네트워크
WSL 네트워크

WSL을 제대로 사용하려면 Microsoft 문서와 친해질 필요가 있다.

이 글은 WSL1을 제외하고 WSL2를 기준으로 작성한다. 개인적으로 WSL1은 너무 일찍 세상에 나온 미완성 기술처럼 느껴졌다. WSL2는 실제 Linux 커널을 경량 유틸리티 가상머신에서 실행하는 구조로 다시 만들어졌다.

WSL2와 Hyper-V

WSL2는 Hyper-V 기술을 바탕으로 하지만 Windows의 전체 Hyper-V 가상머신 관리 기능과 완전히 같은 제품은 아니다. WSL2는 Virtual Machine Platform과 경량 유틸리티 VM을 이용해 Linux 환경을 Windows에 통합한다. Windows 10·11의 클라이언트 Hyper-V와 Windows Server의 Hyper-V는 제공 기능과 운영 목적에 차이가 있지만 근본적인 하이퍼바이저 기술이 완전히 다른 것은 아니다.

Microsoft가 가상화와 클라우드에 투자한 이유는 분명하다. 개발 환경과 운영 환경의 차이를 줄이고 Azure 생태계로 이어지게 할 수 있기 때문이다. 다만 Hyper-V VM이나 WSL 배포판을 내보냈다고 해서 그대로 Azure에 즉시 올릴 수 있는 것은 아니다. Azure가 지원하는 이미지와 VHD 형식, 네트워크와 에이전트 설정을 맞추는 과정이 필요하다. 컨테이너와 Docker 역시 여전히 배포 재현성과 이식성을 위해 중요한 역할을 한다.

Azure를 사용해 본 개인적인 느낌은 비용이 높다는 것이었다. 국내 사용자만 대상으로 하고 트래픽과 운영 방식이 단순하다면 코로케이션이 더 저렴할 수 있다. 반대로 빠른 증설, 해외 리전, 관리형 서비스와 장애 대응이 중요하다면 클라우드의 장점이 커진다.

기본 NAT 네트워크

현재 WSL2의 기본 네트워크 방식은 NAT다. WSL의 Ubuntu는 Windows 호스트와 다른 가상 IP를 사용한다. Windows에서 WSL 안의 웹 서버로 접속할 때는 대부분 localhost 전달 기능을 통해 다음처럼 접속할 수 있다.

서버 프로그램은 외부 연결이 필요하다면 127.0.0.1이 아니라 0.0.0.0에 바인딩해야 할 수 있다. NAT는 외부에서 WSL로 직접 들어오는 연결을 줄여 주지만 그것만으로 해킹에 안전하다고 단정할 수는 없다. Windows 방화벽, 서비스의 인증과 보안 업데이트가 여전히 필요하다.

공유기 안쪽에서 바깥으로 나가는 것은 쉽지만 외부에서 안쪽 서비스로 들어오려면 전달 규칙이 필요한 것과 비슷하다. 그러나 “WSL2에서는 방법이 없다”는 결론은 현재 기준으로 맞지 않는다.

과거의 브리지 시도

당시 다음 블로그를 참고해 외부 브리지 연결을 시도했다.

Windows 네트워크 어댑터 화면에서 실제 이더넷과 WSL 가상 스위치를 브리지로 묶었지만 두 어댑터 모두 인터넷을 사용할 수 없었다. 사용자 폴더에 .wslconfig를 만들고 설정했을 때 일부 반응은 있었지만 vmSwitch 설정 오류가 발생했다.

.wslconfig는 YAML이나 JSON이 아니라 INI 형식이다. 과거 브리지 설정은 다음 형태였다.

[wsl2] networkingMode=bridged vmSwitch=외부용가상스위치이름

키 이름은 netmode나 networkMode가 아니라 networkingMode다. 그러나 bridged 모드는 WSL 2.4.5부터 사용 중단 대상으로 표시되어 있다. 인터넷에 남은 Windows Server 또는 예전 WSL 설정을 현재 Windows 10·11에 그대로 적용하면 동작하지 않을 수 있다.

Windows 11의 권장 방법: mirrored

Windows 11 22H2 이상에서는 진짜 브리지 설정을 억지로 만드는 대신 mirrored 네트워킹을 사용하는 것이 현재의 권장 방법이다. %UserProfile%\.wslconfig에 다음 내용을 넣는다.

[wsl2] networkingMode=mirrored

설정을 저장한 뒤 PowerShell에서 다음 명령으로 WSL을 완전히 종료하고 다시 시작한다.

wsl --shutdown wsl

mirrored 모드에서는 Windows의 네트워크 인터페이스가 WSL에 반영된다. Windows와 WSL이 localhost로 서로 연결할 수 있고 IPv6, 멀티캐스트, VPN 호환성과 LAN 직접 접속도 개선된다.

LAN의 다른 기기에서 WSL 서비스로 접속하려면 애플리케이션을 0.0.0.0에 바인딩하고 Hyper-V 방화벽의 인바운드 규칙도 허용해야 한다. 모든 포트를 여는 것보다 필요한 포트만 여는 편이 안전하다. 예를 들어 3000번 TCP 포트를 허용하려면 관리자 PowerShell에서 다음과 같이 설정할 수 있다.

New-NetFirewallHyperVRule -Name 'WSL-Web-3000' -DisplayName 'WSL Web 3000' -Direction Inbound -VMCreatorId '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -Protocol TCP -LocalPorts 3000

Windows 10에서는 NAT와 포트 프록시

Windows 10은 mirrored 모드를 지원하지 않는다. Windows에서 WSL 서비스에 접속하는 목적이라면 기본 localhost 전달만으로 충분한 경우가 많다. 같은 LAN의 다른 PC나 휴대전화가 접속해야 한다면 관리자 PowerShell에서 portproxy와 Windows 방화벽 규칙을 설정하는 방식이 공식 문서에 안내되어 있다.

먼저 WSL 주소를 확인한다.

wsl hostname -I

그 주소가 172.30.98.229이고 서비스 포트가 3000이라고 가정하면 다음처럼 전달한다.

netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.30.98.229

그다음 Windows Defender 방화벽에서 TCP 3000 인바운드 규칙을 허용해야 한다. WSL의 NAT 주소는 재시작 후 바뀔 수 있으므로 시작 스크립트에서 규칙을 갱신하거나 고정된 개발 흐름을 마련해야 한다.

Windows 10에서 WSL 자체에 공유기와 같은 LAN 주소를 직접 주는 완전한 L2 브리지가 꼭 필요하다면 현재 WSL2보다 일반 Hyper-V VM, VMware 또는 VirtualBox의 브리지 어댑터를 사용하는 편이 안정적이다.

결론

처음 WSL2의 NAT 구조를 보았을 때 웹·WAS·애플리케이션 서버 개발에는 치명적인 제약처럼 느껴졌다. 하지만 현재는 목적에 따라 방법이 분명하다.

Windows 11 22H2 이상이면 mirrored 모드를 사용한다. Windows 10이면 로컬 개발에는 localhost 전달을, LAN 공개에는 portproxy와 방화벽 규칙을 사용한다. 완전한 브리지 네트워크가 필수라면 WSL이 아닌 일반 가상머신을 선택한다.

과거에 시도했던 네트워크 브리지는 틀린 고민이 아니었다. 다만 WSL의 네트워크 구조와 지원 방식이 바뀌었고, 지금은 bridged보다 mirrored가 그 고민에 대한 공식적인 답에 가깝다.