ssh: 암호화된 채널로 원격 서버에 안전하게 접속하는 프로토콜
SSH(Secure Shell)는 네트워크를 통해 원격 컴퓨터에 안전하게 로그인하고 명령을 실행하며 파일을 전송하는 암호화 프로토콜이다. 서버 신원 확인, 키 교환, 사용자 인증의 단계를 거쳐 암호화된 채널을 만든다. 공개키 인증과 `~/.ssh/config`를 사용하면 비밀번호 없이도 안전하고 편리하게 서버를 관리할 수 있다.
By 송민성
1. 개념
SSH(Secure Shell)는 신뢰할 수 없는 네트워크 위에서 원격 컴퓨터에 안전하게 접속하기 위한 응용 계층 프로토콜이다. 기본 포트는 TCP 22번이다. 접속 후 셸 사용, 원격 명령 실행, 파일 전송(SCP, SFTP), 포트 포워딩(터널링)을 하나의 암호화된 연결 위에서 처리한다.
리눅스에서는 보통 OpenSSH가 클라이언트(ssh)와 서버 데몬(sshd)을 제공한다.
2. 왜 사용하는가
과거의 원격 접속 도구인 Telnet, rsh는 아이디와 비밀번호를 포함한 모든 데이터를 평문(plaintext)으로 전송했다. 같은 네트워크의 누군가가 패킷을 가로채면(스니핑, sniffing) 계정 정보가 그대로 노출된다. SSH는 다음을 제공해 이 문제를 해결한다.
- 기밀성(confidentiality): 통신 내용을 암호화한다.
- 무결성(integrity): 전송 중 데이터가 변조되었는지 검증한다.
- 인증(authentication): 서버와 사용자의 신원을 확인한다.
3. 동작 원리
연결은 크게 세 단계로 진행된다.
- 프로토콜 버전·알고리즘 협상: 클라이언트와 서버가 지원하는 키 교환, 암호화, MAC 알고리즘 중 서로 공통된 것을 고른다.
- 키 교환(key exchange)과 서버 인증: Diffie-Hellman 계열(예: ECDH, Curve25519) 방식으로 양쪽이 네트워크에 비밀 값을 직접 보내지 않고도 동일한 세션 키(session key)를 만든다. 서버는 자신의 호스트 키(host key)로 교환 과정에 서명하여 신원을 증명한다. 클라이언트는 이 호스트 키의 지문(fingerprint)을
~/.ssh/known_hosts에 저장된 값과 비교한다. 처음 접속하는 서버라면 지문을 보여주고 신뢰할지 묻는다. - 사용자 인증: 암호화된 채널이 만들어진 뒤에 사용자를 인증한다. 방식은 크게 두 가지다.
- 비밀번호 인증 - 공개키 인증(public key authentication): 클라이언트가 개인키(private key)로 서명을 만들고, 서버가 ~/.ssh/authorized_keys에 등록된 공개키(public key)로 검증한다. 개인키는 네트워크로 전송되지 않는다.
인증이 끝나면 하나의 연결 안에서 여러 채널(셸, 파일 전송, 포워딩)이 다중화(multiplexing)되어 동작한다.
4. 코드 예제
키 생성과 서버 등록
# Ed25519 키 쌍 생성 (비밀번호 passphrase 설정 권장)
ssh-keygen -t ed25519 -C "my-laptop" -f ~/.ssh/id_ed25519
# 공개키를 서버의 ~/.ssh/authorized_keys에 등록
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@example.com
# 접속
ssh user@example.com
# 비표준 포트와 특정 키 지정
ssh -p 2222 -i ~/.ssh/id_ed25519 user@example.com원격 명령 실행과 파일 전송
# 로그인 없이 명령 한 줄만 실행
ssh user@example.com "df -h && uptime"
# 파일 복사 (로컬 → 원격)
scp ./app.tar.gz user@example.com:/tmp/
# 디렉터리 동기화 (SSH 위에서 rsync)
rsync -avz -e ssh ./dist/ user@example.com:/var/www/app/설정 파일로 간소화 (~/.ssh/config)
cat >> ~/.ssh/config <<'EOF'
Host prod
HostName example.com
User deploy
Port 22
IdentityFile ~/.ssh/id_ed25519
EOF
chmod 600 ~/.ssh/config
# 이제 별칭으로 접속
ssh prod포트 포워딩(터널링)
# 로컬 포워딩: 내 5433 포트 → 원격 서버 입장에서의 localhost:5432(PostgreSQL)
ssh -N -L 5433:localhost:5432 prod
# 다른 터미널에서 터널을 통해 DB 접속
psql -h localhost -p 5433 -U appuser mydb서버 측 보안 설정 (/etc/ssh/sshd_config)
# 아래 항목을 확인/수정한 뒤 설정 문법 검사 및 재시작
# PasswordAuthentication no
# PermitRootLogin no
sudo sshd -t && sudo systemctl reload sshd5. 시간 복잡도 또는 성능 특성
- 연결 수립 시 알고리즘 협상, 키 교환, 사용자 인증을 위한 왕복(round trip)이 여러 번 발생하므로 연결을 새로 맺는 비용이 있다. 이후 데이터 전송 시 암호화 오버헤드는 현대 CPU에서 대체로 크지 않다.
- 같은 서버에 반복 접속한다면 OpenSSH의 연결 재사용(ControlMaster)으로 매번 핸드셰이크를 하지 않도록 할 수 있다.
cat >> ~/.ssh/config <<'EOF'
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
EOF6. 실무 사용 사례
- 클라우드 인스턴스(EC2 등)와 VPS 서버 관리
- 배포 자동화: CI/CD에서
ssh,rsync로 빌드 결과물 전송 - Git 원격 저장소 인증:
git@github.com:user/repo.git형태는 SSH 공개키로 인증한다. - 점프 호스트(bastion) 경유 접속:
ssh -J bastion user@private-host - 사설망 안의 DB·관리 콘솔에 접근하기 위한 터널링
7. 주의할 점
- 개인키 보호: 개인키(
id_ed25519)는 절대 공유하거나 저장소에 커밋하지 않는다. 권한은chmod 600이어야 하며, 그렇지 않으면 ssh가 사용을 거부한다.~/.ssh디렉터리는700을 권장한다. - passphrase 사용: 키가 유출되더라도 바로 악용되지 않도록 passphrase를 설정하고
ssh-agent로 관리한다. - 호스트 키 경고:
REMOTE HOST IDENTIFICATION HAS CHANGED경고는 서버 재설치일 수도 있지만 중간자 공격(MITM)일 수도 있다. 원인을 확인하기 전에 무작정known_hosts를 지우지 않는다. - 비밀번호 인증과 root 로그인 비활성화: 무차별 대입 공격(brute force)의 표적이 되기 쉬우므로 공개키 인증만 허용하는 구성이 일반적이다.
- 설정 변경 시 세션 유지:
sshd_config를 수정할 때는 기존 세션을 닫지 말고, 새 세션으로 접속이 되는지 확인한 뒤 종료한다. 잘못 설정하면 서버에 접근할 수 없게 된다. - 에이전트 포워딩(`-A`): 신뢰할 수 없는 서버에서는 내 인증 에이전트가 악용될 수 있으므로 필요한 경우가 아니면 대신
-J(ProxyJump)를 쓴다.
8. 핵심 정리
- SSH는 TCP 22번 포트를 기본으로 사용하는 암호화된 원격 접속 프로토콜이며, 기밀성·무결성·인증을 제공한다.
- 연결은 알고리즘 협상 → 키 교환과 서버 인증 → 사용자 인증 순서로 진행된다.
- 공개키 인증에서 개인키는 네트워크로 전송되지 않으며, 서버는
authorized_keys의 공개키로 서명을 검증한다. - 처음 접속 시 확인하는 호스트 키 지문은
known_hosts에 저장되어 이후 서버 위장을 탐지한다. ~/.ssh/config, ControlMaster, ProxyJump를 활용하면 접속과 운영이 편해지고, 서버에서는 비밀번호 로그인과 root 로그인을 막는 것이 기본 보안 설정이다.