1P by baeba | ★ favorite | 댓글과 토론

요약 개요

  • SSH 터널은 외부에서 직접 접근할 수 없는 서비스에 안전하게 접속하거나, 내부 서비스를 외부에 임시로 공개하는 기술이다.
  • SSH 포트 포워딩은 크게 로컬 포워딩, 원격 포워딩, 동적 로컬 포워딩, 동적 원격 포워딩으로 구분된다.
  • -L은 로컬 SSH 클라이언트가 포트를 열고, -R은 원격 SSH 서버가 포트를 연다.
  • Bastion Host를 활용하면 SSH 서버 자체뿐 아니라 해당 서버가 접근할 수 있는 다른 사설망 서비스에도 연결할 수 있다.
  • 동적 포워딩은 특정 목적지를 고정하지 않고 SOCKS 프록시를 생성해 여러 호스트와 포트에 접근하게 한다.
  • 원격 포워딩을 외부 네트워크에 공개하려면 SSH 서버의 GatewayPorts 설정을 검토해야 한다.

서론

SSH 터널의 목적

  • SSH는 원격 명령 실행뿐 아니라 네트워크 트래픽을 암호화해 전달하는 터널 기능을 제공한다.

  • 별도의 VPN이나 전용 프록시 프로그램 없이 표준 SSH 명령만으로 사설망 접근과 서비스 공개가 가능하다.

  • 대표적인 활용 사례는 다음과 같다.

    • 공개 서버를 경유해 내부 VPC 서비스에 접속
    • 원격 개발 서버의 로컬 포트를 사용자 PC의 브라우저에서 열기
    • 가정이나 사설망의 서비스를 외부에 임시 공개
    • 로컬 브라우저의 디버깅 포트를 원격 개발 에이전트에 연결
  • SSH 터널을 이해할 때는 다음 두 가지를 구분해야 한다.

    • 어느 장비가 새로운 포트를 열고 대기하는가
    • 터널을 통과한 트래픽이 어느 장비의 관점에서 목적지에 접속하는가

본론

로컬 포워딩은 원격 서비스를 로컬에 연결한다

  • 로컬 포트 포워딩은 원격 서버 또는 원격 서버가 접근할 수 있는 서비스를 사용자 PC의 로컬 포트로 연결하는 방식이다.
  • 기본 명령 구조는 다음과 같다.
ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr  
  • SSH 클라이언트가 사용자 PC의 local_port에서 연결을 기다린다.

  • 해당 포트로 들어온 트래픽은 SSH 터널을 거쳐 remote_addr:remote_port로 전달된다.

  • 최종 목적지에는 SSH 서버가 위치한 네트워크의 관점에서 접속한다.

  • 주요 활용 사례는 다음과 같다.

    • 원격 MySQL, PostgreSQL, Redis 접속
    • 사설망에서만 열리는 웹 애플리케이션 접속
    • 서버의 외부 인터페이스에 공개하지 않은 컨테이너 포트 접속

Bastion Host는 사설망 접근을 중계한다

  • remote_addr와 SSH 접속 대상인 sshd_addr는 동일한 장비일 필요가 없다.

  • SSH 서버가 다른 내부 서비스에 접근할 수 있다면 해당 서버를 중계 지점으로 사용할 수 있다.

  • 이러한 중계 서버를 Bastion Host 또는 Jump Host라고 한다.

  • 일반적인 연결 구조는 다음과 같다.

    • 사용자 PC에서 공개 Bastion Host로 SSH 접속
    • Bastion Host가 접근할 수 있는 VPC 내부 서비스로 트래픽 전달
  • 이를 통해 외부에 공개되지 않은 데이터베이스, 검색 클러스터, 내부 API 등에 접속할 수 있다.

원격 포워딩은 로컬 서비스를 원격에 공개한다

  • 원격 포트 포워딩은 사용자 PC나 내부망의 서비스를 외부 SSH 서버의 포트에 연결하는 방식이다.
  • 기본 명령 구조는 다음과 같다.
ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr  
  • 원격 SSH 서버가 remote_port를 열고 연결을 기다린다.

  • 해당 포트로 들어온 트래픽은 SSH 터널을 통해 SSH 클라이언트 쪽의 local_addr:local_port로 전달된다.

  • 주요 활용 사례는 다음과 같다.

    • 노트북에서 실행 중인 개발 서버를 외부 데모용으로 공개
    • 홈랩 서비스를 인터넷에서 접근하도록 연결
    • 로컬 브라우저의 디버깅 포트를 원격 개발 환경에 제공

외부 공개에는 GatewayPorts 설정이 필요하다

  • 기본 설정에서는 원격 포워딩 포트가 SSH 서버의 localhost에만 바인딩될 수 있다.
  • 이 경우 해당 서비스는 원격 서버 내부에서는 접속할 수 있지만 외부에서는 접근할 수 없다.
  • 원격 서버의 공인 IP를 통해 접속하게 하려면 sshd_config에서 다음 설정을 검토해야 한다.
GatewayPorts yes  
  • 이 설정은 포트를 외부 인터페이스에 노출할 수 있으므로 방화벽과 접근 제어를 함께 적용해야 한다.
  • 개발 서비스를 공개 인터넷에 직접 노출하면 인증되지 않은 접근이나 공격 가능성이 증가할 수 있다.

