hhkb.dev

BLOG

2025-12-18 / 피버팅과터널링 · 05

SSH 로컬 포트 포워딩 심화

1. 개요

SSH 로컬 포트 포워딩(Local Port Forwarding)은 내부 자산으로 연결 경로를 우회해 붙을 때 자주 쓰는 기본 구조다. 이 문서에서는 단순히 명령만 적는 대신, 소켓 바인딩과 데이터 흐름이 어떻게 이어지는지에 초점을 맞춘다.

2. SSH 포트 포워딩의 기술적 동작 원리

SSH 포트 포워딩은 단순한 패킷 릴레이로만 보면 부족하다. 실제로는 SSH 프로토콜의 채널(Channel) 멀티플렉싱(Multiplexing) 구조를 이용한다.

2.1 연결 수립 흐름

예를 들어 ssh -L 8080:Target:80 Pivot을 실행하면 내부에서는 아래 흐름이 일어난다.

  1. 로컬 바인딩(Local Bind)
    SSH 클라이언트가 로컬 포트 8080에 TCP 소켓(Socket)을 만들고, 리스닝(Listen) 상태로 대기한다.
  2. 캡슐화 및 전송(Encapsulation)
    사용자가 localhost:8080으로 요청을 보내면, SSH 클라이언트가 이 데이터를 받아 암호화한 뒤 기존 SSH 세션(TCP 22) 안의 채널로 전달한다.
  3. 원격 연결(Remote Connect)
    피벗 호스트의 sshd가 데이터를 복호화하고, 다시 Target:80으로 새 TCP 연결을 만든다.

결과적으로 타겟 입장에서는 요청 출발지가 로컬 PC가 아니라 피벗 호스트 쪽으로 보인다.

2.2 바인딩 주소와 보안

-L 옵션에서 어디에 바인딩하느냐에 따라 접근 범위가 달라진다.

  • 127.0.0.1 (기본값)
    ssh -L 8080:...처럼 주소를 생략하면 보통 여기에 붙는다. 로컬 호스트만 터널을 쓸 수 있어서 기본값으로는 가장 무난하다.
  • 0.0.0.0 (모든 인터페이스)
    ssh -L 0.0.0.0:8080:... 또는 -g처럼 열면 같은 네트워크의 다른 사용자도 이 포트에 접근할 수 있다. GatewayPorts 설정도 함께 영향을 준다.

3. 기술적 시나리오 분석

3.1 Loopback 서비스 접근(Local-Only Bypass)

피벗 호스트 안의 phpMyAdmin이나 관리자 콘솔이 127.0.0.1:8080처럼 로컬에만 묶여 있으면 외부 NIC(eth0)에서는 바로 접근되지 않는다.

이때 로컬 포트 포워딩을 쓰면 트래픽이 eth0를 직접 타지 않고, sshd 내부에서 Loopback 인터페이스(lo) 쪽으로 전달된다. 그래서 외부에서 안 보이던 로컬 전용 서비스에 연결 경로가 생긴다.

3.2 다중 홉(Multi-Hop)과 라우팅

공격자 -> 피벗(DMZ) -> 타겟(Internal Jenkins)처럼 한 단계를 더 거치는 경우에도 원리는 같다.

  • 핵심: 타겟 호스트(10.1.20.50)는 인터넷에서는 바로 닿지 않지만, 피벗 호스트와는 라우팅이 가능한 상태다.
  • 데이터 흐름: 로컬 PC에서 나갈 때는 SSH 암호화 패킷으로 보이고, 피벗 호스트에서 복호화된 뒤에는 일반 HTTP 패킷처럼 내부 라우팅을 따라 움직인다.

4. 실전 활용 예시

활용 예시는 보통 아래처럼 정리된다.

  • 웹 인터페이스 접근: 내부망에만 열려 있는 Jenkins, Tomcat 관리자 페이지 같은 로컬 서비스에 연결 경로를 만든다.
  • 로컬 도구 호환성: 복잡한 프록시 설정 없이도 브라우저나 Burp Suite 같은 로컬 도구를 거의 그대로 쓸 수 있다.