Devin.KR
로그인

리눅스 ssh 명령어 사용법 - 접속, 포트 포워딩, 터널링 실전 예제

개발자 조회 2

이 명령어를 언제 쓰는가

ssh는 원격 서버에 접속하는 명령이지만, 실무에서 값어치의 절반은 접속 이외의 용도에 있다. 배스천을 거쳐 사설망 서버에 들어가고, 로컬 PC 의 DB 툴을 방화벽 뒤 MySQL 에 연결하고, 서버 20대에 같은 점검 명령을 한 번에 돌리는 일이 전부 ssh 한 줄이다.

운영 서버가 공인 IP 없이 배스천 뒤에 있는 구성은 이제 기본이다. 매번 배스천에 들어갔다가 다시 들어가는 대신 -J~/.ssh/config 를 쓰면 한 번에 간다. 이걸 아느냐 모르느냐가 하루 작업량을 바꾼다.

기본 형식

ssh [옵션] [사용자@]호스트 [원격에서 실행할 명령]
  • 사용자 — 생략하면 로컬 사용자 이름으로 접속을 시도한다. 로컬 계정명과 서버 계정명이 다르면 반드시 적는다.
  • 원격 명령 — 붙이면 로그인하지 않고 그 명령만 실행한 뒤 종료한다. 스크립트에서 쓰는 형태다.

자주 쓰는 옵션

옵션의미예시
-p 포트접속 포트(소문자 p)ssh -p 22022 deploy@10.0.1.20
-i 키파일사용할 개인키 지정ssh -i ~/.ssh/prod.pem ec2-user@1.2.3.4
-J 경유호스트배스천을 거쳐 접속(ProxyJump)ssh -J bastion app@10.0.1.20
-L 로컬:대상:포트로컬 포트를 원격 쪽으로 전달-L 13306:127.0.0.1:3306
-R 원격:대상:포트원격 포트를 로컬 쪽으로 전달-R 8080:127.0.0.1:3000
-N원격 명령 실행 없이 터널만 유지ssh -N -L 13306:127.0.0.1:3306 bastion
-f인증 후 백그라운드로 보낸다ssh -fN -L ...
-t강제로 TTY 할당. sudo·vim 등에 필요ssh -t host 'sudo systemctl restart nginx'
-o 설정=값설정 파일 항목을 한 번만 덮어쓴다-o ConnectTimeout=5
-v / -vvv접속 과정 디버깅. 인증 실패 원인 추적ssh -vvv deploy@10.0.1.20

실전 예제

1. 접속하지 않고 원격 명령만 실행한다. 서버 여러 대의 상태를 한 번에 훑을 때 쓴다.

for h in web01 web02 web03; do
  echo "== $h"
  ssh -o ConnectTimeout=5 "$h" 'uptime; df -h / | tail -1'
done

ConnectTimeout 이 없으면 죽은 서버 하나에서 반복문 전체가 멈춘다.

2. 방화벽 뒤 DB 에 로컬 툴로 붙는다. 실무에서 가장 많이 쓰는 터널이다. 아래를 실행한 뒤 DB 클라이언트에서 127.0.0.1:13306 으로 접속하면 원격 MySQL 에 연결된다.

ssh -fN -L 13306:127.0.0.1:3306 deploy@bastion.example.com

여기서 127.0.0.1:3306배스천 입장에서 본 주소다. DB 가 별도 서버라면 -L 13306:10.0.2.15:3306 처럼 적는다. 끝낼 때는 pkill -f 'ssh -fN -L 13306' 로 정리한다.

3. 배스천을 거쳐 한 번에 들어간다. 두 번 로그인할 필요가 없다.

ssh -J deploy@bastion.example.com app@10.0.1.20

4. 설정 파일에 별칭을 만들어 손을 줄인다. ~/.ssh/config 에 적어두면 ssh prod-web 한 줄로 끝나고, scp·rsync·git 도 같은 설정을 그대로 쓴다.

Host bastion
    HostName bastion.example.com
    User deploy
    IdentityFile ~/.ssh/id_ed25519

Host prod-web
    HostName 10.0.1.20
    User app
    Port 22022
    ProxyJump bastion
    ServerAliveInterval 30
    ServerAliveCountMax 3

ServerAliveInterval 은 유휴 세션이 NAT 타임아웃으로 조용히 끊기는 것을 막는다. 장시간 작업하는 서버에는 반드시 넣는다.

5. 비밀번호 없이 키로 접속하도록 등록한다. 자동화의 전제 조건이다.

ssh-keygen -t ed25519 -C "deploy@$(hostname)"
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@10.0.1.20

함정과 주의점

개인키 권한이 틀리면 접속 자체가 거부된다. 키 파일을 복사해 오면 권한이 644 로 붙는 경우가 많고, 그러면 이렇게 나온다.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/deploy/.ssh/id_ed25519' are too open.

chmod 600 ~/.ssh/id_ed25519 로 고친다. 서버 쪽 ~/.ssh 는 700, authorized_keys 는 600 이어야 한다. 키를 넣었는데 계속 비밀번호를 묻는다면 십중팔구 서버 쪽 권한 문제다.

호스트 키 경고가 떴을 때 습관적으로 known_hosts 를 지우지 않는다. REMOTE HOST IDENTIFICATION HAS CHANGED 는 서버를 재설치했을 때도 뜨지만, 중간자 공격일 때도 똑같이 뜬다. 서버를 재설치했거나 IP 를 재사용한 것이 확실할 때만 ssh-keygen -R 호스트명 으로 해당 항목만 지운다. 파일 전체를 날리면 다른 서버의 신뢰 정보까지 잃는다.

원격 명령 안의 변수는 로컬에서 먼저 확장된다. 아래 두 줄은 결과가 완전히 다르다.

ssh host "rm -rf $TARGET/*"    # $TARGET 이 로컬에서 빈 값이면 rm -rf /* 가 된다
ssh host 'rm -rf $TARGET/*'    # 원격의 $TARGET 을 쓴다

큰따옴표와 작은따옴표의 차이가 서버 하나를 날린다. 원격에서 평가돼야 할 변수는 반드시 작은따옴표 안에 둔다.

에이전트 포워딩(-A)은 아무 서버에나 켜지 않는다. 그 서버의 root 권한을 가진 사람이 내 키로 다른 서버에 접속할 수 있게 된다. 배스천 경유가 목적이라면 -A 대신 -J(ProxyJump)를 쓴다.

함께 보면 좋은 명령어

  • scp — 파일 한두 개를 빠르게 주고받는다. ssh 설정을 그대로 쓴다.
  • rsync — 디렉터리 동기화와 재개 가능한 전송. -e ssh 로 같은 통로를 탄다.
  • tmux — 세션이 끊겨도 원격 작업이 살아남는다. 장시간 배포·마이그레이션에는 필수다.