Published on

ssh 터널링 접속 한눈에 보기: 로컬·원격·동적 포워딩 정리

Authors
  • avatar
    Name
    Indo Yoon
    Twitter

ssh 터널링 접속은 이미 열려 있는 SSH 세션을 암호화된 통로로 재사용해서, 직접 닿지 않는 포트나 서비스에 접근하는 방법이에요. 핵심은 -L(로컬 포워딩), -R(원격 포워딩), -D(동적 포워딩) 세 가지 방향을 구분하는 것이고, 나머지는 같은 원리의 응용이에요. 이 글은 배포와 운영을 담당하는 백엔드 개발자가 현장에서 바로 쓸 수 있도록 개념, 비교, 단계별 명령, 주의점 순서로 정리했어요.

한눈에 보기

ssh 터널링 접속은 별도의 프로토콜이 아니에요. 하나의 SSH 연결 안에서 여러 개의 논리 채널을 열고, 그 채널을 TCP 트래픽 전달에 쓰는 구조예요. 연결 자체는 항상 SSH 클라이언트가 서버로 먼저 맺고, 그 위에 "이 주소와 이 포트로 보내 달라"는 요청을 얹는 방식이에요.

그래서 방향을 판단하는 기준은 단순해요. 연결을 시작하는 쪽이 내 노트북인지 원격 서버인지, 그리고 목적지를 하나로 지정하는지 여러 개를 즉석에서 고르는지입니다. 이 두 가지 질문에 답하면 어떤 옵션을 써야 하는지 거의 결정돼요.

터널은 인증을 우회하는 수단이 아니에요. SSH 로그인이 가능한 계정의 권한 범위 안에서만 동작하고, 서버 쪽 설정에서 포워딩을 막아 두면 명령이 거부돼요. 이 점을 먼저 기억해 두면 운영 환경에서 오해가 줄어듭니다.

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

구분옵션연결을 시작하는 쪽목적지 지정 방식대표 사용 상황서버 쪽 확인 사항
로컬 포워딩-L내 PC내가 미리 고정사내 DB, 내부 대시보드, 프라이빗 API 접근서버에서 목적지로 나가는 경로
원격 포워딩-R원격 서버내가 미리 고정외부에서 사내 개발 PC나 내부 서비스로 접근GatewayPorts, 방화벽 인바운드
동적 포워딩-D내 PC클라이언트가 매번 결정브라우저·CLI 도구의 SOCKS 프록시AllowTcpForwarding
점프 호스트-J내 PC경유지만 지정베스천 서버를 거쳐 내부 호스트 접속중간 서버 접근 권한

표에서 눈여겨볼 부분은 "연결을 시작하는 쪽"이에요. 로컬 포워딩은 내 PC가 먼저 듣고 있다가 트래픽을 SSH 너머로 밀어 넣고, 원격 포워딩은 반대로 원격 서버가 먼저 듣고 있다가 나에게 밀어 넣어요. 같은 SSH 연결을 쓰지만 누가 리스너 역할을 하느냐가 완전히 달라지는 셈이에요.

단계별로 ssh 터널링 접속하기

준비: 접속 정보와 포트 확인

가장 먼저 확인할 것은 세 가지예요. SSH 로그인이 되는 계정과 키, 목적지 서비스의 호스트와 포트, 그리고 사용할 로컬 포트가 이미 점유되어 있지 않은지입니다. 로컬 포트 점유 여부는 ss -lntp로 확인할 수 있어요.

목적지 주소는 "서버에서 바라본 주소"라는 점도 함께 기억해 주세요. 127.0.0.1이라고 적으면 내 PC가 아니라 SSH 서버 자신을 가리켜요. 사내 DB가 SSH 서버와 같은 호스트에 있다면 127.0.0.1이 맞고, 다른 내부 호스트에 있다면 그 내부 주소나 사내 DNS 이름을 적어야 해요.

로컬 포워딩으로 내부 서비스 접근하기

가장 자주 쓰는 형태예요. 내 PC의 특정 포트를 열고, 그 포트로 들어온 트래픽을 SSH 서버를 거쳐 목적지로 전달해요. 예를 들어 ssh -L 15432:db.internal:5432 user@bastion.example.com이라고 실행하면, 내 PC의 로컬 포트로 접속했을 때 베스천 서버 너머의 DB로 연결돼요.

