🚆

SSH reverse tunneling

Created
2020/12/26 07:50
*메이아이의 블로그에 동일한 내용을 더 상세하게 풀어 쓴 포스트가 있다.
클라이언트 C로부터 원격으로 접속하기를 원하는 서버 A가 있다고 하자. 하지만 각종 환경의 문제로 A에 원격 접속이 불가능한 상황이다. 그런데 공인 IP를 가지고 있어 C와 A에서 접속이 가능한 서버 B가 있다고 하자. 이런 상황에서는 A가 B에 접속할 수 있다는 상황을 이용하여 reverse tunnel을 뚫어 C로부터 (B를 우회하여) A로의 접속을 꾀할 수 있다. 이 때 공인 IP를 갖는 서버 B는 AWS의 EC2 서비스를 이용하여 쉽게 만들어낼 수 있다.
이 예시에서는 B의 10002번 포트와 A의 22번 포트를 연결하는 reverse tunnel을 뚫도록 한다.
먼저 다음과 같이 B를 설정하자.
AWS에서 Ubuntu EC2 서버를 구성한다.
SSH를 이용하여 접속한다.
/etc/ssh/sshd_configGatewayPorts yes를 추가하자.
다음 명령어를 통해 ssh 서비스를 리로드한다.
sudo service ssh reload
Shell
복사
다음과 같은 명령어를 수행하여 해당 포트의 방화벽을 해제해준다.
sudo ufw allow 10002
Shell
복사
AWS console에서 해당 서버에 10002번 포트로 접속이 가능하도록 Inbound 정책을 수정한다.
콘솔에 접속하기 귀찮으면 aws cli를 통해 inbound rule을 추가할 수 있다. 명령어는 다음과 같다.
aws ec2 authorize-security-group-ingress --group-name GROUP_NAME --protocol tcp --port 10002 --cidr 0.0.0.0/0
Shell
복사
한두 번 실패하다 보면 해당 포트가 이미 사용중이기 때문에 설정이 불가능하다는 등의 에러 메시지가 뜰 수도 있다. 이 경우에는 sudo netstat -tnlp를 통해 포트 상황을 확인하고, 사용하고자 하는 포트를 물고 있는 세션을 죽여버리면 된다. (kill PID)
이제 다음과 같이 A를 설정하자.
아무래도 A에서 B로 SSH를 통해 한 번 접속해 줘야 tunneling이 가능해지는 것 같다.
다음 명령어로 터널을 뚫는다.
ssh -i [PATH_TO_PEM] -fNR 10002:localhost:22 ubuntu@[EC2_HOST_NAME]
Shell
복사
이 때 f은 background로 연결을 설정하기 위함이고, N은 괜히 쓸데없이 쉘에 접속하지 않기 위함이다.
또 연결이 끊겼을 때 알아서 다시 연결을 수복하도록 하기 위해서는 autossh 를 사용하면 편하다. autossh를 사용하는 경우 M 옵션을 따로 주어야 한다.
autossh -i [PATH_TO_PEM] -M 10984 -fNR 10002:localhost:22 ubuntu@[EC2_HOST_NAME]
Shell
복사
이로써 reverse tunnel이 완성되었다. 이제 C에서 다음과 같이 A로 접속할 수 있다.
ssh -i [PATH_TO_PEM] [USERNAME]@[EC2_HOST_NAME] -p 10002
Shell
복사
이 때 [USERNAME]은 EC2 instance의 username이 아닌 접속하고자 하는 A 서버의 username임에 주의하자! 또한 작업 도중 여러 알 수 없는 에러에 휘말릴 수 있으니 마음의 준비를 하도록 하자.
하지만 터널을 유지하기 위해서는 매번 컴퓨터를 끄고 켤 때마다 새로운 터널을 만들어주어야 하는데, 아주 귀찮고 번거로운 일이 아닐 수 없다. 다음 포스트를 통해 컴퓨터가 켜질 때마다 자동으로 터널을 생성하도록 할 수 있다.
E.O.D.