지난 시간에 우리는 SSH 비밀번호 인증을 전면 폐쇄하고 SSH 키 기반 인증을 도입함과 동시에, 포트 번호를 변경하여 해커들의 자동화 스캔을 회피하는 방법을 배웠습니다. 이 두 가지 설정만으로도 서버의 안전성은 비약적으로 상승하며, 대부분의 무차별 대입 공격(Brute Force Attack) 세력을 무력화할 수 있습니다.
하지만 보안의 세계에 '완벽'이란 없습니다. 해커가 포트 스캔을 정교하게 수행하여 우리가 숨겨놓은 SSH 포트를 찾아내거나, 웹 서버(Nginx, Apache)의 로그인 창, 혹은 FTP 서버 등 여전히 비밀번호 인증을 유지해야만 하는 다른 서비스들을 집요하게 공격할 수 있습니다. 공격자가 지치지도 않고 수천, 수만 번의 비정상적인 접근을 시도할 때, 시스템이 이를 실시간으로 감지하고 공격자의 손발을 묶어버릴 수 있다면 얼마나 든든할까요?
연재 세 번째 시간인 이번 글에서는 리눅스 서버의 실시간 파수꾼이자 무차별 대입 공격을 온몸으로 막아내는 침입 차단 자동화 도구, Fail2ban의 동작 원리와 실무 구축 방법을 구체적인 예시와 함께 마스터해 보겠습니다.
Fail2ban은 시스템의 로그 파일(Log Files)을 실시간으로 모니터링하다가, 미리 정의된 규칙을 위반하는 IP를 발견하면 즉시 시스템 방화벽(UFW, Firewalld, iptables 등)을 조작하여 해당 IP의 접근을 일정 시간 혹은 영구적으로 차단(Ban)하는 오픈소스 보안 도구입니다.
동작 메커니즘을 쉽게 비유하자면 다음과 같습니다.
어떤 사람이 건물 문을 열려고 비밀번호를 계속 틀립니다. 경비원(Fail2ban)이 실시간 출입 기록(Log)을 지켜보다가 "5분 안에 5번 넘게 틀린 녀석이 있군!" 하고 판단하는 순간, 즉시 그 사람의 얼굴을 블랙리스트에 올리고 건물 진입로(방화벽)에서 통행을 완전히 차단해 버리는 것입니다.
자원 절약: 공격자가 계속 접속을 시도하면 시스템은 매번 인증 처리를 하느라 CPU와 메모리를 소모합니다. Fail2ban이 방화벽 단에서 IP를 차단하면, 공격자의 패킷이 리눅스 커널 내부로 들어오기 전에 드롭(Drop)되므로 서버 자원을 완벽하게 보호할 수 있습니다.
보안 가시성 확보: 어떤 IP가 언제, 몇 번 공격을 시도하다가 차단되었는지 명확한 이력을 추적할 수 있습니다.
유연한 확장성: SSH뿐만 아니라 웹 서버(Nginx, Apache), 메일 서버(Postfix), 데이터베이스 등 로그가 남는 모든 서비스에 플러그인 형태로 규칙을 적용할 수 있습니다.
이제 실제 리눅스 서버 환경에 Fail2ban을 설치하고 세부 아키텍처를 살펴보겠습니다.
리눅스 배포판의 패키지 관리자를 통해 Fail2ban을 설치합니다. Rocky Linux 등 RedHat 계열은 EPEL(Extra Packages for Enterprise Linux) 저장소가 먼저 활성화되어 있어야 합니다.
Ubuntu / Debian 계열:
Bash
sudo apt update
sudo apt install fail2ban -y
Rocky Linux / AlmaLinux 계열:
Bash
sudo dnf install epel-release -y
sudo dnf install fail2ban -y
Fail2ban의 설정 디렉토리는 /etc/fail2ban/입니다. 이곳에는 중요한 두 가지 설정 파일 템플릿이 있습니다.
jail.conf: Fail2ban의 기본 전역 설정 파일입니다. 단, 이 파일은 패키지가 업데이트될 때 덮어씌워질 수 있으므로 직접 수정하면 안 됩니다.
jail.local: 우리가 직접 생성하고 수정할 커스텀 설정 파일입니다. Fail2ban은 jail.conf를 먼저 읽은 뒤, jail.local에 적힌 내용을 덮어쓰는 방식으로 동작합니다.
따라서 안전한 설정을 위해 기본 파일을 복사하여 복사본을 수정하는 방식을 취합니다.
Bash
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
이제 핵심 자물쇠 세팅을 위해 /etc/fail2ban/jail.local 파일을 텍스트 편집기로 열고 필수 옵션들을 조정해 보겠습니다.
Bash
sudo nano /etc/fail2ban/jail.local
파일 내부의 [DEFAULT] 섹션에서 전역적으로 적용될 기본 차단 정책을 설정할 수 있습니다. 다음 예시를 참고하여 매개변수를 수정합니다.
Plaintext
[DEFAULT]
# [중요] 차단에서 제외할 화이트리스트 IP를 지정합니다.
# 관리자의 사무실 IP나 로컬 호스트(127.0.0.1/8)를 적어두면 관리자가 실수로 차단되는 대참사를 막을 수 있습니다.
ignoreip = 127.0.0.1/8 ::1 192.168.1.50
# 공격자를 몇 초 동안 차단할지 설정합니다. (예: 1h = 1시간, 1d = 하루, -1 = 영구 차단)
bantime = 1h
# 누적 로그인 실패 횟수를 감시할 시간 범위입니다. (예: 10m = 10분)
findtime = 10m
# findtime 동안 허용할 최대 실패 횟수입니다. 이 횟수를 초과하면 차단됩니다.
maxretry = 5
# 로그를 분석할 백엔드 시스템과 방화벽 매칭 방식을 지정합니다.
backend = auto
banaction = ufw # Ubuntu에서 UFW를 쓰는 경우 (Rocky Linux 등은 firewalld 사용)
위 설정을 요약하면 "10분(findtime) 동안 5번(maxretry) 이상 로그인이 실패한 IP는 화이트리스트(ignoreip)에 매칭되지 않는 한 1시간(bantime) 동안 방화벽으로 차단하겠다"는 의미가 됩니다.
전역 설정을 마쳤다면, 이제 구체적으로 어떤 서비스를 감시할지 '감옥(Jail)'을 지정해야 합니다. 우리는 SSH 서비스를 집중 감시할 것이므로 파일 하단부(또는 별도의 /etc/fail2ban/jail.d/sshd.local 파일)에 SSH 전용 설정을 활성화합니다.
여기서 가장 중요한 것은 지난 2회차에서 수정한 커스텀 SSH 포트 번호를 Fail2ban에게도 명확히 알려주어야 한다는 점입니다. 기본값인 22번 포트만 감시하도록 방치하면, 변경된 포트로 들어오는 공격을 인지하지 못합니다.
jail.local 파일 내부에서 [sshd] 섹션을 찾아 다음과 같이 수정합니다.
Plaintext
[sshd]
# 이 감옥(Jail)을 활성화합니다.
enabled = true
# [매우 중요] 지난 시간에 변경한 커스텀 SSH 포트 번호를 적어줍니다.
port = 22022
# SSH 로그가 기록되는 경로를 지정합니다.
# Ubuntu/Debian은 주로 /var/log/auth.log 이며, Rocky/RedHat 계열은 /var/log/secure 입니다.
logpath = %(sshd_log)s
# 전역 설정보다 SSH에 더 엄격한 규칙을 적용하고 싶다면 개별 지정이 가능합니다.
maxretry = 3
bantime = 1d
설정을 저장하고 나온 뒤, Fail2ban 서비스를 시작하고 시스템 부팅 시 자동으로 켜지도록 등록합니다.
Bash
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
Fail2ban이 정상적으로 구동되고 공격자를 제대로 잡아내고 있는지 관리자가 감시하고 제어할 수 있어야 합니다. Fail2ban은 전용 클라이언트 도구인 fail2ban-client를 제공합니다.
Bash
sudo fail2ban-client status
실행 시 현재 활성화된 감옥 이름(예: Status for the jail: sshd)이 출력됩니다.
Bash
sudo fail2ban-client status sshd
이 명령어를 입력하면 현재까지 실패한 총 횟수, 현재 차단된 IP 개수, 그리고 실제로 방화벽에 갇혀 있는 공격자의 IP 목록(Banned IP list)이 실시간으로 상세히 출력됩니다.
서버를 관리하다 보면 비밀번호를 깜빡하거나 설정을 잘못하여 관리자 본인의 IP가 Fail2ban에 의해 차단당하는 곤란한 상황이 발생할 수 있습니다. (다른 회선이나 다른 IP를 통해 서버에 우회 접속한 뒤) 아래 명령어로 오인 차단된 IP를 구출할 수 있습니다.
Bash
# fail2ban-client unban [차단 해제할 IP] [감옥 이름]
sudo fail2ban-client unban 192.168.1.150 sshd
정상적으로 해제되면 1 또는 성공 메시지가 출력되며 즉시 해당 IP의 접근이 다시 허용됩니다.
이번 시간에 구축한 Fail2ban은 고정된 벽 역할만 하던 방화벽에 '지능'과 '실시간 대응력'을 부여하는 혁신적인 보안 도구입니다. 1회차의 기본 컴플라이언스, 2회차의 키 기반 인증과 주소 숨기기에 이어, 3회차의 Fail2ban 능동 차단 시스템까지 결합되면서 여러분의 리눅스 서버 SSH 환경은 엔터프라이즈급의 강력한 방어력을 갖추게 되었습니다.
공격자가 포트를 찾아내 문을 두드리더라도 딱 3번 실패하는 순간, 서버는 그 공격자의 존재 자체를 한동안 지워버립니다. 이를 통해 무의미한 CPU 소모를 막고 시스템 안정성을 유지할 수 있습니다.
다음 4회차에서는 Fail2ban이 공격자를 가두는 실제 집행 기구이자, 리눅스 네트워크 보안의 사령탑 역할을 하는 방화벽 인프라의 양대 산맥, 'UFW와 Firewalld 실무 활용법'에 대해 세부 메커니즘과 함께 깊이 있게 다루어 보겠습니다. 안전한 서버 운영으로 소중한 데이터를 지켜내시길 바랍니다.