명령은 -L [내 주소:]내 포트:목적지 호스트:목적지 포트 순서로 읽으면 됩니다. 내 주소를 생략하면 기본적으로 로컬 루프백에만 바인딩돼요. 같은 네트워크의 다른 사람에게도 노출하려면 주소를 명시해야 하는데, 운영 환경에서는 가급적 피하는 편이 안전해요.

터널이 열린 동안에는 별도 창에서 목적지 서비스에 접속하면 돼요. DB 클라이언트라면 호스트를 로컬 루프백, 포트를 위에서 정한 로컬 포트로 지정합니다. -N을 붙이면 원격 명령을 실행하지 않고 포워딩만 유지할 수 있어서, 터널 전용 세션을 만들 때 편해요.

원격 포워딩으로 안쪽 서비스 노출하기

원격 포워딩은 반대 방향이에요. 원격 서버가 리스너가 되고, 그 포트로 들어온 연결을 SSH 클라이언트 쪽으로 가져옵니다. ssh -R 8080:localhost:3000 user@public.example.com이라고 실행하면, 원격 서버의 특정 포트로 들어온 요청이 내 PC에서 실행 중인 애플리케이션으로 전달돼요.

이 형태는 외부에서 접근하기 어려운 개발 PC의 로컬 서버를 잠깐 보여줘야 할 때 유용해요. 다만 원격 서버 쪽에서 리스너를 열어야 하므로 GatewayPorts 설정과 방화벽 인바운드 규칙을 함께 확인해야 해요. 기본 설정에서는 루프백에만 바인딩되는 경우가 많아서, 외부 인터페이스로 열려면 서버 관리자와 합의가 필요합니다.

동적 포워딩으로 SOCKS 프록시 만들기

동적 포워딩은 목적지를 미리 정하지 않아요. ssh -D 1080 user@bastion.example.com처럼 실행하면 로컬에 SOCKS 프록시가 열리고, 클라이언트가 요청할 때마다 목적지가 결정돼요. 브라우저나 curl --socks5 같은 도구의 프록시 설정에 이 주소를 넣으면, 여러 내부 호스트를 오가며 확인할 수 있어요.

편리한 대신 트래픽이 어디로 향하는지 명령줄에 드러나지 않는다는 점은 기억해야 해요. 운영 서버를 상대로 쓸 때는 어떤 목적지에 접근할지 미리 정해 두고 쓰는 편이 감사와 재현 측면에서 유리해요.

설정 파일로 터널 자동화하기

매번 긴 명령을 입력하는 대신 ~/.ssh/config에 호스트 블록을 만들어 두면 터널 설정을 재사용할 수 있어요. Host 항목으로 별칭을 정하고, 그 아래에 HostName, User, IdentityFile, LocalForward, RemoteForward, DynamicForward 같은 지시자를 나열하는 구조예요. 이후에는 ssh 별칭만 입력하면 같은 터널이 열립니다.

설정 파일에 넣어 두면 좋은 지시자가 몇 가지 더 있어요. ServerAliveInterval과 ServerAliveCountMax는 유휴 상태에서 세션이 조용히 끊기는 상황을 줄여 주고, ExitOnForwardFailure는 포워딩이 실패했을 때 세션을 유지하지 않고 바로 종료하게 해요. 배포 스크립트나 백그라운드 작업에서 터널을 쓸 때 특히 유용합니다.

여러 홉을 거쳐야 한다면 ProxyJump를 활용해 보세요. 베스천을 거쳐 내부 호스트로 들어가는 경로를 설정 파일에 한 번만 적어 두면, 이후 접속은 단일 호스트처럼 다룰 수 있어요. 이 경우에도 각 구간의 계정과 키 권한은 따로 관리해야 합니다.

상황별 선택 가이드

내 PC에서만 내부 서비스에 닿으면 되는 상황이라면 로컬 포워딩이 가장 단순해요. 목적지가 명확하고, 권한 범위도 좁게 유지할 수 있어요.

외부에서 사내 자원으로 들어와야 한다면 원격 포워딩을 검토하게 되는데, 이때는 서버 설정과 방화벽 변경이 필요할 수 있어요. 상시 운영 용도라면 터널 하나에 의존하기보다 조직의 표준 접근 경로를 따르는 편이 안전합니다.

여러 목적지를 오가며 브라우저로 확인해야 한다면 동적 포워딩이 편해요. 반대로 목적지가 정해져 있고 반복 작업이라면 로컬 포워딩과 설정 파일 조합이 재현성 면에서 낫습니다.

