VPN 없이 SSH 하나로 끝내는 포트 포워딩 완전 정복

한눈에 보는 요약
SSH는 단순히 원격 서버에 접속해 명령을 실행하는 도구가 아닙니다. 네트워크 트래픽을 암호화해 전달하는 터널 기능을 활용하면 별도의 VPN이나 프록시 프로그램 없이도 사설망 서비스에 접속하거나, 내 PC의 서비스를 외부에 임시로 공개할 수 있습니다.
핵심은 단 두 가지 질문으로 정리됩니다.
- 어느 장비가 새 포트를 열고 대기하는가?
- 터널을 통과한 트래픽은 어느 장비 관점에서 목적지에 접속하는가?
이 두 가지만 명확히 구분하면 복잡해 보이는 SSH 터널이 단숨에 정리됩니다.
SSH 터널은 언제 쓸까?
실무에서 자주 마주치는 활용 사례는 다음과 같습니다.
- 공개 서버를 경유해 내부 VPC 서비스에 접속
- 원격 개발 서버의 포트를 내 PC 브라우저에서 열기
- 가정·사설망의 서비스를 외부에 임시 공개
- 로컬 브라우저 디버깅 포트를 원격 개발 에이전트에 연결
로컬 포워딩(-L): 원격 서비스를 내 PC로 끌어오기
로컬 포트 포워딩은 원격 서버(또는 그 서버가 접근 가능한 서비스)를 내 PC의 로컬 포트로 연결하는 방식입니다.
ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr
- SSH 클라이언트가 내 PC의
local_port에서 연결을 기다립니다. - 들어온 트래픽은 터널을 거쳐
remote_addr:remote_port로 전달됩니다. - 최종 목적지에는 SSH 서버 네트워크의 관점에서 접속합니다.
주요 활용 사례:
- 원격 MySQL, PostgreSQL, Redis 접속
- 사설망에서만 열리는 웹 애플리케이션 접속
- 외부에 공개하지 않은 컨테이너 포트 접속
Bastion Host로 사설망 깊숙이 들어가기
흥미로운 점은 remote_addr와 접속 대상인 sshd_addr가 꼭 같은 장비일 필요가 없다는 것입니다. SSH 서버가 다른 내부 서비스에 접근할 수 있다면, 그 서버를 중계 지점(Bastion Host 또는 Jump Host)으로 삼을 수 있습니다.
- 내 PC에서 공개 Bastion Host로 SSH 접속
- Bastion Host가 접근 가능한 VPC 내부 서비스로 트래픽 전달
이를 통해 외부에 노출되지 않은 데이터베이스, 검색 클러스터, 내부 API에 안전하게 접근할 수 있습니다.
원격 포워딩(-R): 내 서비스를 외부에 공개하기
원격 포트 포워딩은 방향이 정반대입니다. 내 PC나 내부망의 서비스를 외부 SSH 서버의 포트에 연결합니다.
ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr
- 원격 SSH 서버가
remote_port를 열고 대기합니다. - 들어온 트래픽은 터널을 통해 클라이언트 쪽
local_addr:local_port로 전달됩니다.
주요 활용 사례:
- 노트북의 개발 서버를 외부 데모용으로 공개
- 홈랩 서비스를 인터넷에서 접근하도록 연결
- 로컬 디버깅 포트를 원격 개발 환경에 제공
외부 공개에는 GatewayPorts가 필요하다
기본 설정에서는 원격 포워딩 포트가 SSH 서버의 localhost에만 바인딩됩니다. 즉 서버 내부에서만 접속할 수 있죠. 공인 IP로 외부 접근을 열려면 sshd_config에서 다음을 검토해야 합니다.
GatewayPorts yes
⚠️ 이 설정은 포트를 외부 인터페이스에 노출하므로 방화벽과 접근 제어를 반드시 함께 적용해야 합니다. 인증 없는 개발 서비스를 공개 인터넷에 직접 노출하면 공격 표면이 크게 늘어납니다.
또한 원격 포워딩의 목적지는 클라이언트 장비 자체에 한정되지 않습니다. 내 PC가 홈 네트워크의 다른 서버에 접근할 수 있다면, 내 PC가 사설망과 공인 게이트웨이를 잇는 중계 장비(Jump Host) 역할을 하게 됩니다.
동적 포워딩: 하나의 터널로 여러 목적지에
일반 포워딩은 포트 하나를 목적지 하나에 고정합니다. 반면 동적 포워딩은 SOCKS 프록시를 생성해 연결할 때마다 목적지를 바꿀 수 있습니다.
동적 로컬 포워딩(-D)
ssh -D [local_addr:]local_port [user@]sshd_addr
- 내 PC의 지정 포트에서 SOCKS 프록시가 실행됩니다.
- SOCKS를 지원하는 앱은 연결마다 다른 목적지를 지정할 수 있습니다.
- 실제 연결은 원격 SSH 서버 네트워크 관점에서 이루어집니다.
하나의 SSH 연결로 원격 사설망의 여러 서비스(여러 내부 API, VPC 엔드포인트 등)를 탐색할 수 있다는 점이 고정형과의 결정적 차이입니다.
동적 원격 포워딩(목적지 생략 -R)
ssh -R [bind_address:]port [user@]gateway_addr
- 원격 게이트웨이 서버에 SOCKS 프록시가 생성됩니다.
- 들어온 요청은 터널을 통해 클라이언트 쪽 네트워크 관점에서 연결됩니다.
- 이를 통해 원격 서버에서 내 홈 네트워크 전체에 접근할 수 있습니다.
💡 동적 원격 포워딩은 클라이언트에 OpenSSH 7.6 이상이 필요하며, 외부 공개 시 마찬가지로
GatewayPorts설정이 요구됩니다.
터널만 유지하는 백그라운드 옵션
명령 실행 없이 포워딩만 유지하려면 다음 옵션을 조합합니다.
-N: 원격 명령을 실행하지 않고 터널만 유지-f: 터널을 백그라운드로 전환
ssh -f -N -L ...
ssh -f -N -R ...
ssh -f -N -D ...
단, 자동화·장시간 운영 환경에서는 터널 종료, 재접속, 장애 감지 방식을 별도로 마련해야 합니다.
헷갈리지 않는 기억법
명령은 포트를 여는 위치로 구분하면 됩니다.
-L = local:remote (로컬 클라이언트가 포트를 연다)
-R = remote:local (원격 서버가 포트를 연다)
- 콜론 기준 왼쪽이 새로 열리는 리스닝 지점입니다.
local은 SSH 클라이언트 자체 또는 클라이언트가 접근 가능한 내부 장비remote는 SSH 서버 자체 또는 서버가 접근 가능한 내부 장비
마무리: 방향으로 선택하라
| 목적 | 옵션 |
| --- | --- |
| 원격 서비스를 내 PC에서 사용 | 로컬 포워딩 -L |
| 내 서비스를 원격 서버에 공개 | 원격 포워딩 -R |
| 원격망의 여러 목적지에 유동 접근 | 동적 로컬 -D |
| 내 네트워크 전체를 원격에서 유동 접근 | 동적 원격 -R(목적지 생략) |
SSH 터널을 설계할 때 우선 확인할 항목은 명확합니다.
- 새 포트를 열어야 하는 위치
- 최종 목적지에 접근 가능한 장비
GatewayPorts, 방화벽, SSH 접근 권한 설정- 외부 공개로 인한 보안 위험
결국 핵심 판단 기준은 서비스를 어느 쪽에 보이게 할 것인가, 그리고 어느 장비가 실제로 목적지에 접근할 수 있는가입니다. 이 두 가지만 잡으면 SSH 터널은 더 이상 어렵지 않습니다.