비밀번호는 추측당하고, 유출되고, 무차별 대입당합니다. 공개키는 그 모든 것에 면역입니다. 단, 그 키를 제대로 지킬 때만.
들어가며: 두 번째 관문을 강철로
6장에서 우리는 SSH에 도달하는 경로 자체를 인터넷에서 숨겼습니다. 22번 포트를 닫고, Zero Trust 뒤로 옮겨, 무차별 자동 공격이 두드릴 문조차 찾지 못하게 했습니다. 그렇다면 SSH 자체를 더 단단하게 만드는 이 장은 왜 필요할까요?
답은 이 책의 두 번째 원칙, "침해를 가정하라"에 있습니다. 6장의 경로 은폐는 강력하지만, 그것이 유일한 방어여서는 안 됩니다. Zero Trust 계층이 우회되거나, 내부 네트워크에서 접근이 시도되거나, 예상치 못한 경로로 SSH에 도달하는 상황을 가정해야 합니다. 그 순간, SSH 자체가 두 번째 관문으로서 단단히 버텨 주어야 합니다. 6장이 "문에 이르는 길을 숨기는 것"이라면, 이 장은 "그 문 자체를 강철로 만드는 것"입니다. 두 관문이 독립적으로 단단할 때, 깊이 방어(원칙 3)가 완성됩니다.
그리고 SSH는 특별히 중요합니다. SSH(Secure Shell, 서버에 원격으로 명령을 내리는 암호화된 접속 통로)는 서버에 대한 가장 강력한 원격 접근 수단이기 때문입니다. SSH가 뚫리면, 공격자는 서버에 대한 광범위한 통제권을 얻습니다. 1장에서 보았듯, SSH 무차별 대입은 모든 신규 서버에 가장 먼저, 가장 끈질기게 도착하는 공격입니다. 그만큼 SSH는 공격자가 가장 사랑하는 표적이며, 따라서 방어자가 가장 단단히 지켜야 할 곳입니다. 2026년 현재도 사정은 같습니다. 클라우드에 서버 하나를 새로 띄우면, 몇 분 안에 전 세계의 자동 봇이 22번 포트를 두드리기 시작합니다 — 사람이 아니라 기계가, 쉬지 않고.
이 장에서는 SSH를 단계적으로 하드닝합니다. 가장 중요한 것 — 비밀번호 로그인을 완전히 끄고 공개키로만 접속하는 것 — 부터 시작하여, 공개키 자체를 안전하게 생성·보관·교체·폐기하는 법, SSH 데몬의 세부 설정을 단단히 하는 법, 그리고 추가 방어 계층(다단계 인증, fail2ban, 권한 분리)까지 다룹니다.
6장의 안전 원칙을 기억하십시오. SSH 설정 변경은 자기 자신을 서버에서 잠가 버릴 수 있는 대표적인 위험 작업입니다. 이 장의 모든 변경은 6.5에서 다룬 안전 절차(새 경로 우선 검증, 두 번째 세션 유지, 자동 롤백, 비상 콘솔 확인)를 따라야 합니다. 특히 비밀번호 로그인을 끄기 전에는, 반드시 공개키 접속이 작동함을 별도 세션으로 확인하십시오.
7.1 왜 비밀번호 인증을 완전히 꺼야 하는가
SSH 하드닝의 가장 근본적이고 가장 효과적인 단 하나의 조치는, 비밀번호 인증을 완전히 끄고 공개키 인증만 허용하는 것입니다. 다른 모든 하드닝을 합친 것보다 이 하나가 더 큰 효과를 냅니다. 그 이유를 정확히 이해해야 합니다.
비밀번호의 근본적 약점
비밀번호는 세 가지 근본적 약점을 가집니다.
첫째, 추측 가능합니다. 사람이 기억할 수 있는 비밀번호는 본질적으로 한계가 있습니다. 사람은 기억하기 쉬운 패턴을 택하는 경향이 있고, 그 경향은 공격자에게 알려져 있습니다. 흔한 단어, 예측 가능한 변형, 재사용된 비밀번호 — 이 모든 것이 추측의 대상입니다.
둘째, 무차별 대입당합니다. 1장에서 본 대로, 자동화된 공격은 끊임없이 비밀번호를 시도합니다. 유출된 비밀번호 목록과 흔한 조합을 초당 수없이 던집니다. 비밀번호가 충분히 강하지 않으면, 시간문제로 뚫립니다. 그리고 사람이 만든 비밀번호 중 "충분히 강한" 것은 드뭅니다.
셋째, 유출됩니다. 비밀번호는 사람이 알고, 입력하고, 때로 적어 두고, 재사용하는 것입니다. 피싱으로 넘어가고(3장), 다른 서비스의 유출 데이터에 포함되며, 키로거에 잡히고, 어깨너머로 훔쳐보입니다. 비밀번호가 한 번이라도 유출되면, 그것을 아는 누구나 접속할 수 있습니다.
공개키가 이 모든 것에 면역인 이유
공개키 인증(public key authentication)은 비밀번호의 세 약점에 근본적으로 면역입니다. 작동 원리를 이해하면 그 이유가 분명해집니다.
공개키 인증은 한 쌍의 키를 사용합니다. 개인키(private key) 와 공개키(public key) 입니다. 이 둘은 수학적으로 연결되어 있지만, 공개키로부터 개인키를 알아낼 수는 없습니다. 개인키는 사용자가 자신의 기기에 안전하게 보관하고 절대 외부로 내보내지 않습니다. 공개키는 이름 그대로 공개되어도 안전하며, 접속하려는 서버에 미리 등록해 둡니다.
접속 과정은 대략 이렇습니다. 서버는 등록된 공개키에 대응하는 개인키를 사용자가 가지고 있는지를, 개인키를 직접 받지 않고도 수학적으로 검증합니다. 사용자는 자신이 개인키를 가지고 있음을 증명하지만, 개인키 자체는 네트워크로 전송되지 않습니다.
이 방식이 비밀번호의 약점을 어떻게 해결하는지 보겠습니다.
- 추측 불가능. 개인키는 사람이 기억하는 것이 아니라 기계가 생성한 거대한 무작위 값입니다. 추측하거나 패턴을 찾을 수 없습니다.
- 무차별 대입 불가능. 개인키의 경우의 수가 천문학적으로 많아, 무차별 대입이 현실적인 시간 안에 불가능합니다. 1장의 자동 공격은 공개키만 허용된 서버 앞에서 완전히 무력해집니다.
- 유출 경로 차단. 개인키는 네트워크로 전송되지 않으므로, 통신을 가로채도 얻을 수 없습니다. 피싱으로 "비밀번호를 입력하세요"라고 속여도, 애초에 입력할 비밀번호가 없습니다.
요컨대, 비밀번호 인증을 끄고 공개키만 허용하는 것은, 1장에서 본 SSH 무차별 대입이라는 가장 흔한 공격을 원리적으로 불가능하게 만드는 조치입니다. 막는 것이 아니라 성립 자체를 없애는 것입니다.
단, 개인키를 지킬 때만
그러나 여기에 결정적인 단서가 붙습니다. 공개키 인증의 안전성은 전적으로 개인키가 안전하게 지켜진다는 전제 위에 있습니다. 개인키가 유출되면, 공개키 인증의 모든 이점이 무너집니다. 비밀번호는 추측이라도 해야 하지만, 개인키는 손에 넣으면 그것으로 끝입니다.
그래서 7.3에서 개인키를 안전하게 관리하는 법을 비중 있게 다룹니다. 공개키 인증으로 전환하는 것이 절반이라면, 그 키를 제대로 지키는 것이 나머지 절반입니다. 둘 다 갖추어야 비로소 안전합니다.
7.2 공개키 인증으로 전환하기
이제 실제로 공개키 인증을 설정하겠습니다. 순서가 중요합니다. 반드시 공개키 접속이 작동함을 확인한 뒤에 비밀번호 인증을 끕니다.
1단계: 키 페어 생성
먼저 자신의 로컬 기기(서버가 아니라, 서버에 접속하는 당신의 컴퓨터)에서 키 페어를 생성합니다. 현대적으로 권장되는 방식은 Ed25519 알고리즘입니다. 참고로, 지금 다루는 모든 명령(ssh, ssh-keygen, ssh-copy-id)과 서버 쪽 SSH 설정은 사실상 표준 구현인 OpenSSH의 것입니다. 리눅스 서버에 기본으로 깔려 있는 그 SSH가 바로 이것입니다.
# 로컬 기기에서 실행: Ed25519 키 페어 생성
ssh-keygen -t ed25519 -C "your-comment-or-email"
# 생성 과정에서 두 가지를 묻습니다:
# 1) 저장 위치 (기본: ~/.ssh/id_ed25519)
# 2) 패스프레이즈 (반드시 설정하십시오 - 7.3에서 설명)
이 명령은 두 개의 파일을 만듭니다. id_ed25519(개인키, 절대 공유 금지)와 id_ed25519.pub(공개키, 서버에 등록할 것)입니다.
생성 중 패스프레이즈(passphrase) 를 묻는데, 이것을 빈칸으로 두지 말고 반드시 강한 패스프레이즈를 설정하십시오. 이유는 7.3에서 자세히 설명합니다. 간단히 말하면, 개인키 파일이 어떤 이유로 유출되더라도, 패스프레이즈가 있으면 그것을 모르는 한 키를 쓸 수 없기 때문입니다. 개인키에 대한 두 번째 자물쇠인 셈입니다.
2단계: 공개키를 서버에 등록
생성한 공개키를 서버에 등록합니다. 가장 간단한 방법은 ssh-copy-id입니다(아직 비밀번호 접속이 가능한 상태에서).
# 로컬 기기에서: 공개키를 서버에 등록
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# 또는 수동으로: 공개키 내용을 서버의 ~/.ssh/authorized_keys에 추가
이 작업은 공개키를 서버의 ~/.ssh/authorized_keys 파일에 추가합니다. 이 파일에 등록된 공개키에 대응하는 개인키를 가진 사람만 접속할 수 있게 됩니다.
3단계: 공개키 접속 확인 (필수)
비밀번호를 끄기 전에, 반드시 공개키로 접속이 되는지 확인합니다. 이 단계를 건너뛰면 6장에서 경고한 자물쇠 사고가 일어날 수 있습니다.
# 로컬 기기에서: 공개키로 접속 시도
ssh -i ~/.ssh/id_ed25519 user@server
# 정상 접속되면, 패스프레이즈를 물을 것입니다 (개인키를 보호하는 패스프레이즈).
# 접속이 성공해야만 다음 단계로 진행하십시오.
공개키 접속이 성공함을 확인했다면, 그리고 6.5의 안전 절차에 따라 별도 세션을 유지하고 있다면, 이제 비밀번호 인증을 끌 준비가 되었습니다.
4단계: 서버에서 비밀번호 인증 끄기
서버의 SSH 데몬 설정 파일(/etc/ssh/sshd_config)에서 비밀번호 인증을 비활성화합니다.
# 서버에서: /etc/ssh/sshd_config 편집
# 다음 설정을 적용합니다.
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
설정 변경 후, SSH 데몬을 재시작하기 전에 설정 문법을 검증하고, 재시작 후에는 6.5의 절차대로 새 세션으로 접속을 확인합니다.
# 서버에서: 설정 문법 검증 (재시작 전 필수)
sudo sshd -t
# 문법이 정상이면 데몬 재시작
sudo systemctl restart ssh
# 그 다음, 반드시 별도의 새 세션으로 공개키 접속을 확인하십시오.
# 기존 세션은 닫지 마십시오. 새 접속이 실패하면 기존 세션으로 되돌립니다.
이제 비밀번호로는 접속할 수 없고, 등록된 공개키를 가진 사람만 접속할 수 있습니다. 1장의 SSH 무차별 대입은 이 서버 앞에서 원리적으로 무력해졌습니다.
7.3 개인키를 안전하게 관리하기
7.1에서 강조했듯, 공개키 인증의 안전성은 전적으로 개인키를 지키는 데 달려 있습니다. 이 절은 그 핵심을 다룹니다. 공개키로 전환하는 것만큼 중요한 절반입니다.
패스프레이즈: 개인키의 두 번째 자물쇠
개인키 파일은 그 자체로 접속 권한입니다. 만약 패스프레이즈 없이 개인키를 생성했다면, 그 파일을 손에 넣은 누구나 즉시 서버에 접속할 수 있습니다. 노트북을 분실하거나, 백업이 유출되거나, 기기가 침해당하면, 개인키도 함께 넘어갑니다.
패스프레이즈는 이 위험에 대한 방어입니다. 패스프레이즈로 보호된 개인키는, 파일 자체가 암호화되어 있어, 패스프레이즈를 모르면 쓸 수 없습니다. 즉, 개인키 파일이 유출되어도 패스프레이즈라는 두 번째 자물쇠가 시간을 벌어 줍니다. 그 시간 동안 당신은 7.4의 방법으로 해당 키를 폐기할 수 있습니다.
따라서 개인키에는 반드시 강한 패스프레이즈를 설정하십시오. 이미 패스프레이즈 없이 만든 키가 있다면, 다음 명령으로 추가할 수 있습니다.
# 기존 개인키에 패스프레이즈 추가/변경
ssh-keygen -p -f ~/.ssh/id_ed25519
SSH 에이전트: 편의와 안전의 균형
패스프레이즈를 설정하면, 접속할 때마다 패스프레이즈를 입력해야 하는 번거로움이 생깁니다. 이 번거로움 때문에 패스프레이즈를 포기하는 것은 본말이 전도된 것입니다. 대신 SSH 에이전트(ssh-agent)를 사용합니다.
SSH 에이전트는 패스프레이즈를 한 번 입력하면, 그 세션 동안 개인키를 메모리에 안전하게 보관하여 반복 입력 없이 접속할 수 있게 해 줍니다. 패스프레이즈의 보안을 유지하면서 편의를 얻는 방법입니다.
# SSH 에이전트 시작 (대개 데스크톱 환경에서 자동 실행됨)
eval "$(ssh-agent -s)"
# 개인키를 에이전트에 추가 (패스프레이즈를 한 번 입력)
ssh-add ~/.ssh/id_ed25519
# 일정 시간 후 자동으로 키를 잊도록 설정 (예: 1시간)
ssh-add -t 3600 ~/.ssh/id_ed25519
-t 옵션으로 키의 유효 시간을 제한하면, 에이전트에 키가 무한정 남아 있지 않게 하여 안전성을 높일 수 있습니다.
개인키 파일의 권한
개인키 파일은 소유자만 읽을 수 있도록 권한이 엄격히 제한되어야 합니다. SSH는 개인키 파일의 권한이 너무 개방적이면 사용을 거부하는데, 이것은 좋은 안전장치입니다.
# 개인키 파일 권한 확인 및 설정
chmod 600 ~/.ssh/id_ed25519 # 소유자만 읽기/쓰기
chmod 700 ~/.ssh # .ssh 디렉터리도 소유자만 접근
chmod 644 ~/.ssh/id_ed25519.pub # 공개키는 읽기 허용 가능
하드웨어 보안 키: 가장 강력한 보관
개인키 보관의 가장 강력한 형태는, 개인키를 파일이 아니라 물리적인 하드웨어 보안 키에 저장하는 것입니다. 하드웨어 키 방식에서는 개인키가 하드웨어 장치 안에서 생성되어 그 안을 절대 떠나지 않습니다. 접속 시 물리적 장치가 있어야 하고, 종종 장치를 직접 터치하는 등의 물리적 확인이 필요합니다.
이 방식의 이점은 분명합니다. 개인키가 파일로 존재하지 않으므로, 기기가 침해당하거나 파일이 유출되어도 개인키를 훔칠 수 없습니다. 물리적 장치 자체를 빼앗지 않는 한 키를 쓸 수 없으며, 장치가 있어도 물리적 확인이 필요합니다. 이것은 3장에서 본 피싱과 원격 침해 모두에 매우 강한 방어입니다. 특히 중요한 서버에 접근하는 키라면, 하드웨어 키 방식을 적극 고려할 가치가 있습니다.
개인키 관리의 핵심 원칙
개인키 관리를 관통하는 원칙을 정리하면 다음과 같습니다.
- 개인키는 절대 전송하지 않습니다. 이메일, 메신저, 클라우드 동기화 등으로 개인키를 옮기지 마십시오. 개인키는 생성된 기기를 떠나지 않는 것이 원칙입니다. 다른 기기가 필요하면 그 기기에서 별도의 키를 만드십시오.
- 개인키를 공유하지 않습니다. 한 사람당, 한 기기당 별도의 키를 쓰십시오. 여러 사람이 하나의 키를 공유하면, 누가 접속했는지 추적할 수 없고, 한 사람의 유출이 모두의 유출이 됩니다.
- 개인키에 패스프레이즈를 겁니다. 두 번째 자물쇠를 반드시 두십시오.
- 권한을 엄격히 제한합니다. 파일 권한을 소유자 전용으로 설정하십시오.
- 가능하면 하드웨어 키를 씁니다. 중요한 접근일수록 더 강한 보관을.
7.4 키의 생애주기: 교체와 폐기
개인키 관리는 보관에서 끝나지 않습니다. 키에는 생애주기가 있고, 교체와 폐기가 그 일부입니다. 이것은 원칙 5(보안은 과정이다)의 적용입니다.
키 교체 (rotation)
비밀번호를 주기적으로 바꾸는 것처럼, SSH 키도 주기적으로 교체하는 것이 좋습니다. 오래된 키일수록 그동안 유출되었을 가능성이 누적되기 때문입니다. 키 교체는 새 키 페어를 만들고, 새 공개키를 서버에 등록한 뒤, 새 키로의 접속을 확인하고, 옛 공개키를 서버에서 제거하는 순서로 이루어집니다.
이때도 6.5의 안전 원칙이 적용됩니다. 새 키 접속이 작동함을 확인한 뒤에 옛 키를 제거하십시오. 순서를 거꾸로 하면 접속이 끊길 수 있습니다.
키 폐기 (revocation)
다음과 같은 상황에서는 즉시 키를 폐기해야 합니다.
- 개인키가 유출되었거나 유출이 의심될 때
- 개인키가 저장된 기기를 분실하거나 도난당했을 때
- 키를 사용하던 사람이 더 이상 접근 권한을 가져서는 안 될 때(퇴사 등)
키 폐기는 서버의 ~/.ssh/authorized_keys에서 해당 공개키를 제거하는 것으로 이루어집니다. 제거하는 즉시, 그 키로는 더 이상 접속할 수 없게 됩니다.
# 서버에서: authorized_keys에서 특정 공개키 제거
# 해당 키의 줄을 찾아 삭제합니다.
# 폐기 후, 그 키로 접속이 거부되는지 확인하십시오.
이것이 7.3에서 "한 사람당, 한 기기당 별도의 키"를 강조한 이유이기도 합니다. 키가 사람·기기별로 분리되어 있으면, 특정 키만 폐기하여 다른 접속에 영향을 주지 않을 수 있습니다. 키를 공유했다면, 하나를 폐기할 때 모두가 영향을 받습니다.
또한 패스프레이즈가 폐기의 시간을 벌어 준다는 점을 다시 강조합니다. 기기를 분실했을 때, 개인키에 패스프레이즈가 걸려 있으면, 그것을 모르는 습득자가 즉시 접속할 수 없습니다. 그 사이에 당신은 키를 폐기하면 됩니다. 패스프레이즈가 없었다면, 분실과 동시에 접속 권한이 넘어갔을 것입니다.
7.5 SSH 데몬 하드닝: 세부 설정
공개키 인증으로 전환한 뒤, SSH 데몬의 추가 설정으로 보안을 더 강화할 수 있습니다. 다음은 /etc/ssh/sshd_config에서 권장되는 주요 설정과 그 이유입니다. 변경 후에는 항상 sshd -t로 검증하고 6.5의 절차로 접속을 확인하십시오.
root 직접 로그인 차단
PermitRootLogin no
root는 무제한 권한을 가진 계정이므로, root로 직접 로그인을 허용하면 공격자에게 가장 큰 표적을 내주는 것입니다. 대신 일반 사용자로 로그인한 뒤 필요시 권한을 상승시키는 방식(sudo)을 쓰면, 공격자가 일반 계정을 뚫더라도 곧바로 모든 권한을 얻지는 못합니다. 또한 누가 어떤 권한 작업을 했는지 추적이 가능해집니다.
인증 시도 제한과 타임아웃
MaxAuthTries 3
LoginGraceTime 30
MaxAuthTries는 한 연결에서 허용하는 인증 시도 횟수를 제한합니다. LoginGraceTime은 인증을 완료하지 않은 연결을 끊기까지의 시간을 제한합니다. 이 설정들은 자동화된 공격이 하나의 연결로 여러 시도를 하거나, 연결을 오래 점유하는 것을 막습니다.
유휴 세션 자동 종료
ClientAliveInterval 300
ClientAliveCountMax 2
이 설정은 일정 시간 활동이 없는 세션을 자동으로 종료합니다. 방치된 세션이 탈취되거나, 자리를 비운 사이 무단으로 사용되는 것을 막습니다.
접근 가능한 사용자 제한
# 특정 사용자에게만 SSH 접근을 허용
AllowUsers your-user
# 또는 특정 그룹에게만 허용
AllowGroups ssh-users
SSH로 접근할 수 있는 사용자를 명시적으로 제한하면, 의도하지 않은 계정(시스템 계정 등)을 통한 접근 가능성을 줄입니다. 이것은 5장의 공격면 축소를 SSH에 적용하는 것입니다.
불필요한 기능 비활성화
# 사용하지 않는 전달 기능 비활성화 (필요에 따라)
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
# 빈 비밀번호 절대 금지
PermitEmptyPasswords no
SSH는 다양한 부가 기능을 제공하는데, 쓰지 않는 기능은 꺼 두는 것이 공격면 축소의 원칙에 부합합니다. 다만 일부 기능은 정당한 용도가 있으므로, 자신의 사용 패턴을 고려해 결정하십시오.
강한 암호 알고리즘만 허용
오래되고 약한 암호 알고리즘을 비활성화하고, 현대적이고 강한 것만 허용하는 것이 좋습니다. 구체적인 권장 목록은 시간에 따라 갱신되므로, 신뢰할 수 있는 최신 하드닝 가이드를 참고하여 약한 알고리즘을 배제하십시오. 이 절의 sshd_config 항목 전체에 대해, 저는 Mozilla의 OpenSSH 하드닝 가이드를 기준으로 삼기를 권합니다. KexAlgorithms·Ciphers·MACs에 무엇을 넣을지를 "Modern"/"Intermediate"로 나누어 복사-붙여넣기 가능한 형태로 제시하는데, 직접 외울 필요 없이 현재 권장값을 그대로 가져다 쓰면 됩니다. 이것은 8장에서 다룰 TLS 암호 스위트 선택과 같은 맥락의 작업입니다.
7.6 추가 방어 계층
공개키 전용 인증과 데몬 하드닝 위에, 몇 가지 방어 계층을 더할 수 있습니다. 깊이 방어(원칙 3)의 적용입니다.
다단계 인증 (MFA)
SSH에 다단계 인증을 추가하면, 공개키에 더해 두 번째 인증 요소를 요구할 수 있습니다. 6장의 Zero Trust Access가 이미 신원 기반의 한 겹을 제공하지만, SSH 자체에 MFA를 추가하는 것도 가능합니다.
3장에서 강조했듯, MFA는 자격 증명이 유출되어도 두 번째 요소가 없으면 접속을 막아 줍니다. 다만 MFA의 방식에 따라 피싱 저항성이 다르므로, 가능하면 피싱에 강한 방식(7.3에서 본 하드웨어 키 등)을 우선하십시오.
fail2ban: 무차별 대입 차단
fail2ban은 로그를 감시하여, 반복적으로 인증에 실패하는 IP를 자동으로 차단하는 도구입니다. 쉽게 말해, 누군가 문을 계속 잘못 두드리면 그 사람의 IP를 방화벽 수준에서 일정 시간 출입금지시키는 자동 경비입니다. 공개키 전용으로 전환했다면 무차별 대입 자체가 무력하지만, fail2ban은 추가적인 잡음 감소와 로그 정리 효과를 줍니다.
# fail2ban 설치 (데비안/우분투)
sudo apt-get install fail2ban
# SSH 보호를 위한 기본 설정 예시 (/etc/fail2ban/jail.local)
# [sshd]
# enabled = true
# maxretry = 3
# bantime = 3600
# findtime = 600
이 설정은 일정 시간 내에 일정 횟수 이상 실패한 IP를 일정 시간 차단합니다. 다만 6장의 방식으로 SSH를 인터넷에서 숨겼다면, fail2ban이 처리할 무차별 대입 자체가 거의 도달하지 않게 됩니다. fail2ban은 인터넷에 노출된 SSH를 운영해야 하는 경우에 특히 유용합니다.
현장에서 반복해 본 것은, fail2ban을 "방어의 핵심"으로 오해하지 않는 일입니다. 제가 운영하는 서버들에서 fail2ban이 차단하는 IP 수는 그 자체로 인상적이지만, 그것은 어디까지나 마지막 잡음 필터일 뿐입니다. 순서가 중요합니다 — 먼저 비밀번호 인증을 끄고(7.2), 가능하면 SSH를 인터넷에서 숨긴 다음(6장), 그 위에 fail2ban을 얹는 것입니다. 거꾸로 fail2ban만 깔아 두고 비밀번호 로그인을 열어 둔 서버를 적지 않게 봤는데, 이는 자물쇠는 그대로 둔 채 경비원만 세운 격입니다.
권한 분리와 최소 권한
SSH 접근 이후의 보안도 중요합니다. 7.5에서 root 직접 로그인을 막았듯, 서버 안에서도 최소 권한 원칙을 적용합니다. 각 사용자와 프로세스가 자신의 작업에 필요한 최소한의 권한만 갖게 하면, 한 계정이 침해당해도 피해가 그 권한 범위로 제한됩니다. 이것은 2장의 내부자 위협과 측면 이동 방어에도 직결됩니다.
배스천(점프) 호스트
여러 서버를 운영한다면, 모든 서버에 개별적으로 접근하는 대신, 잘 보호된 단일 진입점(배스천 호스트, bastion host 또는 점프 호스트)을 두고 그것을 통해서만 내부 서버에 접근하는 구조를 고려할 수 있습니다. 이 방식은 외부에 노출되는 접점을 하나로 줄이고(공격면 축소), 그 하나를 집중적으로 방어하며, 모든 접근을 한곳에서 기록하고 통제할 수 있게 합니다. 6장의 Zero Trust Access는 이 배스천 개념을 클라우드 수준에서 구현한 것으로 볼 수 있습니다.
7.7 이 장이 남기는 교훈
이 장에서 확인한 것을 압축합니다.
첫째, SSH는 두 번째 관문이며 강철이어야 합니다. 6장에서 경로를 숨겼더라도, 침해를 가정하면(원칙 2) SSH 자체가 단단히 버텨야 합니다. 두 관문이 독립적으로 단단할 때 깊이 방어가 완성됩니다.
둘째, 비밀번호를 끄고 공개키로만 접속하는 것이 가장 효과적인 단일 조치입니다. 비밀번호는 추측·무차별 대입·유출의 약점을 가지지만, 공개키는 이 모두에 원리적으로 면역입니다. 1장의 SSH 무차별 대입을 성립 자체로 불가능하게 만듭니다.
셋째, 공개키의 안전성은 개인키 보호에 달려 있습니다. 전환이 절반이라면, 키를 지키는 것이 나머지 절반입니다. 패스프레이즈(두 번째 자물쇠), SSH 에이전트(편의와 안전의 균형), 엄격한 파일 권한, 그리고 가능하면 하드웨어 키를 쓰십시오.
넷째, 키에는 생애주기가 있습니다. 주기적으로 교체하고, 유출·분실·권한 종료 시 즉시 폐기하십시오. 사람·기기별로 키를 분리하면 폐기가 깔끔해지고, 패스프레이즈는 폐기까지의 시간을 벌어 줍니다.
다섯째, 데몬 설정과 추가 계층으로 더 단단히 만듭니다. root 직접 로그인 차단, 인증 시도 제한, 유휴 세션 종료, 사용자 제한, 약한 알고리즘 배제, 그리고 MFA·fail2ban·최소 권한·배스천으로 깊이를 더하십시오.
여섯째, 모든 변경에 안전 절차를 지키십시오. 6.5의 원칙(새 경로 우선 검증, 두 번째 세션, 자동 롤백, 비상 콘솔)은 SSH 하드닝에서 특히 생명입니다.
이것으로 2부 "공격면"을 마칩니다. 우리는 공격면을 지도화하고(5장), 인터넷을 향한 포트를 닫고(6장), SSH 자체를 강철로 만들었습니다(7장). 접근의 경로를 단단히 했으니, 이제 데이터가 그 경로를 오갈 때 어떻게 보호되는지로 넘어갑니다. 3부에서는 전송 계층 보안을 다룹니다. 그 첫 장에서, TLS를 제대로 설정하여 통신을 암호화하고 SSL Labs에서 최고 등급을 받는 법을 살펴보겠습니다.
이 장의 실행 항목
- 공개키 인증으로 전환하십시오. 키 생성 → 등록 → 접속 확인 → 비밀번호 인증 끄기 순서를 지키십시오. (7.2)
- 개인키에 강한 패스프레이즈를 거십시오. 이미 없이 만든 키가 있다면 추가하십시오. (7.3)
- 개인키 파일 권한을 소유자 전용으로 설정하십시오.
chmod 600. (7.3) - 중요한 접근에는 하드웨어 키를 고려하십시오. 개인키가 파일로 존재하지 않게 하십시오. (7.3)
- 키 교체·폐기 절차를 정하십시오. 유출·분실·퇴사 시 즉시 폐기할 수 있게 사람·기기별로 키를 분리하십시오. (7.4)
sshd_config를 하드닝하십시오. root 차단, 인증 제한, 유휴 종료, 사용자 제한, 약한 알고리즘 배제. (7.5)- 추가 계층을 더하십시오. MFA, fail2ban, 최소 권한, 배스천을 위협 모델에 맞게 적용하십시오. (7.6)
- 모든 변경에 6.5의 안전 절차를 적용하십시오. 자기 자신을 잠그지 마십시오. (6.5)
다음 장: 8장 — TLS를 제대로. 1.2 이상만, 그리고 SSL Labs에서 A+. 3부 "전송 계층 방어"의 시작.