SSH 보안은 설정 한 줄보다 운영 절차가 중요합니다

리눅스 서버를 운영할 때 SSH는 가장 자주 열어 두는 관리 통로입니다. 그래서 보안 설정을 단순히 “비밀번호 로그인을 끈다” 수준으로 끝내면 실제 운영에서 빈틈이 남습니다. 키 인증, 계정 제한, 접속 로그 확인, 방화벽, 백업 접속 수단까지 함께 설계해야 장애 없이 안전하게 강화할 수 있습니다. 특히 외부에 공개된 서버라면 무작위 대입 공격, 퇴사자 계정 방치, 루트 직접 로그인, 오래된 키 파일, 접속 실패 로그 미확인 같은 문제가 반복적으로 발생합니다.

이 문서는 Ubuntu, Debian, Rocky Linux, Amazon Linux 같은 일반적인 서버에서 바로 적용할 수 있는 SSH 보안 점검 순서를 정리합니다. 배포판마다 서비스명이나 방화벽 명령은 조금 다를 수 있지만, 핵심은 운영 계정과 접속 정책을 명확히 하고 변경 전후 검증 절차를 남기는 것입니다. 운영 중인 서버에서는 한 번에 모든 설정을 바꾸지 말고, 반드시 새 터미널을 열어 기존 세션을 유지한 상태에서 테스트해야 합니다.

1. 관리자 계정과 키 인증부터 정리합니다

먼저 개인별 운영 계정을 만들고, 공용 계정 하나를 여러 사람이 공유하지 않도록 합니다. 공용 계정은 누가 접속했는지 추적하기 어렵고, 키를 회수할 때도 영향 범위를 판단하기 어렵습니다. 운영자는 개인 계정으로 접속한 뒤 sudo 권한을 사용하고, sudo 로그를 통해 명령 이력을 추적하는 방식이 좋습니다.

  • 운영자마다 별도 계정을 만들고, 불필요한 계정은 잠급니다.
  • 서버에 등록된 공개키는 주기적으로 실제 사용자와 대조합니다.
  • 개인키에는 암호를 설정하고, 로컬 PC나 CI 환경에 평문으로 방치하지 않습니다.
  • 비상용 계정은 별도 문서로 관리하되, 상시 사용하지 않습니다.
sudo adduser deployer
sudo usermod -aG sudo deployer
sudo install -d -m 700 -o deployer -g deployer /home/deployer/.ssh
sudo install -m 600 -o deployer -g deployer ./deployer.pub /home/deployer/.ssh/authorized_keys
sudo passwd -l old-operator

키를 등록한 뒤에는 비밀번호 로그인을 끄기 전에 반드시 새 창에서 키 인증 접속을 먼저 확인합니다. 기존 SSH 세션은 절대 끊지 않은 상태로 유지해야 합니다. 만약 새 접속이 실패하면 기존 세션에서 설정을 되돌릴 수 있기 때문입니다.

2. sshd_config는 최소 권한 원칙으로 좁힙니다

SSH 서버 설정은 보통 /etc/ssh/sshd_config에서 관리합니다. 최근 OpenSSH 환경에서는 배포판이 /etc/ssh/sshd_config.d/ 디렉터리의 추가 설정 파일을 읽도록 구성된 경우도 많습니다. 운영에서는 원본 파일을 크게 수정하기보다 별도 파일을 만들어 변경 이력을 관리하는 방식이 실수 복구에 유리합니다.

sudo tee /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowUsers deployer ops-admin
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
EOF

sudo sshd -t
sudo systemctl reload sshd || sudo systemctl reload ssh

PermitRootLogin no는 루트 직접 접속을 막고, PasswordAuthentication no는 비밀번호 대입 공격의 효과를 크게 줄입니다. AllowUsers는 접속 가능한 계정을 명시적으로 제한합니다. 다만 자동 배포 계정, 백업 계정, 모니터링 계정이 SSH를 사용한다면 누락되지 않도록 먼저 확인해야 합니다. AllowTcpForwarding no는 터널링 악용을 줄이는 데 도움이 되지만, 운영에서 포트포워딩을 실제로 쓰는 배포 구조라면 서비스별로 예외 설계를 해야 합니다.