로컬 장비는 사설망의 Jump Host가 될 수 있다

  • 원격 포워딩의 목적지는 SSH 클라이언트가 실행되는 장비 자체에 한정되지 않는다.

  • 사용자 PC가 홈 네트워크의 다른 서버에 접근할 수 있다면 그 내부 서버의 포트도 원격 SSH 서버를 통해 공개할 수 있다.

  • 이때 사용자 PC는 다음 두 네트워크를 연결하는 중계 장비가 된다.

    • 홈 네트워크 또는 사설 개발망
    • 공인 SSH 게이트웨이 서버
  • 이를 이용하면 인터넷에 직접 연결되지 않은 홈 서버나 내부 개발 서버의 서비스를 외부에서 접근할 수 있다.

동적 로컬 포워딩은 로컬 SOCKS 프록시를 만든다

  • 일반 로컬 포워딩은 하나의 로컬 포트를 하나의 목적지에 고정한다.
  • 동적 로컬 포워딩은 SSH 클라이언트에 SOCKS 프록시를 생성한다.
  • 기본 명령 구조는 다음과 같다.
ssh -D [local_addr:]local_port [user@]sshd_addr  
  • 사용자 PC의 지정 포트에서 SOCKS 프록시가 실행된다.

  • SOCKS를 지원하는 애플리케이션은 연결할 때마다 서로 다른 목적지 주소와 포트를 지정할 수 있다.

  • 실제 목적지 연결은 원격 SSH 서버의 네트워크 관점에서 이루어진다.

  • 하나의 SSH 연결로 원격 사설망의 여러 서비스에 접근할 수 있다는 점이 고정형 로컬 포워딩과의 차이이다.

  • 주요 활용 사례는 다음과 같다.

    • Bastion Host를 통한 여러 내부 API 호출
    • 사설망 내부 웹 애플리케이션 탐색
    • 하나의 EC2 인스턴스를 통한 여러 VPC 엔드포인트 접속

동적 원격 포워딩은 원격 SOCKS 프록시를 만든다

  • -R 옵션에서 고정 목적지를 생략하면 원격 SSH 서버에 SOCKS 프록시를 생성할 수 있다.
  • 기본 명령 구조는 다음과 같다.
ssh -R [bind_address:]port [user@]gateway_addr  
  • 원격 게이트웨이 서버가 지정한 포트에서 SOCKS 연결을 기다린다.
  • 프록시로 들어온 요청은 SSH 터널을 통해 클라이언트 쪽으로 전달된다.
  • 최종 목적지는 SSH 클라이언트가 위치한 네트워크의 관점에서 연결된다.
  • 이를 이용하면 원격 서버에서 사용자 PC가 접근할 수 있는 전체 홈 네트워크나 사설망에 접근할 수 있다.
  • 동적 원격 포워딩은 클라이언트에 OpenSSH 7.6 이상이 필요하다.
  • 원격 SOCKS 프록시를 외부 인터페이스에 공개하려면 일반 원격 포워딩과 마찬가지로 GatewayPorts 설정이 필요하다.

백그라운드 실행 옵션은 터널만 유지한다

  • SSH 접속 후 명령을 실행하지 않고 포트 포워딩만 유지하려면 -N 옵션을 사용한다.
  • 터널을 백그라운드로 전환하려면 -f 옵션을 함께 사용할 수 있다.
  • 유형별 예시는 다음과 같다.
ssh -f -N -L ...  
ssh -f -N -R ...  
ssh -f -N -D ...  
  • 자동화나 장시간 운영 환경에서는 터널 종료, 재접속, 장애 감지 방식도 별도로 마련해야 한다.

명령은 포트를 여는 위치로 구분한다

  • ssh -L은 로컬 SSH 클라이언트가 새로운 포트를 연다.
  • ssh -R은 원격 SSH 서버가 새로운 포트를 연다.
  • ssh -D는 로컬 SSH 클라이언트에 SOCKS 프록시를 만든다.
  • 목적지를 생략한 ssh -R은 원격 SSH 서버에 SOCKS 프록시를 만든다.
  • 명령을 기억하는 기본 규칙은 다음과 같다.
-L = local:remote  
-R = remote:local  
  • 콜론을 기준으로 왼쪽에 있는 주소와 포트가 새롭게 열리는 리스닝 지점이다.
  • local은 SSH 클라이언트 자체 또는 클라이언트가 접근할 수 있는 내부 장비를 의미할 수 있다.
  • remote는 SSH 서버 자체 또는 서버가 접근할 수 있는 다른 내부 장비를 의미할 수 있다.

결론

SSH 터널은 접근 방향에 따라 선택한다

  • 원격 서비스를 내 PC에서 사용하려면 로컬 포워딩 -L을 사용한다.

  • 내 PC나 내부 서비스를 원격 서버 쪽에 공개하려면 원격 포워딩 -R을 사용한다.

  • 원격망의 여러 목적지에 유동적으로 접근하려면 동적 로컬 포워딩 -D를 사용한다.

  • 클라이언트 측 네트워크 전체를 원격 게이트웨이에서 유동적으로 접근하게 하려면 목적지를 생략한 동적 원격 포워딩 -R을 사용한다.

  • SSH 터널을 설계할 때는 다음 항목을 우선 확인해야 한다.

    • 새 포트를 열어야 하는 위치
    • 최종 목적지에 접근할 수 있는 장비
    • GatewayPorts, 방화벽, SSH 접근 권한 설정
    • 외부 공개로 인해 발생할 수 있는 보안 위험
  • 핵심 판단 기준은 서비스를 어느 쪽에 보이게 할 것인지와 어느 장비가 목적지에 실제로 접근할 수 있는지이다.

댓글과 토론