이번 포스팅에서는 ssh 터널링에 대한 기초적인 설명과, 명령을 통한 실제 터널링에 대해 알아본다.
ssh 터널링
터널링 이란것은 일종의 통신 프로토콜이다. 기존 패킷을 어떠한 터널링 프로토콜로 감싸 새로운 패킷을 만들어(캡슐화, Encapsulation) 터널 위에서 패킷을 옮기는 기법을 말한다. 이러한 기법들은 기존 네트워크가 아닌 새로운(또는 보여지면 안되는) 채널이 필요한 경우 사용되게 된다. 또한 갈 수 없는 곳까지의 도달을 터널링을 통해 도달할 수도 있다.
이러한 터널링에는 여러가지 프로토콜이 있다. (VPN, calico CNI에서 기본으로 사용하는 IPIP 프로토콜, ssh 터널링 프로토콜등) 이러한 터널링의 목적은 결국 기존 패킷을 새로운 패킷으로 감싸 기존에는 도달하지 못하던 곳을 도달하거나, 기존 정보를 감추는 것이다.
이번에 알아볼 ssh 터널링(ssh 포트포워딩)은 서버와 클라이언트 간 ssh 채널을 열어 다른 포트에서 제공되는 서비스를 ssh 채널을 통해 전달(relay) 해주는 역할을 한다.
아래 그림과 같이 host A의 위치(네트워크상 위치)에서 host B의 특정 포트(서비스)에 접근이 되지 않고, ssh 접근만 가능한경우 host B와의 ssh 채널을 이용하여 host B의 서비스를 제공받을 수 있다.
나는 이러한 ssh 터널링을 보통 외부에서 접근이 불가능한 내부자원을 접근할때 사용한다.
대게 조직들은 자원을 방화벽 내로 숨기고 외부로 공개하지 않는다. 이건 보안으로 인해 당연한 처사다. 그리고 최소한의 접근 통로인 ssh 통로 하나정도는 열어둔다. 하지만 개발자들이라면 한번쯤은 외부에서 내부 자원에 대한 접근이 필요한때가 반드시 있을것이다. (ex DB를 까본다던지) 하지만 외부로 노출되지 않은 내부자원에 바로 접근하는것은 불가능에 가깝고, ssh 터미널 콘솔로 접근하는것도 한계가 있다.
이럴때 ssh 터널링을 사용하여 외부에서 접근 불가능한 내부자원에 접근할 수 있다.
host A에서 동작하는 App은 host B의 3306 포트로 접근하고 싶다.
하지만 host B는 22번 포트만 외부로 노출되어 있고, 3306 포트는 방화벽등의 이유로 외부로 노출되어있지 않은 상황.
이때 ssh 채널을 통해 host A와 B를 연결하고 각 말단에는 host A의 3307 포트, host B의 3306 포트를 연결하게 되면, App은 host A의 3307 포트 (127.0.0.1:3307)에 접근하면 해당 포트는 ssh 채널을 통해 relay 되어 host B의 3306 포트까지 도달하게 되고 이 과정은 ssh 의 특성상 암호화 되어 데이터가 전송된다.
실제 예시를 들어보면 다음과 같다.
내부망 (CIDR 172.16.10.0/24) 내에는 두개의 서버가 돌아가고 있다.
host C에는 Grafana(172.16.10.7:30004)가 돌아가고 있지만, 외부로는 노출되지 않는다.
host B에는 ssh 서버(172.16.10.6:22)가 열려있고, 외부에서 접근 가능하도록(223.A.B.C:22) 설정되어있다.
이런 경우 host A에서는 서버 모니터링을 위해 Grafana에 접속하고 싶어도 서비스가 외부로 노출되어 있지 않으므로 직접 접속할 수 있는 방법이 없다.
하지만 host B의 ssh 채널은 외부로 노출이 되어있고 host A는 터널링을 통해 내부망에 있는 Grafana 서비스를 자신의 8080 포트로 포워딩 할 수 있다.
아직 설명하지는 않았지만, 나의 8080 포트를 host B를 통해 host C의 Grafana 서비스로 포워딩 하는 명령이다.
ssh 접속과 같은 형태가 되면 터널링이 완료된 것이다. 이제 host A에서 localhost:8080, 127.0.0.1:8080을 통해 터널링된 서비스에 접속할 수 있다.
로컬 터널링, 로컬 포트포워딩
로컬 포트포워딩이란, 위에서 설명한 것처럼 ssh client에서 ssh server로 채널을 수립하고, ssh server 에서 접근 가능한 자원에 대해 접근하는 방법이다.
명령은 다음과 같다.
https://linuxize.com/post/how-to-setup-ssh-tunneling/
How to Set up SSH Tunneling (Port Forwarding)
SSH tunneling or SSH port forwarding is a method of creating an encrypted SSH connection between a client and a server machine through which services ports can be relayed.
linuxize.com
ssh -L [LOCAL_IP:]LOCAL_PORT:DESTINATION:DESTINATION_PORT [USER@]SSH_SERVER [-p port]
아마 명령의 어디에 어떤 값을 넣어야 하는지가 제일 관건일 것이다. 그림 3으로 예를 들자면
- LOCAL_IP : 이값은 넣어도 되고 안넣어도 된다, 나의 주소 127.0.0.1
- LOCAL_PORT : 터널을 타고 내가 접속할 말단지점 8080
- DESTINATION : 최종적으로 접속할 호스트 host C / 172.16.10.7
- DESTINATION_PORT : 최종적으로 접속할 호스트의 포트 30004
- [USER@]SSH_SERVER : ssh 채널을 수립할 서버 host B의 ssh 포트로 접근 가능한 공인 주소 (223.A.B.C)
- host B의 172.10.0.2는 내부 주소이므로, 외부 접근이 가능한 주소를 사용
- 만약 포트가 22번이 아닌 다른 포트라면 -p 옵션을 통해 지정할 수 있음
리모트 터널링, 리모트 포트포워딩
리모트 포트포워딩이란, ssh client에서 ssh server로 채널 수립이 불가능 할때(방화벽등의 이유로) 즉 서버로 ssh 연결이 불가능 할때 사용 가능한 방법이다.
그림 3에서의 예를 조금 변형하자면, host A에서 내부망으로 접근할 방법이 없는데 (외부로 노출된 223.A.B.C 도 없음) host A에서 내부망의 자원에 대한 접근이 하고자 할때 사용할 수 있다.
이때는 host B에서 host A로 ssh 채널을 연결해주게 되어 (inbound는 막히지만 outbound는 가능) 둘 사이 ssh 채널을 수립한다.
단 이때 host A로 접근 가능한 방법이 있어야 하며, host A에서 ssh server가 동작중이여야 한다.
명령은 다음과 같고, 이 명령은 host B에서 실행되는 명령이다.
https://linuxize.com/post/how-to-setup-ssh-tunneling/
How to Set up SSH Tunneling (Port Forwarding)
SSH tunneling or SSH port forwarding is a method of creating an encrypted SSH connection between a client and a server machine through which services ports can be relayed.
linuxize.com
ssh -R [REMOTE:]REMOTE_PORT:DESTINATION:DESTINATION_PORT [USER@]SSH_SERVER
- REMOTE : 접속하고자 하는 상대방의 주소 host A / Some Pub IP
- REMOTE_PORT : 접속 하고자 하는 상대방의 포트 8080
- DESTINATION : 최종적으로 도달할 주소 host C / 172.16.10.7
- DESTINATION_PORT : 최종적으로 도달할 포트 30004
- [USER@]SSH_SERVER : 접속하고자 하는 ssh 서버 host A / Some Pub IP
즉 host B에서 host A로 ssh 채널을 열어, host A가 host B를 거쳐 host C의 자원을 사용할 수 있도록 한다.