Blog >> Linux >> Whitepapers.
fail2ban 운용
/etc/fail2ban/action.d 그리고 /etc/fail2ban/filter.d 이 두 디렉토리는
fail2Ban이 작동하는 과정에서 각각 ‘공격 감지’와 ‘방화벽 차단’이라는 명확히 분리된 역할을 담당.
📁 디렉토리별 역할 및 설정 연관성
1. action.d 디렉토리 (banaction과 직접 연관)
- 역할: 악성 IP를 실제로 방화벽에 어떻게 차단하고 해제할지 정의된 ‘실행 스크립트(액션 파일)’들이 모여 있는 곳.
- 연관성: 사용자가 설정한
banaction = nftables-multiport라는 값은 곧action.d/폴더 내부에 있는nftables-multiport.conf설정 파일을 읽어서 방화벽 명령을 내리라는 뜻. - 이번에 찾아봤던
nftables-allports.conf,iptables-ipset.conf등의 파일들이 모두 이 폴더에 들어있던 이유가 바로 이 때문.
2. filter.d 디렉토리
- 역할: 로그 파일(예:
/var/log/secure등)에서 어떤 문구를 공격 시도로 판단할지 정의된 ‘정규표현식(필터 파일)’들이 모여 있는 곳. - 연관성:
[sshd]jail이라면filter.d/sshd.conf파일을 읽어서 “Password authentication failed” 같은 실패 로그를 추적하는 역할. - jail.local 의 각 섹션이 filter.d 디렉토리 conf 파일.
💡 한 줄 요약
filter.d는 “누가 범인(공격자)인지 로그에서 찾아내는 규칙“이고,action.d는 찾아낸 범인을 “banaction설정을 통해 방화벽으로 잡아가두는 행동 규칙“.filter.d– 로그 분석 규칙 /action.d– 제어 규칙
~]# fail2ban-client status
Status
|- Number of jail: 7
- Jail list: apache-auth, apache-badbots, apache-custom-get-dos, apache-noscript, recidive, sshd, wordpress-custom-login
# 총 7개의 방어 룰(Jail)이 단 하나의 에러도 없이 완벽하게 메모리에 안착하여 가동 중!!
# sshd: 22번 포트를 노리는 서버 탈취 시도 원천 차단
# apache-auth, apache-badbots, apache-noscript: 아파치 취약점 탐색 및 알려진 악성 해킹 봇 접근 차단
# wordpress-custom-login: 워드프레스 관리자 계정 해킹 및 xmlrpc 취약점 공격 차단
# apache-custom-get-dos: 서버 자원을 고갈시키는 무한 새로고침(L7 DDoS) 트래픽 공격 방어
# recidive: 위 공격들을 반복하는 악질 상습범 1주일 영구 격리
fail2ban-client status [jail 이름]
# sshd 감옥(jail)의 최종 설정값 확인 (예: bantime 확인)
fail2ban-client get sshd bantime
# sshd 감옥의 maxretry(최대 실패 횟수) 설정 확인
fail2ban-client get sshd maxretry
# 실제 설정값(bantime, maxretry 등)을 파일에서 직접 확인
grep -A 5 "\[recidive\]" /etc/fail2ban/jail.d/*.conf /etc/fail2ban/jail.local 2>/dev/null
# 실시간 오류 감시
tail -f /var/log/fail2ban.log
# 실시간 차단 현황
fail2ban-client status sshd
# 동안 총 몇 번이나 'Ban(차단)' 시켰는지 개수 세기
grep "Ban" /var/log/fail2ban.log | wc -l
# 어떤 IP가 가장 극성맞게 공격했는지 TOP 10 뽑기
grep "Ban" /var/log/fail2ban.log | awk '{print $NF}' | sort | uniq -c | sort -nr | head -n 10
# # 특정 IP 차단 수동 등록 (Ban)
fail2ban-client set sshd banip <차단할_IP_주소>
# 특정 IP 차단 수동 해제 (Unban)
fail2ban-client set <Jail 이름> unbanip <해제할 IP>
# 특정 IP 차단 모든 Jail 수동 해제 (Unban)
fail2ban-client unban <해제할_IP>
# 실시간 fail2ban 로그 조회
tail -f /var/log/fail2ban.log
# apache-custom-get-dos 키워드가 포함된 라인을 필터링
grep "\[apache-custom-get-dos\]" /var/log/fail2ban.log
# 특정 Jail의 NOTICE만 필터링
grep "NOTICE" /var/log/fail2ban.log | grep "\[apache-custom-get-dos\]"
# 최근 2일 이내의 NOTICE 기록만 필터링
awk -v limit="$(date -d '3 days ago' '+%Y-%m-%d')" '$1 >= limit' /var/log/fail2ban.log | grep "NOTICE"
# 최근 2일 이내의 발생한 Ban 기록만 필터링
awk -v limit="$(date -d '2 days ago' '+%Y-%m-%d')" '$1 >= limit' /var/log/fail2ban.log | grep "NOTICE" | grep "Ban"
#지난 2일간 필터별 Ban 횟수
awk -v limit="$(date -d '2 days ago' '+%Y-%m-%d')" '$1 >= limit' /var/log/fail2ban.log | grep "NOTICE" | grep -w "Ban" | grep -v "Restore" | sed 's/.*\[\(.*\)\] Ban.*/\1/' | sort | uniq -c | sort -nr
# apache-custom-get-dos 필터로 ban 된 IP
grep "\[apache-custom-get-dos\] Ban" /var/log/fail2ban.log
# 지난 2일간 특정 Jail의 Ban 내역
awk -v limit="$(date -d '2 days ago' '+%Y-%m-%d')" '$1 >= limit' /var/log/fail2ban.log | grep "NOTICE" | grep -w "Ban" | grep -v "Restore" | grep "apache-custom-get-dos" | awk '{print $1, $2, $NF}' | awk '{print; count++} END {print "-------------------------------------"; print "apache-custom-get-dos Ban 총횟수:", count; print "-------------------------------------"}'
# 설정한 예외 처리(ignoreregex)가 제대로 적용되었는지 확인하는 방법
fail2ban-client get apache-custom-get-dos ignoreregex
# fail2ban-regex 명령어를 사용하여 현재 아파치 로그가 방금 수정한 필터 규칙에 의해
# 정상적으로 무시(Ignored)되고 있는지 시뮬레이션
# 확인 방법: 출력 결과 중 아래 항목들을 확인합니다.
# Ignored: 무시된 로그 수 (이 수치가 올라가야 정상입니다)
# Matched: 여전히 공격으로 오인되어 매칭된 로그 수
fail2ban-regex /var/log/httpd/[도메인]-access_log /etc/fail2ban/filter.d/apache-custom-get-dos.conf
# 설정을 수정했다면 반드시 리로드 명령어를 실행
fail2ban-client reload apache-custom-get-dos
# 특정 IP(59.22.125.160)가 아파치 로그에 어떤 요청을 보내고 있는지 실시간으로 필터링
tail -f /var/log/httpd/*access_log | grep --line-buffered "59.22.125.160"
# 해당 규칙으로 Ban 당한 아이피 조회
grep "\[apache-custom-get-dos\] Ban" /var/log/fail2ban.log
# 특정 IP가 recidive Jail에 의해 차단된 이력이 있는지 확인
grep "\[recidive\].*13.70.107.184" /var/log/fail2ban.log
# Fail2ban 로그의 날짜 형식(YYYY-MM-DD)은 문자열 크기 비교가 가능하므로,
# 리눅스의 date 명령어와 awk를 조합하면 "최근 N일" 기준의 기간 필터를 가장 깔끔하게 구현
# date -d '2 days ago' '+%Y-%m-%d'를 통해 오늘 기준 2일 전
# awk는 Fail2ban 로그의 첫 번째 필드($1, 날짜)가 기준일 이후인 라인만 추림
# grep으로 해당 jail의 Ban 내역만 깔끔하게 뽑아냄
awk -v limit="$(date -d '2 days ago' '+%Y-%m-%d')" '$1 >= limit' /var/log/fail2ban.log | grep "\[apache-custom-get-dos\] Ban"
# 정규식(Regex)을 이용한 직접 패턴 매칭 방식
# 2026-10-0[5-7] 정규식은 2026-10-05, 2026-10-06, 2026-10-07 날짜로 시작하는 로그만 매칭
grep -E "2026-10-0[5-7].*\[apache-custom-get-dos\] Ban" /var/log/fail2ban.log과거의 GeoIP(레거시 데이터베이스 형식)가 단종되고, MaxMind 사가 GeoLite2 형식으로 데이터베이스 구조를 변경하면서 리눅스 배포판들이 더 이상 구형 패키지를 기본 제공하지 않음.
방법 1. Firewalld 고유 기능 활용 (가장 추천)
현재 방화벽 백엔드 nftables로 정상화했기 때문에, 별도의 외부 패키지 설치 없이 firewalld 자체에 국가 별 IP 목록(Zone 또는 IPset)을 등록하는 것이 가장 안전하고 부하가 적음.
- MaxMind 공식 홈페이지에서 무료 배포하는 GeoLite2 Country (CSV 형식) 데이터베이스를 다운로드.
- 다운로드한 CSV 파일에서 차단하고 싶은 국가(예: 중국
CN, 러시아RU등)의 IP 대역만 추출. firewall-cmd명령어를 사용하여 해당 대역들을 하나의 거대한 최신 세트로 밀어 넣고 차단구역(Drop Zone)에 지정.
방법 2. Fail2Ban 커스텀 스크립트 연동 (geoiplookup 대체)
구형 geoiplookup 명령어 대신, 현대적인 mmdblookup 패키지나 Python 스크립트를 사용하여 Fail2Ban이 차단하기 전에 국가를 판별하게 만드는 방식.
# 로키 리눅스 10(Rocky Linux 10)에서 libmaxminddb-devel 패키지는
# CRB(CodeReady Builder) 저장소에서 제공
~]# dnf config-manager --set-enabled crb
~]# dnf install libmaxminddb libmaxminddb-devel
# MaxMind에서 GeoLite2-Country.mmdb 파일을 다운로드하여 /usr/share/GeoIP/ 폴더에 배치
# GeoIP 폴더 생성
~]# mkdir -p /usr/share/GeoIP
# 무료 오픈소스 버전 데이터베이스 다운로드 및 배치
~]# curl -sSLo /usr/share/GeoIP/GeoLite2-Country.mmdb "https://github.com/wp-statistics/GeoLite2-Country/blob/master/GeoLite2-Country.mmdb.gz"
~]# gzip -d /usr/share/GeoIP/GeoLite2-Country.mmdb.gz
~]# chmod 644 /usr/share/GeoIP/GeoLite2-Country.mmdb
# 최종 파일 용량 확인 (정상적이라면 약 8MB 사이)
~]# ls -lh /usr/share/GeoIP/GeoLite2-Country.mmdb
# 최신 nftables 및 mmdblookup 기반 스크립트 실행
~]# for ip in $(nft list set inet f2b-table addr-set-wordpress-custom-login 2>/dev/null | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'); do echo -n "$ip: "; mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip $ip country names en 2>/dev/null | awk -F'"' '{print $2}' | grep . || echo "N/A"; done
# 기존 구형 리눅스
~]# yum install GeoIP
... 중략 ...
Complete!
# 기존 iptbles 기반 스크립트 실행
~]# for ip in $(sudo ipset list f2b-sshd | grep timeout | awk '{print $1}'); do echo -n "$ip: "; geoiplookup $ip | awk -F': ' '{print $2}'; done
..... 중략 .....스크립트를 만들어서 root 로그인 시 차단 내역 보고. 해당 아이피 geoip 정보 조회.
# 상단에 if [ "$EUID" -ne 0 ]; then exit 0; fi 구문을 추가하여
# root 로그인 시 노티할 수 있게 안전장치를 마련
~]# vi /usr/local/sbin/custom-noti-ban.sh
# 실행 권한
~]# chmod 700 /usr/local/sbin/custom-noti-ban.sh
# 로그인 시 출력 가능하게 심볼릭 링크를 /etc/profile.d 디렉토리에 걸어둠.
~]# ln -s /usr/local/sbin/custom-noti-ban.sh /etc/profile.d/custom-noti-ban.sh
# 특정 아이피 조회
~]# vi /usr/local/sbin/custom-check-geoip.sh <조회할 IP>
- 포스트 태그:
- fail2ban
- geoip
- libmaxminddb
- 포스트 위치:
- Linux
- Whitepapers
<< 이전 페이지



