대상 OS: Debian 12 (bookworm)
SSH는 서버 운영의 기본 통로지만, 인터넷 전체에 열어두면 무차별 스캔/대입 시도가 끊이지 않습니다. 가장 효과가 큰 방법은 “인증(키)”도 중요하지만, 그 이전에 **네트워크 레벨에서 접속 가능한 IP를 제한(allowlist)** 하는 것입니다. Debian 12에서는 nftables로 이를 깔끔하게 구현할 수 있습니다.
1) 변경 전 확인(현재 노출/접속 상태)
# SSH 포트/프로세스
sudo ss -lntp | egrep 'sshd|:22'
# 최근 SSH 로그(실패 패턴 확인)
sudo journalctl -u ssh --since 'today' --no-pager | tail -n 120
# nftables 사용 여부/현재 룰셋
sudo systemctl status nftables --no-pager || true
sudo nft list ruleset | head -n 120
2) 전제: ‘키 인증 강제’가 먼저(방화벽은 2중 안전망)
IP 제한을 하더라도, SSH는 기본적으로 키 기반을 강제하는 게 안전합니다.
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F_%H%M)
sudoedit /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 20
sudo sshd -t && sudo systemctl reload ssh
3) nftables로 SSH allowlist 적용(예: 고정 IP 1개만 허용)
주의: 원격 서버에서 작업 중이면 **반드시 SSH 세션을 2개 유지**하고, 적용 직후 새 세션으로 재접속 테스트를 하세요.
# 패키지/서비스(이미 있다면 생략)
sudo apt-get update
sudo apt-get install -y nftables
sudo systemctl enable --now nftables
예시 정책(SSH만 allowlist, 나머지 인바운드는 기본 차단 가정이 아니라 “SSH만 추가로 잠그는” 형태):
# 허용할 관리자 IP로 교체
ADMIN_IP="203.0.113.10"
# 규칙 파일 생성/편집
sudoedit /etc/nftables.conf
`/etc/nftables.conf` 예시(핵심만):
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
# 기본: 이미 성립된 연결은 허용
ct state established,related accept
# 로컬 루프백 허용
iifname "lo" accept
# (선택) ping 허용
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# SSH: 관리자 IP만 허용
tcp dport 22 ip saddr $ADMIN_IP accept
# 그 외 SSH는 드롭
tcp dport 22 drop
# 나머지 인바운드는 정책에 따라(최소는 drop)
counter drop
}
chain forward {
type filter hook forward priority 0;
drop
}
chain output {
type filter hook output priority 0;
accept
}
}
적용:
sudo nft -f /etc/nftables.conf
sudo nft list ruleset | sed -n '1,160p'
4) 여러 IP/대역을 허용하고 싶을 때(집/회사/VPN)
# 예: 집/회사/VPN 대역을 여러 개 허용(개념)
# tcp dport 22 ip saddr { 203.0.113.10, 198.51.100.0/24, 10.8.0.0/24 } accept
5) 트러블슈팅(증상→원인→해결)
1) 적용 후 SSH가 끊김
- 원인: ADMIN_IP를 잘못 넣었거나, 실제 접속 IP가 다름(통신사 NAT/회사 프록시)
- 해결: 콘솔 접근(클라우드 콘솔/물리 콘솔) 확보 후 규칙 수정
2) nftables 서비스는 켜져 있는데 규칙이 안 보임
- 원인: conf 경로 불일치 또는 다른 도구(ufw/firewalld)가 혼재
- 해결: `nft list ruleset` 기준으로 단일 진실(source of truth) 만들기
3) IPv6로 접속이 계속 되거나 차단이 이상함
- 원인: IPv4만 제한하고 IPv6 경로를 놓침
- 해결: inet 테이블을 사용하거나 IPv6도 같이 제어
4) 특정 시간대에만 접속이 안 됨
- 원인: 접속 IP가 변동(유동IP)
- 해결: VPN 고정 대역으로 들어오게 설계하거나, DDNS 기반보단 VPN/배스천이 더 안정적
6) 사례(현장에서 자주 겪는 상황)
1) 키 인증을 했다고 방심했는데, 계정이 늘어나면서 퇴사자 계정이 남아 공격 표면이 커짐
2) UFW와 nftables를 동시에 만져서 어느 쪽이 실제로 막는지 모르는 상태가 됨
3) 회사에서 나가는 공인 IP가 여러 개라 allowlist가 자주 틀어짐 → VPN/배스천으로 해결하는 게 장기적으로 편함
결론: SSH 보안은 “키 인증 + 접근 IP 제한” 조합이 가장 효율이 좋습니다. nftables로 네트워크 레벨을 잠그면, 공격자가 인증을 시도할 기회 자체가 크게 줄어듭니다.