<src="photo.png">

SSH Config로 SSH 접속 편하게 하기: Port Forward 설정까지 정리 본문

개발

SSH Config로 SSH 접속 편하게 하기: Port Forward 설정까지 정리

samsonites89 2026. 6. 14. 19:23

TL:DR

- ~/.ssh/config 를 쓰면 긴 SSH 명령어를 ssh dev처럼 줄일 수 있다.
- 포트포워딩은 LocalForward, RemoteForward, DynamicForward 3개만 먼저 이해하면 된다.
- DB, Redis, 내부 관리자 페이지 접속할 때 SSH Config가 꽤 든든하다.

 

SSH 접속.

개발하다 보면 SSH 접속 명령어가 생각보다 길어진다.

ssh -i ~/.ssh/dev.pem -p 2222 ubuntu@203.0.113.10

 

여기까지는 그래도 괜찮다. 그런데 여기에 포트포워딩까지 붙으면 슬슬 보기 싫어진다.

ssh -i ~/.ssh/dev.pem -p 2222 -L 5432:127.0.0.1:5432 ubuntu@203.0.113.10

 

한두 번이면 그냥 치겠는데, 매번 치기에는 귀찮다.
특히 회사 개발 서버, Bastion 서버, DB 터널링, Redis 터널링처럼 자주 쓰는 접속 정보라면 더 그렇다.

 

이럴 때 사용하는 게 바로 SSH Config다.
보통 ~/.ssh/config 파일에 서버 접속 정보를 미리 적어두고, 이후에는 짧은 이름으로 접속한다.

ssh dev-db

 

개인적으로 SSH Config의 진짜 장점은 단순히 접속 명령어를 줄이는 데서 끝나지 않는다고 생각한다.
특히 Port Forward, 그러니까 포트포워딩 설정을 같이 관리할 수 있다는 점이 꽤 크다.

 

다만 여기서 한 가지 짚고 넘어가야 한다.


OpenSSH 설정에 PortForward라는 단일 필드가 있는 것은 아니다.
보통 우리가 말하는 “SSH Port Forward 설정”은 아래 3가지 필드를 의미한다.

  • LocalForward
  • RemoteForward
  • DynamicForward

이 글에서는 SSH Config 기본 구조와 함께, 포트포워딩 관련 필드를 중심으로 각 설정값을 정리해보려고 한다.

SSH Config 파일 위치

SSH Config 파일은 보통 아래 위치에 만든다.

~/.ssh/config

파일이 없다면 직접 만들면 된다.

touch ~/.ssh/config
chmod 600 ~/.ssh/config

기본 SSH Config 예시

먼저 가장 기본적인 형태부터 보자.

Host dev
    HostName 203.0.113.10
    User ubuntu
    Port 2222
    IdentityFile ~/.ssh/dev.pem
    IdentitiesOnly yes

이렇게 작성해 두면 앞으로는 아래처럼 접속할 수 있다.

ssh dev

기존에 길게 입력하던 명령어를 거의 별칭처럼 줄여주는 느낌이다.

ssh -i ~/.ssh/dev.pem -p 2222 ubuntu@203.0.113.10

각 필드 설명

Host

Host dev

Host는 SSH 접속 시 사용할 별칭이다.

 

여기서 dev가 바로 Host 값이다.
실제 도메인이나 IP일 필요는 없다. 내가 기억하기 쉬운 이름이면 된다.

예를 들어 아래처럼 나눠둘 수 있다.

Host dev
Host staging
Host prod
Host dev-db

실무에서는 서버 역할에 맞게 이름을 정해두면 꽤 편하다.

HostName

HostName 203.0.113.10

 

HostName은 실제 접속할 서버 주소다.
IP 주소를 넣어도 되고, 도메인을 넣어도 된다.

HostName dev.example.com

Host는 내가 쓰는 별칭이고, HostName은 실제 목적지라고 보면 된다.

User

User ubuntu

User는 SSH 접속에 사용할 계정명이다.

AWS EC2라면 ubuntu, ec2-user를 쓰는 경우가 많고, 일반 리눅스 서버라면 deploy, admin, 개인 계정 등을 사용할 수 있다.

이 값을 적어두면 매번 아래처럼 입력하지 않아도 된다.

ssh ubuntu@203.0.113.10

 

유저 값을 잘 모르겠다면 whoami 추천

Port

Port 2222

 

Port는 SSH 서버에 접속할 포트다. 기본값은 22다.

보안이나 운영 정책 때문에 SSH 포트를 2222, 22022처럼 바꿔두는 경우도 있다.

 