경유 서버가 여러 단계라면 -J나 ProxyJump로 홉을 정리하세요. 터널을 여러 개 중첩하기보다 경로를 설정으로 명시하는 쪽이 장애 원인을 찾기 쉬워요.

주의할 점

터널은 SSH 계정 권한을 그대로 물려받아요. 터널을 열어 준 사람이 곧 그 목적지에 접근할 수 있는 사람이므로, 공용 계정으로 터널을 공유하는 방식은 피해야 해요. 누가 언제 어떤 포워딩을 열었는지 남기려면 서버의 SSH 로그와 인증 로그를 함께 확인해야 합니다.

로컬 포워딩에서 바인딩 주소를 넓게 잡으면 내 PC가 중계 지점이 될 수 있어요. 특별한 이유가 없다면 루프백 바인딩을 유지하고, 필요할 때만 범위를 넓히세요.

세션이 끊기면 터널도 함께 끊긴다는 점도 운영에서 자주 발목을 잡아요. 유휴 시간이 긴 작업이라면 keepalive 관련 지시자를 설정하고, 재연결 정책을 프로세스 관리 도구 쪽에서 함께 다루는 편이 좋아요. 터널 프로세스가 남아 포트를 점유하고 있지 않은지도 주기적으로 확인해 주세요.

서버 쪽에서 포워딩을 제한해 둔 경우에는 명령이 거부돼요. AllowTcpForwarding이나 GatewayPorts 같은 설정은 관리자 권한 영역이므로, 임의로 우회하려 하지 말고 정해진 절차를 따르는 것이 맞습니다.

자주 묻는 질문

ssh 터널링 접속은 VPN과 무엇이 다른가요?

VPN은 네트워크 전체를 통로에 태우는 방식이고, ssh 터널링 접속은 지정한 포트나 프록시 경로만 SSH 세션 위로 보내는 방식이에요. 범위가 좁은 대신 설정이 가볍고, 이미 열어 둔 SSH 접근 권한만 있으면 바로 쓸 수 있어요. 다만 라우팅이나 DNS까지 통째로 다뤄야 하는 요구에는 VPN이 더 적합합니다.

터널이 끊기면 자동으로 다시 연결할 수 있나요?

SSH 자체는 끊긴 세션을 자동으로 복구하지 않아요. ServerAliveInterval 같은 지시자로 끊김을 늦추거나 빨리 감지할 수는 있지만, 재연결은 별도의 프로세스 관리 수단이 필요해요. 운영에서는 터널을 서비스 단위로 등록해 두고 재시작 정책을 함께 정의하는 편이 안정적입니다.

서버에서 포워딩을 막아 두면 어떻게 되나요?

포워딩 요청이 거부되고 터널이 열리지 않아요. 이때는 설정을 바꾸려 하기보다 왜 막혀 있는지 확인하는 것이 먼저예요. 접근 경로가 정해져 있는 조직이라면 베스천 정책이나 별도 접근 도구를 안내받는 쪽이 맞습니다.

동적 포워딩은 어떤 프로그램에서 쓸 수 있나요?

SOCKS 프록시를 지원하는 클라이언트라면 대부분 사용할 수 있어요. 브라우저의 프록시 설정, curl의 SOCKS 옵션, 여러 언어의 HTTP 클라이언트 라이브러리가 해당돼요. 프록시 설정을 지원하지 않는 도구는 로컬 포워딩으로 목적지를 하나씩 지정하는 편이 낫습니다.

로컬 포워딩에서 목적지 주소는 어느 쪽 기준인가요?

목적지 주소는 SSH 서버에서 바라본 주소 기준이에요. 그래서 127.0.0.1은 내 PC가 아니라 SSH 서버 자신을 가리켜요. 이 기준을 헷갈리면 연결이 되지 않거나 엉뚱한 서비스에 붙을 수 있으니, 목적지가 서버와 같은 호스트인지부터 확인해 주세요.

출처

터널을 실제 운영에 붙일 때는 접속 자체보다 세션을 어떻게 유지하고 로그를 어떻게 남길지가 더 오래 문제가 됩니다. 함께 보면 좋은 글: systemd로 장기 실행 프로세스 관리하기와 SSH 접속 로그와 인증 실패 확인하기를 참고해 보세요.