SSH 포트 포워딩은 SSH 연결을 통해 특정 포트로 들어오는 네트워크 트래픽을 다른 호스트나 포트로 리다이렉션하는 기술입니다. 이 기능을 사용하면 암호화된 SSH 터널을 통해 안전하게 데이터를 전송할 수 있으며, 방화벽 제한을 우회하거나 보안이 취약한 프로토콜을 보호하는 데 유용합니다.
SSH 포트 포워딩은 크게 세 가지 유형으로 나눌 수 있습니다:
로컬 포워딩은 가장 일반적으로 사용되는 SSH 포트 포워딩 방식입니다. 로컬 머신의 특정 포트로 들어오는 트래픽을 SSH 연결을 통해 원격 서버나 그 너머의 다른 서버로 전달합니다.
ssh -L [bind_address:]local_port:destination_host:destination_port user@ssh_server
local_port에 접속합니다.destination_host:destination_port로 전달합니다.ssh -L 8080:localhost:80 user1@192.168.64.31
이 명령어는 로컬 8080 포트를 SSH 서버(192.168.64.31)의 80 포트로 포워딩합니다. 웹 브라우저에서 http://localhost:8080에 접속하면 원격 서버의 웹 페이지가 표시됩니다.
ssh -L 8080:192.168.64.31:80 user1@192.168.64.30
이 명령어는 로컬 8080 포트를 SSH 서버(192.168.64.30)를 통해 다른 서버(192.168.64.31)의 80 포트로 포워딩합니다. 이 경우, SSH 서버는 중간 경유지 역할을 합니다.
원격 포워딩은 로컬 포워딩의 반대 개념입니다. SSH 서버의 특정 포트로 들어오는 트래픽을 SSH 클라이언트 측으로 전달합니다. 이 방식은 로컬 머신이 외부에서 직접 접근할 수 없는 네트워크 환경에 있을 때 유용합니다.
동적 포워딩은 SOCKS 프록시 서버를 생성하여 다양한 목적지로의 트래픽을 동적으로 라우팅합니다. 특정 포트와 호스트를 미리 지정하지 않고, 클라이언트 애플리케이션의 요청에 따라 SSH 서버를 통해 다양한 목적지로 트래픽을 전달합니다.
Nginx가 설치된 VM2(192.168.64.31)의 80번 포트를 로컬 머신의 8080 포트로 포워딩하기 위해 다음과 같이 SSH 명령어를 실행합니다:
[user1@localhost ~]$ ssh -L 8080:192.168.64.31:80 user1@192.168.64.31
이 명령어는 로컬 머신의 8080 포트로 들어오는 모든 트래픽을 SSH 터널을 통해 192.168.64.31 서버의 80번 포트로 전달합니다.
설정 후, 로컬에서 다음과 같이 요청을 보내면 정상적인 Nginx 응답을 받을 수 있습니다:
curl localhost:8080
❯ curl 192.168.64.30:8080
curl: (7) Failed to connect to 192.168.64.30 port 8080 after 1003 ms: Couldn't connect to server
192.168.64.1서버에서 curl 요청시 접속이 거부되는 것을 확인할 수 있습니다.
Wire shark 사진

wire shark 사진을 보면 응답으로 R플래그가 설정되면서 접근이 거부된 것을 확인 할 수 있습니다.
문제의 원인은 SSH 포트 포워딩 설정에 있습니다. 기본 설정인 ssh -L 8080:192.168.64.31:80 user1@192.168.64.31에서는 바인딩 주소가 명시되지 않았기 때문에 기본값인 localhost(127.0.0.1)만 접근이 가능하게 됩니다.
실제로 열려있는 포트를 확인해보면:
[user1@localhost ~]$ ss -tna
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:111 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 127.0.0.1:8080 0.0.0.0:*
8080 포트가 127.0.0.1(localhost)에만 바인딩되어 있는 것을 확인할 수 있습니다.
SSH 포트 포워딩 명령어의 형식은 다음과 같습니다:
ssh -L [bind_address:]port:host:hostport user@remote_host
여기서 bind_address는 어떤 네트워크 인터페이스에서 연결을 수신할지 결정하는 값입니다. 외부에서도 접근 가능하게 하려면 다음과 같이 설정합니다:
[user1@localhost ~]$ ssh -L 0.0.0.0:8080:192.168.64.31:80 user1@192.168.64.31
0.0.0.0으로 설정하면 모든 네트워크 인터페이스에서 연결을 수신하게 됩니다.
바인딩 주소를 변경해도 여전히 접근이 안 될 수 있습니다. 그 이유는 방화벽에서 해당 포트가 차단되었기 때문입니다.
Wireshark

