Blog >> Linux >> Whitepapers.

fail2ban 설치 150 150 phobe

fail2ban 설치

외부 공인 IP를 통해 간헐적으로 SSH를 개방할 때 발생하는 무차별 대입 공격(Brute-force)과 로그 도배를 막기 위한 4가지 실무적인 해결책 중 적용 할 방법을 찾아 보려 한다. 이중 현실적인 fail2ban.

  1. firewalld 특정 IP/대역만 허용 – DHCP 외부 접속 문제
  2. 외부 접속용 SSH 포트 변경 – 표준 포트 사용을 선호
  3. Firewalld 비율 제한(Rate Limiting) 적용 – Firewalld 자체 기능으로 분당 접속 시도 횟수를 제한
  4. Fail2Ban 도입 (능동적 차단) – 시스템이 실시간으로 감지하고 방화벽 단에서 IP를 영구적(또는 일시적)으로 차단

fail2ban이 운영 중인 서버에 무리를 주지 않고 안정적인 이유는 다음과 같다.

  • 독립적인 읽기 전용 동작: Fail2Ban은 SSH 연결 자체에 개입하거나 네트워크 트래픽을 직접 가로채지 않는다. 오직 백그라운드에서 /var/log/secure 같은 로그 파일의 텍스트만 조용히 읽어들인다.
  • 낮은 리소스 점유율: 시스템의 핵심 데몬과 분리되어 작동하며, 정규식으로 로그 패턴을 매칭 할 때만 리소스를 사용하므로 CPU나 메모리 부하가 거의 없다.
  • 기존 방화벽 활용: 차단 기능을 직접 수행하는 것이 아니라, 리눅스 자체 방화벽인 firewalld에 차단 규칙(Rule)을 추가하라는 명령만 전달한다. 실제 패킷 차단은 커널 수준의 방화벽이 처리하므로 효율적이다.
  • 휘발성 룰 관리: 차단된 IP는 지정된 시간(예: 24시간)이 지나면 방화벽 규칙에서 자동으로 삭제된다. 차단 목록이 무한정 쌓여 방화벽 성능이 저하되는 것을 스스로 방지한다.

fail2ban 패키지 설치. 설치 전에 epel 저장소를 먼저 설정한 후 설치.
SSH 포트(22번)를 무작위로 찌르는 공격자를 자동으로 차단하도록 정책(Jail)을 설정.
봇 들이 22번 포트를 5분(600초) 이내에 3번만 찔러도 하루 동안 알아서 튕겨나가게 설정.
7개의 정책 설정.

jail.local 각 섹션 별 설정

fail2ban이 구동되어 SSH(sshd) 감시를 제대로 시작했는지 확인 – 설정 7개 확인.
fail2ban의 jail.local 파일은 표준 INI 설정 파일 형식([섹션], 키 = 값)을 따르며, #이나 ;을 사용하여 주석을 작성.

  • [DEFAULT] 섹션: 파일 전체에 공통으로 적용되는 기본값을 설정합니다. 각 개별 감옥(jail)에서 재정의하지 않는 한 이 값을 따릅니다.
  • 개별 감옥 섹션 (예: [sshd]): 특정 서비스나 로그를 모니터링하기 위한 개별 설정을 지정합니다. enabled = true를 넣어야 활성화됩니다.
  • 값 할당: 키 = 값 형태로 작성하며, 등호(=) 앞뒤의 공백은 무시됩니다.
  • enabled: 감옥 활성화 여부 (true 또는 false)
  • port: 차단할 포트 번호 또는 서비스 이름 (예: ssh, http,https 또는 숫자 80,443)
  • filter: /etc/fail2ban/filter.d/ 디렉터리에 있는 필터 파일 이름 (확장자 제외)
  • logpath: 모니터링할 로그 파일 경로
  • maxretry: 차단 전 최대 허용 실패 횟수
  • findtime: 실패 횟수를 카운트할 시간 범위
  • bantime: 차단 유지 시간
~]# dnf install fail2ban fail2ban-firewalld
..... 설치 중략 .....
완료되었습니다!

~]# vi /etc/fail2ban/jail.local
[DEFAULT]
# 내 내부망 IP 대역은 차단 대상에서 제외 (관리자 보호용, 필요시 본인 대역으로 수정)
ignoreip = 127.0.0.1/8 192.168.168.0/24
# DNS 역조회(Reverse DNS Lookup)를 시도 방지
usedns = no

# 5분(600초) 이내에
findtime = 5m
# 3번 접속 시도 실패 시
maxretry = 3
# 24시간(86400초) 동안 방화벽에서 IP를 차단
bantime = 24h

# firewallcmd-ipset 액션은 Fail2Ban이 ipset 명령어를 직접 내려서 세트를 만드는 것이 아니라, 
# firewalld 방화벽(데몬)에게 "ipset 세트 제어해줘"라고 요청하는 방식
# ipset 조회를 위해 변경하려면 - firewalld, fail2ban 세트 변경
#banaction = firewallcmd-ipset
# 최신 OS에서는 nftables
# 공격이 감지된 특정 포트만 차단할 때 사용
banaction = nftables-multiport
# Fail2Ban이 특정 jail(제일)에서 "모든 포트(All Ports)를 차단해야 할 때"
banaction_allports = nftables-allports

