Published on

ssh 터널링 포트 포워딩 기초 정리

Authors
  • avatar
    Name
    Indo Yoon
    Twitter

SSH 터널링 포트 포워딩은 SSH 연결을 재사용해 다른 포트의 트래픽을 안전하게 전달하는 방법입니다. 로컬 포워딩은 내 컴퓨터에서 원격 대상으로, 원격 포워딩은 원격 서버에서 내 쪽 대상으로 연결을 만들며, 동적 포워딩은 SOCKS 프록시로 활용합니다. 핵심 옵션과 상황별 선택 기준을 아래에서 정리해요.

한눈에 보기

SSH 터널링 포트 포워딩은 크게 로컬 포워딩, 원격 포워딩, 동적 포워딩으로 나눌 수 있습니다. 모두 SSH 클라이언트와 SSH 서버 사이에 이미 만들어진 보안 연결을 통해 별도 포트의 트래픽을 전달한다는 점은 같아요. 차이는 연결을 어느 쪽에서 듣고, 대상 호스트에 어느 쪽이 접속하느냐입니다.

  • -L 로컬 포워딩은 내 컴퓨터에서 포트를 열고 SSH 서버 쪽에서 대상에 접속합니다.
  • -R 원격 포워딩은 SSH 서버에서 포트를 열고 내 쪽에서 대상에 접속합니다.
  • -D 동적 포워딩은 내 컴퓨터에 SOCKS 프록시를 열고 여러 대상으로 가는 연결을 SSH 서버를 거쳐 보냅니다.
  • -N은 원격 명령을 실행하지 않고 포워딩만 유지할 때 씁니다.
  • ExitOnForwardFailure=yes는 포워딩이 실패했을 때 조용히 넘어가지 않고 연결을 종료하게 합니다.

터널은 SSH 접속 권한과 서버의 포워딩 허용 설정에 영향을 받습니다. 서버에서 TCP 포워딩을 제한해 두었다면 같은 명령을 써도 터널이 열리지 않을 수 있어요.

로컬·원격·동적 포워딩 비교

구분명령 옵션연결을 듣는 위치대상에 접속하는 쪽대표 사용
로컬 포워딩-L내 컴퓨터SSH 서버내 PC에서 원격 내부 서비스에 접근
원격 포워딩-RSSH 서버내 컴퓨터원격지에서 내 쪽 서비스에 접근
동적 포워딩-D내 컴퓨터SSH 서버를 경유하는 SOCKS 프록시여러 대상에 브라우저나 도구로 접근

로컬 포워딩의 기본 형태는 ssh -L [바인드주소:]로컬포트:대상호스트:대상포트 사용자@SSH서버입니다. 예를 들어 ssh -N -L 8080:db.internal:5432 deploy@bastion.example.com은 내 컴퓨터의 127.0.0.1:8080으로 들어온 연결을 bastion 서버가 db.internal:5432로 보냅니다. 이때 대상 호스트 이름은 SSH 서버 쪽에서 해석됩니다. 그래서 대상을 localhost로 적으면 내 PC가 아니라 SSH 서버의 루프백을 가리켜요.

원격 포워딩은 ssh -R [바인드주소:]원격포트:대상호스트:대상포트 사용자@SSH서버 형태입니다. ssh -N -R 8080:localhost:3000 deploy@public.example.com은 public 서버의 127.0.0.1:8080을 내 컴퓨터의 localhost:3000으로 연결합니다. 원격 포워딩에서 대상 호스트 이름은 내 쪽에서 해석됩니다. 다른 장비에서도 접근하게 하려면 -R에 바인드 주소를 지정하고 sshd의 GatewayPorts 정책을 함께 확인해야 합니다. 기본 설정에서는 루프백에만 열리는 경우가 많아요.

동적 포워딩은 ssh -N -D 1080 deploy@bastion.example.com처럼 사용합니다. 내 컴퓨터에 SOCKS 프록시가 열리고, 브라우저나 CLI 도구에서 SOCKS5 프록시를 127.0.0.1:1080으로 지정하면 여러 대상으로 가는 연결을 SSH 서버를 거쳐 보낼 수 있어요. 특정 대상 하나가 아니라 여러 호스트를 오가야 할 때 편리합니다.

단계별로 SSH 터널 열기

먼저 SSH 접속 자체가 정상인지 확인합니다. ssh -v deploy@bastion.example.com으로 인증과 호스트 키 확인이 끝나는지 봅니다. 여기서 실패하면 포워딩 옵션을 붙이기 전에 접속 문제부터 해결해야 해요.

로컬 포워딩을 열 때는 ssh -N -L 8080:db.internal:5432 deploy@bastion.example.com을 실행합니다. -N을 붙이면 원격 셸을 열지 않고 포워딩만 유지합니다. 다른 터미널에서 데이터베이스 클라이언트의 호스트를 127.0.0.1, 포트를 8080으로 지정해 접속을 확인합니다.

원격 포워딩을 열 때는 ssh -N -R 8080:localhost:3000 deploy@public.example.com을 실행합니다. public 서버에서 curl http://127.0.0.1:8080으로 응답을 확인할 수 있습니다. 외부 인터페이스까지 열어야 한다면 서버의 GatewayPorts 설정과 방화벽 정책을 먼저 검토합니다.