위 문서와 다른 점으로는 응답값으로 icmp가 왔으며 도착시간도 10ms안으로 매우 빠르게 도착한 것을 볼 수 있습니다.
Rocky Linux에서는 firewalld를 사용하여 방화벽을 관리합니다. 다음 명령어로 8080 포트를 개방합니다:
[user1@localhost ~]$ sudo firewall-cmd --add-port=8080/tcp
[user1@localhost ~]$ sudo firewall-cmd --reload
방화벽 설정 확인:
[user1@localhost ~]$ sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s1
sources:
services: cockpit dhcpv6-client http ssh
ports: 22/tcp 8080/tcp
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
8080/tcp 포트가 열린 것을 확인할 수 있습니다.
모든 설정이 완료되면 이제 다른 시스템에서도 192.168.64.30:8080으로 접근이 가능해집니다:
❯ curl 192.168.64.30:8080
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<title>HTTP Server Test Page powered by: Rocky Linux</title>
<style type="text/css">
/*<![CDATA[*/
html {
height: 100%;
width: 100%;
}
body {
...
What does "bind_address" mean in SSH port forwarding? - Stack exchange
이 질문은 SSH 포트 포워딩의 가장 강력하면서도 혼동되기 쉬운 개념 중 하나를 다루고 있습니다. 왜 아래 명령어가 작동하는지 자세히 설명해 드리겠습니다.
ssh -L 8080:192.168.64.31:80 user1@192.168.64.30
이 명령어를 분석해 보면:
-L 8080:192.168.64.31:80: 로컬 포워딩을 설정하는 부분8080: 로컬 컴퓨터에서 열리는 포트192.168.64.31:80: 트래픽이 최종적으로 전달될 목적지 서버와 포트user1@192.168.64.30: SSH로 연결할 서버이 명령어가 실행되면 다음과 같은 일이 발생합니다:
192.168.64.30 서버에 연결합니다.192.168.64.30 서버로 전송됩니다.192.168.64.30 서버에 도착하면, 이 서버는 트래픽을 192.168.64.31의 80 포트로 전달합니다.중요한 점은 목적지 호스트(192.168.64.31)는 SSH 서버(192.168.64.30)에서 접근 가능해야 한다는 것입니다. 즉, 192.168.64.30 서버는 192.168.64.31 서버에 네트워크로 연결되어 있어야 합니다.
SSH 서버는 단순히 트래픽을 받아 다른 서버로 전달하는 "중계소" 역할을 합니다. 이것이 가능한 이유는:
[로컬 컴퓨터] [SSH 서버] [웹 서버]
192.168.64.1:8080 ------> 192.168.64.30 ------> 192.168.64.31:80
SSH 연결 일반 TCP 연결
http://localhost:8080에 접속).이 기능이 유용한 몇 가지 상황을 살펴보겠습니다:
회사 네트워크에서 특정 서버(192.168.64.31)가 방화벽으로 인해 외부에서 직접 접근할 수 없지만, 다른 서버(192.168.64.30)는 접근 가능한 경우:
ssh -L 8080:192.168.64.31:80 user1@192.168.64.30
이 명령어를 사용하면 접근 가능한 서버를 "점프 호스트"로 활용하여 제한된 서버에 접근할 수 있습니다.
웹 서버(192.168.64.30)와 데이터베이스 서버(192.168.64.31)가 분리되어 있는 환경에서:
ssh -L 3306:192.168.64.31:3306 user1@192.168.64.30
이 명령어를 사용하면 웹 서버를 통해 데이터베이스 서버에 접근할 수 있습니다.
네트워크 연결: SSH 서버(192.168.64.30)는 목적지 서버(192.168.64.31)에 네트워크로 연결되어 있어야 합니다.
방화벽 설정: SSH 서버가 목적지 서버의 해당 포트(80)에 접근할 수 있어야 합니다.
SSH 서버 설정: 일부 SSH 서버는 보안상의 이유로 이러한 종류의 포워딩을 제한할 수 있습니다. 이 경우 /etc/ssh/sshd_config 파일에서 AllowTcpForwarding yes로 설정되어 있는지 확인해야 합니다.
이 기능은 SSH의 가장 강력한 특징 중 하나로, 네트워크 아키텍처를 단순화하고 보안을 강화할 수 있습니다. SSH 서버를 중계소로 사용함으로써, 직접 접근할 수 없는 서버나 서비스에 안전하게 접근할 수 있습니다.
쉽게 생각하면, SSH 서버는 "우리가 보낸 패킷을 받아서 우리가 지정한 다른 서버로 전달해주는 배달부" 역할을 한다고 볼 수 있습니다. 이때 배달부(SSH 서버)는 목적지(다른 서버)에 접근할 수 있어야 패킷을 전달할 수 있습니다.