[sshd]
..... 중략 .....
[apache-auth]
..... 중략 .....
[apache-badbots]
..... 중략 .....
[apache-noscript]
..... 중략 .....
[apache-custom-get-dos]
..... 중략 .....
[wordpress-custom-login]

[recidive]
..... 중략 .....

아파치 DoS 커스텀 필터 생성
편집 작업 중 빈번하게 발생하는 정상적인 백그라운드 요청(admin-ajax.php, wp-json, wp-admin 등)을 Fail2ban 필터 검사에서 아예 제외(ignoreregex)시킴.

~]# vi /etc/fail2ban/filter.d/apache-custom-get-dos.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*
ignoreregex = (?i)\.(jpe?g|png|gif|css|js|ico|svg|woff|woff2|ttf|eot)
          ^<HOST> -.*"(GET|POST) .*(/wp-admin/|/wp-json/|admin-ajax\.php|wp-cron\.php)

워드프레스 로그인 커스텀 필터 생성

~]# vi /etc/fail2ban/filter.d/wordpress-custom-login.conf
[Definition]
failregex = ^<HOST> .* "POST .*(wp-login\.php|xmlrpc\.php).* HTTP.*"
ignoreregex =

fail2ban 등록 및 시작. 상태 확인. 및 테스트

~]# systemctl enable fail2ban
~]# systemctl start fail2ban
~]# systemctl status fail2ban

# Dos 방어테스트
~]# fail2ban-regex /var/log/httpd/gldigital.co.kr-access_log /etc/fail2ban/filter.d/apache-custom-get-dos.conf
... 중략 ...

# 워드프레스 방어 필터 테스트
~]# fail2ban-regex /var/log/httpd/gldigital.co.kr-access_log /etc/fail2ban/filter.d/wordpress-custom-login.conf

# 시스템에 등록된 selinux fail2ban 컨텍스트 조회
~]# semanage fcontext -l | grep fail2ban

# fail2ban 컨텍스트 확인
~]# ll  -Z /var/log/fail2ban.log 
-rw-------. 1 root root system_u:object_r:fail2ban_log_t:s0 3892639 10월  7일  00:06 /var/log/fail2ban.log

# 리치 룰 확인
~]# firewall-cmd --list-rich-rules

몇 가지 에러 상황 확인 ipset list f2b-sshd 명령을 내렸을 때, 혹은 journalctl -u firewalld -n 20 명령어에
firewalld 로그에 찍힌 ERROR: INVALID_IPV: 'ipv4' is not a valid backend or is unavailable
에러는 firewalld가 백엔드로 nftables를 사용하고 있는데, Fail2Ban이 과거 방식(iptables/ipset)의 Direct 규칙을 억지로 밀어 넣으려고 해서 발생한 충돌.

Step 1. firewalld 백엔드 설정 변경 (가장 중요)
~]# vi /etc/firewalld/firewalld.conf
# FirewallBackend
# 방화벽 백엔드 구현을 선택합니다.
# 선택지는 다음:
#       - nftables (기본)
#       - iptables (iptables, ip6tables, ebtables and ipset)
# Note: iptables 백엔드는 더 이상 권장되지 않으며, 향후 릴리스에서 제거될 예정.
FirewallBackend=nftables

~]# systemctl restart firewalld

Step 2. Fail2Ban이 [DEFAULT] 섹션에 nftables를 쓰도록 차단 액션 변경.
~]# vi /etc/fail2ban/jail.local
[DEFAULT]
banaction = firewallcmd-nftables
banaction_allports = firewallcmd-nftables

# 방화벽 리로드
~]# firewall-cmd --reload

# Fail2Ban 재시작
~]# systemctl restart fail2ban

# 이제 백엔드가 nftables로 바뀌었기 때문에 더 이상 ipset list 명령어를 사용하지 않음.
# 대신 아래 명령어로 차단 세트를 조회
~]# nft list sets
... 중략 ...

~]# systemctl status firewalld

~]# systemctl status fail2ban

# firewalld 로그를 실시간으로 감시.
~]# journalctl -u firewalld -f

# 실제로 Fail2Ban이 sshd 제일에 어떤 액션을 최종 할당했는지 아래 명령어로 실시간 검증
~]# fail2ban-client get sshd actions
구분CentOS 7.9Rocky Linux (최신 배포판)
방화벽 엔진iptables 기반 (단일 체계)nftables 기본
firewalld.confFirewallBackend 옵션 없음FirewallBackend=nftables 기본
Fail2Ban 액션banaction = firewallcmd-ipsetbanaction = nftables-multiport
조회 명령어ipset listnft list sets
  • fail2ban 운용 150 150 phobe fail2ban 운용
  • ssh 공개키 전용 인증 설정 150 150 phobe ssh 공개키 전용 인증 설정