이럴 때 Port를 config에 적어두면 매번 -p 2222를 붙이지 않아도 된다.

여기서 주의할 점이 있다.
PortSSH 접속 포트다.

 

DB 포트나 Redis 포트 같은 서비스 포트가 아니다.

포트포워딩에서 사용하는 포트는 뒤에서 설명할 LocalForward, RemoteForward, DynamicForward 쪽에 적는다.

IdentityFile

IdentityFile ~/.ssh/dev.pem

IdentityFile은 SSH 접속에 사용할 개인 키 파일 경로다.

 

예를 들어 AWS에서 받은. pem 파일이나, 직접 생성한 id_ed25519 같은 키를 지정한다.

IdentityFile ~/.ssh/id_ed25519

서버마다 다른 키를 쓰는 경우에는 SSH Config에 넣어두는 게 거의 필수에 가깝다.
안 그러면 매번 -i 옵션을 붙여야 한다.

IdentitiesOnly

IdentitiesOnly yes

 

IdentitiesOnly yes는 지정한 IdentityFile만 사용하겠다는 의미다.

로컬에 SSH 키가 여러 개 있고, ssh-agent에 여러 키가 올라가 있는 경우가 있다.

 

이때 SSH 클라이언트가 여러 키를 순서대로 시도하다가 서버에서 인증 실패 횟수 제한에 걸리는 경우가 있다.

그럴 때 IdentitiesOnly yes를 같이 적어두면 설정한 키 위주로 깔끔하게 접속할 수 있다.

핵심: SSH Config에서 Port Forward 설정하기

이제 핵심인 포트포워딩이다.

SSH 포트포워딩은 간단히 말하면, 내 로컬 포트와 원격 서버 또는 원격 네트워크 안의 포트를 SSH 터널로 연결하는 기능이다.

예를 들어 운영 DB가 외부에 직접 공개되어 있지 않고, Bastion 서버를 통해서만 접근 가능하다고 해보자.

이 경우 로컬에서 아래처럼 접속하고 싶을 수 있다.

psql -h 127.0.0.1 -p 5432

하지만 실제 DB는 원격 서버나 사설망 안에 있다.

 

이때 LocalForward를 사용하면 로컬의 5432 포트를 원격 DB 포트로 연결할 수 있다.

LocalForward

LocalForward 127.0.0.1:5432 127.0.0.1:5432

 

LocalForward는 가장 자주 쓰는 포트포워딩 방식이다.

 

로컬 PC의 특정 포트로 들어온 요청을 SSH 서버 기준의 목적지로 전달한다.

형태는 대략 이렇게 보면 된다.

LocalForward [로컬에서_열_주소:]로컬포트 목적지호스트:목적지포트

예시는 아래와 같다.

Host dev-db
    HostName 203.0.113.10
    User ubuntu
    Port 2222
    IdentityFile ~/.ssh/dev.pem
    IdentitiesOnly yes

    LocalForward 127.0.0.1:5432 127.0.0.1:5432

이 설정은 이런 의미다.

  • 내 로컬 PC의 127.0.0.1:5432를 연다.
  • dev-db 서버에 SSH로 접속한다.
  • 로컬 5432로 들어온 요청을 SSH 터널을 통해 원격 서버 기준 127.0.0.1:5432로 보낸다.

즉, 원격 서버 안에서만 접근 가능한 PostgreSQL을 내 로컬에서 접근하는 느낌으로 사용할 수 있다.

psql -h 127.0.0.1 -p 5432 -U postgres

여기서 헷갈리기 쉬운 포인트가 있다.
두 번째 127.0.0.1:5432는 내 로컬 기준이 아니라 SSH 서버에서 바라본 주소다.

예를 들어 DB가 같은 서버 안에 있으면 이렇게 쓴다.

LocalForward 127.0.0.1:5432 127.0.0.1:5432

DB가 같은 VPC 내부의 별도 서버에 있으면 이렇게 쓸 수 있다.

LocalForward 127.0.0.1:5432 private-db.example.internal:5432

이 차이를 이해하면 SSH 터널링이 훨씬 덜 헷갈린다.

LocalForward를 여러 개 쓰기

포트포워딩은 여러 개를 동시에 설정할 수도 있다.

Host dev-tunnel
    HostName bastion.example.com
    User ubuntu
    IdentityFile ~/.ssh/dev.pem
    IdentitiesOnly yes

    LocalForward 127.0.0.1:5432 private-db.example.internal:5432
    LocalForward 127.0.0.1:6379 private-redis.example.internal:6379
    LocalForward 127.0.0.1:8080 private-admin.example.internal:80