설정 반영 전에는 항상 sshd -t로 문법 검사를 실행합니다. 문법 오류가 있는 상태에서 서비스를 재시작하면 원격 접속이 막힐 수 있습니다. 운영 서버에서는 restart보다 reload를 우선 사용하고, 변경 직후 새 터미널로 접속 검증을 진행합니다.

3. 방화벽과 접속 위치를 함께 제한합니다

SSH 설정만 강화해도 도움이 되지만, 접속 가능한 네트워크를 줄이면 공격 노출면이 더 크게 감소합니다. 사무실 고정 IP, VPN 대역, 배포 서버, 관리용 Bastion 서버처럼 접속 출처를 정의할 수 있다면 방화벽에서 먼저 걸러내는 것이 좋습니다. 클라우드 환경에서는 OS 방화벽뿐 아니라 보안 그룹, 네트워크 ACL, 로드밸런서 접근 정책도 함께 확인해야 합니다.

# UFW 예시: 관리 IP만 SSH 허용
sudo ufw default deny incoming
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status numbered

관리 IP가 자주 바뀌는 환경이라면 VPN을 먼저 구축하고 VPN 대역에서만 SSH를 허용하는 편이 안정적입니다. 여러 서버를 운영한다면 모든 서버에 22번 포트를 공개하기보다 Bastion 서버 하나만 공개하고, 내부 서버는 사설망에서만 접근하게 구성하는 방식이 좋습니다. 이 구조는 감사 로그도 모으기 쉽고, 퇴사자 권한 회수도 단순해집니다.

4. 실패 로그와 성공 로그를 매일 확인할 수 있게 만듭니다

보안 설정은 적용보다 확인이 더 중요합니다. 공격 시도가 계속 들어오는데 아무도 로그를 보지 않으면 계정 잠금, 방화벽 정책, 알림 기준을 개선할 기회를 놓칩니다. systemd 기반 배포판에서는 journalctl로 sshd 로그를 확인할 수 있고, Debian 계열은 /var/log/auth.log, RHEL 계열은 /var/log/secure를 함께 봅니다.

# 최근 SSH 인증 이벤트 확인
sudo journalctl -u ssh -u sshd --since "24 hours ago" --no-pager

# 실패한 로그인 출처 집계 예시
sudo awk '/Failed password|Invalid user/ {print $(NF-3)}' /var/log/auth.log 2>/dev/null   | sort | uniq -c | sort -nr | head

로그에서 같은 IP가 짧은 시간에 많은 실패를 만들거나, 존재하지 않는 사용자명으로 계속 접속을 시도한다면 차단 정책을 강화해야 합니다. fail2ban 같은 도구를 사용할 수도 있지만, 기본 방화벽 정책이 느슨한 상태에서 차단 도구만 추가하는 것은 근본 해결이 아닙니다. 우선 공개 범위, 허용 계정, 인증 방식을 정리한 뒤 보조 수단으로 자동 차단을 붙이는 순서가 안전합니다.

5. 적용 후 점검 체크리스트

  • 개인별 운영 계정이 있고 공용 계정 사용을 줄였는지 확인합니다.
  • 루트 직접 로그인과 비밀번호 로그인이 꺼져 있는지 확인합니다.
  • AllowUsers 또는 방화벽으로 접속 대상을 좁혔는지 확인합니다.
  • 설정 변경 전 sshd -t 문법 검사를 실행했는지 확인합니다.
  • 기존 세션을 유지한 상태에서 새 SSH 접속 테스트를 완료했는지 확인합니다.
  • 최근 24시간 SSH 실패 로그를 확인하고 반복 공격 출처를 집계했는지 확인합니다.
  • 비상 접속 방법과 권한 회수 절차를 문서화했는지 확인합니다.

SSH 보안 강화의 목표는 접속을 불편하게 만드는 것이 아니라, 필요한 사람만 안정적으로 접속하고 문제 발생 시 빠르게 추적할 수 있게 만드는 것입니다. 키 인증, 계정 제한, 네트워크 제한, 로그 점검을 한 번에 묶어 운영하면 작은 서버라도 훨씬 예측 가능한 보안 상태를 유지할 수 있습니다.