저번까지 WSL2를 적용하고 Ubuntu 를 설치하는것까지 해보았다.
이번엔 ssh 서버를 구축하고 외부에서 접속까지 가능하도록 해볼것이다.
ssh 설치하고 서버를 구축하는건 매우 쉽다. 그냥 구글 검색만 해도 나보다 훨씬 좋은 방법으로 인도해줄것이다.
일단 맨 처음 apt를 업데이트 해줘야한다.
ubuntu 를 실행하고 간단하게
apt update -y && apt upgrade -y
를 입력하면 편하게 업데이트가 된다. 아... sudo까지 붙여야함
sudo apt update -y && sudo apt upgrade -y
그럼 모두 자동으로 업데이트가 된다.
그리고 openssh 를 설치해준다.
apt install openssh
권한때문에 안된다면 앞에 sudo를 붙이고..
그리고 ssh 서비스를 스타트 해주면 ssh server 를 열 수 있다.
service ssh start
이것도 역시나 권한에 문제가 있다면 sudo를 앞에 붙인다.
서비스가 잘 확인되고있는지 확인은
service ssh status
ssh 멈춤은
service ssh stop
ssh의 기본 포트는 22인데 나는 이 포트를 보안상 바꾸려고 한다. 포트를 바꾸려면 sshd_config 파일을 수정해줘야하는데 이 파일은 아래의 명령어를 치면 알 수 있다.
cd /etc/ssh/
아래 경로에 sshd_config 파일이 있을것이다. ssh_config 와 헷갈리지 말것.
이걸 vim으로 열어보자.
vim 이 없다면 apt install vim
을 쳐서 vim을 설치해준다.
vim 으로 열려면
vim ./sshd_config
를 입력하면 된다. 사실 cd로 디렉토리 이동을 하지 않고 그냥 홈 디렉토리에서
vim /etc/ssh/sshd_config
를 쳐도 바로 열 수 있다. 일일이 치는것보다 파일명의 일부를 입력하고 탭을 누르면 자동완성이 되거나 이름이 애매할 경우 탭을 한번 더 누르면 그 이름과 비슷한 파일들을 해당경로에서 찾아서 보여준다.
이 파일을 수정하려면 읽기전용이기 때문에 sudo 를 붙여야한다.
sudo vim /etc/ssh/sshd_config
를 치면 여러가지 설정값들이 나오는데 그 중 Port 라고되어있는 부분이 있고 앞에 #이 있을것이다. #을 쓰면 주석처리가 되기때문에 #을 제거하고 port 뒤에는 자기가 쓰고싶은 포트번호를 넣으면 된다. 포트 말고도 다른 설정값들이 있는데 이는 버전마다 기본값으로 되어있는 경우도 있고 아닌경우도 있었다. 혹시 몰라 내 설정값을 올려놓았다.
각 설정값에 대한 설명은 아래에서 찾아보면 된다.
https://webdir.tistory.com/119
이제 접속을 해야하는데 이렇게 ssh server 를 열고나서 한번 잘 열렸는지 테스트를 해보자.
ssh 사용자@접속주소 -p 포트번호
이런 양식으로 치면 되는데 원래는ssh 접속주소
만으로도 가능하다. 이는 접속 사용자 아이디를 현재 사용자와 동일하게 간주하고 또한 포트번호도 기본값인 20을 간주하고 접속하는 형태이다 여기서 사용된 기본값은 위에서 헷갈리지 말라고했던 ssh_config
에서 설정할 수 있다.
자신의 ssh에 접속해보려면 간단하다.
ssh localhost -p 접속포트
이렇게 입력했을때 접속이 되면 일단 된것이다.
이제 외부접속을 되게 해야한다.
저번 포스트에서 wsl2 는 마치 이 컴퓨터를 라우터로 사용하여 서브에 내부망이 하나 더 설치된것같은 느낌으로 동작한다고 했었다. hyper-v 어댑터가 하나 더 생성되어 우리가 설치한 ubuntu 는 이 어댑터에 연결되어 있는것이다.
다른 컴퓨터가 있다면 이 컴퓨터로 연결을 테스트해보길 바란다. 지금 ssh server 를 연 사용자가 good 이고 ip 가 192.168.0.30
, 포트번호가 7554 라면
ssh good@192.168.0.30 -p 7554
라고 입력하면 비밀번호를 입력하고 접속하라고 할것이다. 비밀번호는 우리가 ubuntu 를 처음 실행하고 사용자 이름을 설정하기위해 입력했을테고 그 다음 비밀번호를 설정하기 위해 입력했을 것이다. 그때 사용한 사용자 이름과 비밀번호를 입력하면 된다.
혹은 모바일로도 가능하다 Termux
라는 어플을 사용하면 모바일에서도 터미널을 사용할 수 있다.
현재 날짜 기준 termux 는 구글스토어에는 올리지 못하는 상황이 되었으며 apk를 받고싶다면 공식 홈페이지에 들어가서 받아야 한다.
https://termux.dev/en/
접속이 되는가...? 아마 안될것이다. 무엇이 문제일까 생각해보았다. 일단 우리는 ssh의 기본 포트인 22번을 쓰지않고 우리 임의의 포트를 사용하고 있다. 그럼 22포트로 설정한 다음 ssh server 를 실행했을때는 정상접속이 되어야한다.
여기서 가정해야할 일이 좀 있다.
접속이 된다?
22 포트는 열려있고 내가 설정한 포트는 안열려있다는 말. 그럼 어디인가 22포트를 열어놓은 설정값이 있을것이다.
접속이 안된다?
ssh server 가 실행이 안되있다는 것이거나 접속시도를 엉뚱한 ip로 했다는 뜻이다.
포트 포워딩을 내부는 허용했으나 외부에는 허용을 안해놨을것이다. 내부에서 허용한 설정값이 있을테니 찾아봐야한다...
등등...
굉장한 많은 삽질이 있었다. 집에 노트북이 두대가 있는데 A는 wsl1을, B는 wsl2를 설치했다. 각각 ssh server 를 실행해봤으나 둘다 접속이 되지 않았다. 무언가 막고있다는 생각이 들어서 포트포워딩을 살펴보니 역시나 포트가 문제였다.
공유기를 쓰고있다면 포트포워딩 설정을 가서 우리가 임의로 설정한 포트를 받는다면 해당 ip로 넘겨주는 규칙을 만들어야 한다.
일단 나의 경우에는 synology nas 에 의해 도메인을 받아와서 도메인을 입력하면 집 공인 ip로 접속이 가능하다. 그리고 접속한 다음 어느포트를 사용하냐에 따라서 집에 연결된 수많은 기계중 하나로 연결되게 포트포워딩을 설정해 놓아야 한다.
할게 좀 뒤죽박죽이지만 차근차근하게 설명하자면
- localhost 접속 테스트
- 내부망 접속 테스트
- 외부망 접속 테스트
이런 순서대로 하는게 좋다.
그럼 첫번째 localhost 는 접속이 되었고... 혹시나 이게 안되더라도 사실 건너뛰어도 된다. wsl의 네트워크 구성에 따라 localhost 는 접속이 안되나 내부망은 접속이 되는경우가 있었다. 그래서 1번은 그렇게 신경 안써도 되고 service ssh status
를 쳤을때 sshd가 실행중이라고 뜨기만 하면 일단 ssh server 는 정상실행이 되고있다고 간주한다.
그럼 두번째... 내부망 테스트를 해보자. 포트포워딩 설정방법은 공유기가 다 다를테지만 나는 iptime이기 때문에 그거로 포트포워딩 하는방법만 찾아주겠다.
https://velog.io/@moey920/iptime-%EA%B3%B5%EC%9C%A0%EA%B8%B0-%ED%8F%AC%ED%8A%B8-%ED%8F%AC%EC%9B%8C%EB%94%A9-%EC%84%A4%EC%A0%95
일단 포트포워딩 방법은 알았으니 우리는 ssdh_config 에서 지정한 포트번호로 접속이 되면 ssh server 를 연 컴퓨터로 포워딩을 해주면 된다.
프로토콜은 TCP 로 해주고, 내부, 외부 포트번호는 다 ssh server 를 연 컴퓨터로 설정한다.
그리고 내부망에서 접속테스트를 해보면... wsl1이었다면 됐었을거다... 하지만 wsl 에선 되지 않는다...
다시한번 그림을 그리자면
만약 외부 도메인이 good.okok 로 설정되었고, ssh server를 연 컴퓨터의 내부 ip 망은 192.168.0.43, 포트는 7556 포트를 사용하여 열었다고 간주해보자.
포트포워딩이 되면 위 그림처럼 접속이 된다. wsl1이라면 192.168.0.43번 컴퓨터에 서버가 열려서 저렇게 접속이 되지만... wsl2는 다르다...
ubuntu 에서 hostname -I
를 입력해보면 wsl1 이라면 이 컴퓨터의 ip가 나오지만 wsl2에서는 172로 시작하는 이상한 아이피가 나온다...
그렇다... 바로 아래그림과 같은 형태가 되는것이다.
그럼 우리는 외부와 내부에서는 포트포워딩으로 7556 포트로 오는 접속시도는 192.168.0.43 으로 정상적으로 보냈으나 사실은 192.168.0.43이 그걸 받으면 안되고 그림에서 보이는 ip인 172.19.130.94가 이 ip를 받아야 하는것이다.
위 그림과 같이 192.168.0.43 에서 포트포워딩으로 172.19.130.94로 보내야하는것이다.
여기서 갑자기 172라는 ip가 왜 나왔는지 궁금하다면 아래에 잘 설명되어있다.
https://velog.io/@hidaehyunlee/%EA%B3%B5%EC%9D%B8Public-%EC%82%AC%EC%84%A4Private-IP%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
자, 그럼 받은 192.168.0.43에서 포트포워딩을 통해 wsl2로 보내야한다.. 이건 어떻게 해야하는가... 이러한 포트를 막는 행위는 모두 방화벽에 의해 차단되는데 윈도우 방화벽 설정에서 해당 포트에 대한 혹은 프로세스에 대한 접근을 허용해줘야 한다. 나는 포트로 접속을 하기때문에 해당포트로 들어오는 접속은 그대로 wsl2로 보내야 하는 설정이 필요하다.
방화벽 설정은 powershell을 통해 설정할 수도 있다.
power shell을 관리자 권한으로 연 다음 아래의 명령어를 통해 해당포트로 들어오는 신호를 wsl2로 전달이 가능하다.
netsh interface portproxy add v4tov4 listenport=$port listenaddress='0.0.0.0' connectport=$port connectaddress=172.19.130.94
근데 여기서 골때리는 문제가 생긴다... wsl2는 컴픁가 재시작될 때 마다 ip가 바뀌는데 위 명령은 컴퓨터를 한번 껏다키면 매번 바꿔줘야하는 문제가 생긴다.
그리하여 뭔가 스케쥴러 같은거를 통해서 컴퓨터가 켜질 때 자동으로 실행되는 스크립트가 필요했고 다행히도 전세계에 나와 같은 생각을 한 사람들이 많았기에 검색을 통해 아래의 포스트를 얻을 수 있었다.
https://velog.io/@sjuun/WSL-2-%EC%99%B8%EB%B6%80-%EC%A0%91%EC%86%8D-%ED%97%88%EC%9A%A9
그리고 결론으로 아래 스크립트를 얻게 되었다.
$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,8000,8002,8080);
#[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";
}
위 스크립트를 .ws1
확장자로 저장한 다음 위 코드 중 $ports=@
라고 되어있는 괄호 안에 열고싶은 포트번호를 입력하고 스크립트를 실행하면 된다.
이 스크립트는 컴퓨터가 다시 재시작될때마다 실행되야 하기에 작업 스케쥴러를 통해 설정해놓는게 좋다.
윈도우 키를 누르고 그냥 작업 스케쥴러 를 입력하면 나온다.
작업 만들기를 누른다.
적당한 이름을 입력하고 트리거 탭을 누른다.
새로 만들기를 누른 후 작업 시작 드롭박스를 눌로보면 여러가지가 나오는데 그 중 wsl의 ip는 컴퓨터가 새로 시작할 때 바뀌기 때문에 시작할 때를 선택하고 확인을 누르면 된다.
그 후 동작 을 눌러준다
새로 만들기 를 누르면 아래의 창과 같이 나온다.
각 구간에는 아래와 같이 입력하면 된다.
powershell 의 실행 경로를 넣으면 된다.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
-File
옵션 후에 나오는 .\wsl-connect-external.ps1
는 실행할 파워쉘의 이름을 입력하면 된다.
-ExecutionPolicy Bypass -File .\wsl-connect-external.ps1
위에서 지정한 wsl-connect-external.ps1
가 있는 위치를 입력하면 된다.
C:\PowerShellScript
확인하여 만들고 만들어진 작업을 오른쪽 클릭하면 시작이라는 메뉴가 있다. 이 메뉴를 눌러주면 자동으로 스크립트가 실행된다.
혹시나 스크립트가 동작하지 않았더라도 작업 스케줄러가 해당 스크립트를 물고있기때문에 다시 작업 스케줄러로 들어와서 생성한 테스크를 오른쪽 클릭 한 다음 시작하면 된다.
이제 외부 접속 테스트를 하면 동작을 할것이다.
이 짓을 왜 하냐... ssh뿐만 아니라 나는 ubuntu 에서 code server 를 실행하여 붙을것이기 때문이다. code server 는 ubuntu 로 실행할 생각이고 이 code server는 인터넷으로 연결하기 때문에 port 를 지정할 수 있는데 보안을 위해 또한 외부 입력이 가능하게 한다면 내 synology nas 에서 만든 도메인에다가 code server의 포트번호만 입력한다면 code server 로 쉽게 붙을 수 있을것이다. 이 code server 도 역시나 서버를 열 port 번호를 수정가능한데, 이는 code server 를 본격적으로 설치할 때 포스팅 할 예정이다.
.그... 아마 ... 작업스케쥴러 일반 탭에서 가장 높은 수준의 권한으로 실행 에 체크해야 될 것 같네요! 방화벽이니깐,,ㅎㅎ