이렇게 해두면 SSH 접속 한 번으로 DB, Redis, 내부 관리자 페이지 터널을 같이 열 수 있다.

ssh dev-tunnel

이후 로컬에서는 아래처럼 접근하면 된다.

psql -h 127.0.0.1 -p 5432
redis-cli -h 127.0.0.1 -p 6379
open http://127.0.0.1:8080

개발 환경에서 은근 자주 쓰게 되는 패턴이다.

RemoteForward

RemoteForward 9000 127.0.0.1:3000

RemoteForwardLocalForward와 방향이 반대다.

 

로컬에 떠 있는 서비스를 원격 서버에서 접근할 수 있게 만들 때 사용한다.
예를 들어 내 로컬에서 개발 서버가 3000 포트로 떠 있고, 원격 서버에서 이 서비스를 9000 포트로 접근해야 한다고 해보자.

Host reverse-tunnel
    HostName 203.0.113.10
    User ubuntu
    IdentityFile ~/.ssh/dev.pem

    RemoteForward 9000 127.0.0.1:3000

 

이 경우 원격 서버 입장에서는 127.0.0.1:9000으로 접속했을 때, 내 로컬 PC의 127.0.0.1:3000으로 연결된다.

다만 RemoteForward는 서버 설정의 영향을 받을 수 있다.
원격 서버의 SSH 데몬 설정에서 포트포워딩을 허용하지 않으면 동작하지 않을 수 있다.

 

일반적인 개발 환경에서는 LocalForward를 훨씬 더 자주 쓰고, RemoteForward는 웹훅 테스트나 임시 reverse tunnel이 필요할 때 쓰는 편이다.

DynamicForward

DynamicForward 127.0.0.1:1080

DynamicForward는 SOCKS 프록시를 만드는 방식이다.

특정 목적지 하나를 지정하는 LocalForward와 다르게, 애플리케이션이 요청하는 목적지를 SSH 터널을 통해 동적으로 연결한다.

Host socks-proxy
    HostName 203.0.113.10
    User ubuntu
    IdentityFile ~/.ssh/dev.pem

    DynamicForward 127.0.0.1:1080

이렇게 설정한 뒤 브라우저나 애플리케이션의 SOCKS 프록시를 127.0.0.1:1080으로 맞추면, 해당 트래픽이 SSH 서버를 통해 나가게 된다. 개인적으로는 DB 터널링에는 LocalForward, 특정 네트워크를 브라우저로 확인할 때는 DynamicForward 정도로 구분해서 생각하면 편했다.

터널만 열고 싶다면 SessionType none

포트포워딩만 쓰고 원격 서버 셸은 열 필요가 없는 경우도 많다.
그럴 때는 아래처럼 SessionType none을 사용할 수 있다.

Host dev-tunnel
    HostName bastion.example.com
    User ubuntu
    IdentityFile ~/.ssh/dev.pem
    IdentitiesOnly yes

    LocalForward 127.0.0.1:5432 private-db.example.internal:5432
    LocalForward 127.0.0.1:6379 private-redis.example.internal:6379

    SessionType none

명령어의 ssh -N과 비슷하게, 원격 명령이나 셸 실행 없이 터널만 열겠다는 의미다.

ssh dev-tunnel

터널 전용 설정이라면 이 옵션을 넣어두는 것도 깔끔하다.

포트포워딩에서 같이 쓰면 좋은 옵션

ExitOnForwardFailure

ExitOnForwardFailure yes

 

포트포워딩 설정이 실패했을 때 SSH 접속을 종료할지 정하는 옵션이다.

예를 들어 로컬 5432 포트를 이미 다른 프로세스가 쓰고 있다면 LocalForward가 실패할 수 있다.
그런데 이때 SSH 접속만 성공하고 포트포워딩은 실패하면 꽤 헷갈린다.

“어? SSH 접속은 됐는데 왜 DB 접속이 안 되지?” 같은 상황이 생긴다.

그래서 포트포워딩 목적의 config라면 개인적으로 아래 옵션을 자주 넣는 편이다.

ExitOnForwardFailure yes

포워딩 실패 시 바로 실패하도록 만들어두면 문제를 빨리 알아차릴 수 있다.

ServerAliveInterval / ServerAliveCountMax

ServerAliveInterval 30
ServerAliveCountMax 3

SSH 터널을 오래 열어두면 중간에 네트워크가 바뀌거나, VPN이 끊기거나, 노트북이 잠자기 모드에 들어갔다가 깨어나는 일이 있다.

