윈도우 하위 리눅스인 WSL2를 사용하면 리눅스 기반의 로컬 개발 환경을 구축하는데 매우 편리한 것 같습니다. 서버 환경이 리눅스라면 윈도우에서도 동일한 환경 구축이 가능하다는 점이 큰 장점이죠.

그런데 WSL2를 사용하면서 내 로컬 개발 서버를 외부에 공유하려고 할 때 문제가 발생하였습니다. 외부에서 ip를 통한 접속이 안되는 문제였죠. 아래는 이를 어떻게 해결했는지의 과정입니다.


# wsl2 외부 remote ip로 접속 허용하기
처음에는 당연히 윈도우의 방화벽 설정만으로 접속이 가능할 것이라 생각했습니다. 방화벽에서 해당 포트를 허용하고 접속하면 될 것 같았지만 동작하지 않더군요... 혹시 다른 문제인가 싶어서 IIS(윈도우 웹서버)를 사용하여 윈도우 서버를 구축하고 해보니 잘되는 것을 확인해보았습니다. 즉 wsl 자체에서 문제가 있더군요...

원인을 파악하기 위해서 검색해보니 WSL의 경우 VM 같은 Hyper-V를 사용하고 이 경우 재시작시 ip가 변경된다는 점을 확인했습니다. 또한 wsl 사용시 ip가 redirect되어 사용되는데 기본적으로 우회한 ip를 허용하지 않는 정책 때문에 결국 wsl에 이와 같은 문제가 발생한 것이었죠.


이제 원인 파악했고 문제를 해결하기 위한 과정이 남아있습니다. 검색을 통해 해결 방법을 확인하였고 아래 코드를 PowerShell에서 스크립트로 실행하여 해결하니 잘 동작하였습니다. 스크립트를 실행하기 전에 확인할 내용이 있습니다.

1. 관리자 모드로 파워쉘을 실행할 것
2. 파워셀에 스크립트 실행시 외부 코드를 수행 권한이 있는지 확인할 것

2번의 경우 기본값으로 외부 코드가 실행되지 않도록 설정되어 있습니다.
PS C:\> Get-ExecutionPolicy
Restricted

위와 같이 나올 경우 허용하기 위해서 아래 커맨드를 실행합니다.
PS C:\> Set-ExecutionPolicy RemoteSigned
PS C:\> Get-ExecutionPolicy
RemoteSigned

이제 다음으로 넘어가서 실제 스크립트를 실행해야 합니다.


! 파워쉘 스크립트 작성하기
가장 핵심인 부분입니다. 아래 스크립트는 wsl에 접속을 허용하도록 합니다. 파일을 생성 후 스크립트를 실행하세요.
$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

#[Ports]
#All the ports you want to forward separated by coma
$ports=@(80, 1000,2000,3000,5000);


#[Static ip]
#You can change the addr to your ip config to listen to a specific address
$addr='0.0.0.0';
$ports_a = $ports -join ",";


#Remove Firewall Exception Rules
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

#adding Exception Rules for inbound and outbound Rules
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteport";
}

위에서 $ports로 선언된 부분에 허용해야할 포트를 추가하시면 됩니다. 콤마로 구분되니 알아두세요. 이 파일을 임의의 파일로 만들어 실행합니다. 예를들어 아래와 같이 test.ps1으로 생성하여 실행해도 되겠죠.
PS C:\> .\test.ps1

이제 외부에서 해당 ip로 접속해 테스트를 해봅니다. 접속이 불가했던 로컬 pc가 브라우저에서 잘 나타나는 것을 확인할 수 있습니다.


[ 참고 !!] 만약 ifconfig를 찾을 수 없다고 나온다면?
이 경우 bash 명령어 안에서 실행하는 ifconfig가 동작하지 않아 그렇습니다. net-tools를 설치하면 해결할 수 있습니다.
sudo apt-get install net-tools



# 문제해결... localhost 해당 포트로 접속이 안되는 경우?

위 방법으로 성공한 케이스와 실패한 케이스 모두 존재하게 되었습니다. 만약 설정 이후 해당 포트의 localhost가 동작하지 않는다면? 일단 localhost 접속을 시도했으나 되지 않으면 이전 설정 리셋 등의 방법이 필요하겠죠. 해결 방법은 아래와 같이 현재 설정된 커맨드를 순서대로 입력합니다. PowerShell의 관리자 모드에서 입력합니다.

netsh interface portproxy show v4tov4
현재 설정된 protproxy 리스트를 보여줍니다. 여기에 접근이 안되는 port가 있는지 확인합니다.

netsh interface portproxy reset
이제 위 명령어를 사용하여 잘못 동작하는 값을 리셋하도록 합니다. 이 후 localhost 접속 후 잘 되는지 확인해야겠죠!


여기까지 wsl로 구축된 로컬 개발 환경을 외부에 접속 가능하도록 허용하는 방법을 간략하게 알아보았습니다.