동적 포워딩을 열 때는 ssh -N -D 1080 deploy@bastion.example.com을 실행합니다. 브라우저나 도구의 SOCKS5 프록시 설정에 127.0.0.1:1080을 넣고 실제 대상에 접근되는지 확인합니다. 인증서나 DNS 동작은 사용하는 도구의 프록시 처리 방식에 따라 달라질 수 있어요.

터널을 오래 유지하려면 -f로 백그라운드 실행을 고려할 수 있습니다. 다만 백그라운드로 넘긴 뒤에는 프로세스 관리와 로그 확인 방법을 정해 두는 편이 좋습니다. -v로 디버그 로그를 확인하고, -o ExitOnForwardFailure=yes로 포워딩 실패를 바로 드러나게 하는 습관도 도움이 됩니다.

상황별 선택 기준

운영 서버의 내부 데이터베이스에 내 PC에서 접근해야 한다면 로컬 포워딩이 가장 단순합니다. bastion 서버를 거쳐 내부 주소로 연결하면 데이터베이스를 외부에 직접 노출하지 않아도 됩니다. 이때 데이터베이스 클라이언트는 127.0.0.1의 로컬 포트를 바라보게 설정합니다.

원격 서버에서 내 PC의 개발 서버를 잠시 확인해야 한다면 원격 포워딩을 씁니다. 반대로 여러 내부 웹 서비스에 브라우저로 접근해야 한다면 동적 포워딩이 편합니다. 대상마다 -L을 여러 개 붙이는 방법도 있지만, 호스트가 자주 바뀐다면 SOCKS 프록시가 관리하기 쉬워요.

같은 터널을 반복해서 연다면 ~/.ssh/config에 설정을 저장합니다. 점프 호스트를 거쳐야 한다면 -J 또는 ProxyJump를 사용할 수 있습니다. 예를 들어 ssh -J deploy@bastion.example.com deploy@internal.example.com처럼 bastion을 경유해 내부 서버에 접속합니다.

ssh_config로 재사용하기

~/.ssh/config에 Host db-tunnel 항목을 만들고 HostName bastion.example.com, User deploy, LocalForward 8080 db.internal:5432, ExitOnForwardFailure yes를 적습니다. 이후에는 ssh db-tunnel로 같은 터널을 열 수 있어요. 명령줄이 길어질수록 오타와 옵션 누락이 줄어듭니다.

원격 포워딩은 RemoteForward, 동적 포워딩은 DynamicForward로 설정할 수 있습니다. 적용된 설정은 ssh -G db-tunnel로 확인합니다. 설정 파일은 권한을 제한해 두고, 공용 계정보다는 용도가 분리된 계정을 사용하는 편이 안전합니다.

주의할 점과 보안

바인드 주소를 넓히는 옵션은 특히 주의해야 합니다. -g나 sshd의 GatewayPorts는 터널을 외부 인터페이스에 열 수 있으므로, 필요한 경우가 아니라면 루프백에만 유지합니다. 운영 환경에서는 AllowTcpForwarding, PermitOpen, GatewayPorts 같은 sshd 설정을 확인해 허용 범위를 좁혀야 해요.

터널 대상 호스트 이름이 어느 쪽에서 해석되는지도 중요합니다. 로컬 포워딩은 SSH 서버 쪽 DNS를, 원격 포워딩은 내 쪽 DNS를 사용합니다. 같은 이름을 써도 접속 결과가 달라질 수 있으니 대상 주소를 명확히 적는 편이 좋습니다.

로컬 포트가 이미 사용 중이면 터널이 열리지 않습니다. ExitOnForwardFailure=yes를 사용하면 이런 실패를 빨리 알 수 있습니다. 장시간 유지하는 터널은 keepalive 옵션과 로그 확인을 함께 두고, 사용하지 않는 터널은 바로 종료합니다. 조직의 보안 정책과 방화벽 규칙을 우회하는 용도로 사용해서는 안 됩니다.

자주 묻는 질문

로컬 포워딩과 원격 포워딩은 무엇이 다른가요?

연결을 듣는 쪽과 대상에 접속을 시작하는 쪽이 다릅니다. -L은 내 쪽에서 듣고 SSH 서버가 대상에 연결하며, -R은 SSH 서버에서 듣고 내 쪽이 대상에 연결해요.

-N과 -f는 각각 어떤 역할을 하나요?

-N은 원격 명령을 실행하지 않고 포워딩만 유지합니다. -f는 인증이 끝난 뒤 SSH 프로세스를 백그라운드로 넘기며, 함께 쓰면 셸 없이 터널만 남길 수 있어요.

원격 포워딩을 다른 장비에서도 접속하게 하려면 어떻게 하나요?

-R의 바인드 주소와 sshd의 GatewayPorts 설정을 확인해야 합니다. 기본적으로는 루프백에만 열리는 경우가 많으므로, 외부 인터페이스에 열려면 서버 정책과 방화벽을 함께 검토해요.

출처

관련 운영 글: SSH 접속 보안과 서버 운영 체크리스트도 함께 읽어 보세요. 터널을 운영 환경에 적용할 때 권한과 노출 범위를 점검하는 데 도움이 됩니다.