이때 터널이 죽었는데도 살아있는 것처럼 보이면 더 귀찮다.

ServerAliveInterval은 일정 시간 동안 서버로부터 데이터가 없으면 확인 메시지를 보내는 설정이다.
ServerAliveCountMax는 응답이 없을 때 몇 번까지 시도할지 정한다.

예를 들어 아래 설정은 30초마다 확인하고, 3번 응답이 없으면 끊는 방식으로 볼 수 있다.

ServerAliveInterval 30
ServerAliveCountMax 3

터널을 오래 열어두는 개발 환경에서는 꽤 유용하다.

실사용 예시: Bastion 서버 통해 DB 접속하기

아래는 실제로 가장 많이 쓰는 형태에 가까운 예시다.

Host dev-db-tunnel
    HostName bastion.example.com
    User ubuntu
    Port 22
    IdentityFile ~/.ssh/dev-bastion.pem
    IdentitiesOnly yes

    LocalForward 127.0.0.1:5432 dev-postgres.internal:5432

    ExitOnForwardFailure yes
    ServerAliveInterval 30
    ServerAliveCountMax 3
    SessionType none

이제 터널을 열 때는 이렇게 한다.

ssh dev-db-tunnel

그리고 로컬에서 DB 클라이언트는 이렇게 연결한다.

psql -h 127.0.0.1 -p 5432 -U app_user

DBeaver, TablePlus, DataGrip 같은 GUI DB 클라이언트에서도 host를 127.0.0.1, port를 5432로 잡으면 된다.

이 방식의 장점은 DB를 외부에 직접 노출하지 않아도 된다는 점이다.

 

Bastion 서버를 통해 SSH 인증을 거친 뒤, 내부 네트워크에 있는 DB로 접근하는 구조라서 개발 환경에서 많이 쓴다.

자주 헷갈리는 포인트

1. Port와 LocalForward의 포트는 다르다

Port 22
LocalForward 127.0.0.1:5432 dev-postgres.internal:5432

Port는 SSH 접속 포트다.
LocalForward5432는 로컬에서 열 포트와 목적지 서비스 포트다.

 

이 둘을 같은 개념으로 보면 헷갈린다.

2. LocalForward의 목적지 주소는 서버 기준이다

LocalForward 127.0.0.1:5432 127.0.0.1:5432

 

뒤쪽 127.0.0.1:5432는 내 맥북의 localhost가 아니다.
SSH로 접속한 서버 입장에서의 localhost다.

이 부분이 SSH 터널링에서 가장 많이 헷갈리는 포인트라고 생각한다.

3. 로컬 bind 주소는 웬만하면 127.0.0.1로 둔다

LocalForward 127.0.0.1:5432 dev-postgres.internal:5432

로컬에서만 쓸 거라면 127.0.0.1로 제한하는 게 안전하다.

아래처럼 모든 인터페이스에 열어버리면 같은 네트워크의 다른 장비에서도 접근 가능한 상황이 생길 수 있다.

LocalForward 0.0.0.0:5432 dev-postgres.internal:5432

특별한 이유가 없다면 로컬 개발용 터널은 127.0.0.1로 묶어두는 걸 추천한다.

마무리

SSH Config는 처음에는 단순히 SSH 명령어 줄이는 용도로 쓰게 된다.

ssh dev

그런데 쓰다 보면 진짜 편한 부분은 포트포워딩이다.


LocalForward로 DB나 Redis 터널을 열고, ExitOnForwardFailure로 실패 여부를 바로 확인하고, ServerAliveInterval로 터널 상태까지 챙겨두면 개발 환경이 꽤 깔끔해진다.

개인적으로는 자주 접속하는 서버가 2~3개만 넘어가도 /.ssh/config를 정리해 두는 걸 추천한다.

 

명령어를 외울 필요도 줄고, 서버별 키 파일이나 포트포워딩 설정도 한 곳에서 관리할 수 있어서 나중에 훨씬 편하다.

특히 Bastion 서버를 통해 내부 DB에 접근해야 하는 환경이라면 SSH Config + LocalForward 조합은 거의 필수에 가깝다.

 

 

이상.

출처

'개발' 카테고리의 다른 글

Linux(Ubuntu)에 notion 설치하기  (2) 2024.01.14
Localtunnel  (0) 2023.07.29
M1/M2 맥북에서 Intellij / Jetbrains 터미널 Rosetta로 설정하기  (0) 2023.07.13
[알고리즘] Binary Search  (1) 2021.06.19
[Tool 사용] Clair Image Scanner  (0) 2021.06.14
Comments