[CentOS 7] fail2ban apache DoS 설정

mimic1995·2024년 2월 1일

사전 작업

서버 사양 확인

항목value
OSCentOS Linux release 7.9.2009 (Core)
kenel3.10.0-1160.66.1.el7.x86_64
apache2.4.54 (Unix) prefork

운영 방화벽 백업

cp -arp /etc/sysconfig/iptables /etc/sysconfig/iptables_backup
iptables-save > /etc/sysconfig/iptables_serviceRule_backup

fail2ban 적용 시 기존 iptables 룰셋이 fail2ban 기반으로 변경되기 때문에 사전에 룰셋을 꼼꼼하게 백업해둬야 합니다.

python 확인

python --version
===
Python 2.7.5
===
python3 --version
===
Python 3.6.8
===

python 3.5 ↑ 버전이 설치되어 있어야 fail2ban 설치가 원활하게 이루어집니다.

https://github.com/fail2ban/fail2ban

github를 통해 설치할 수 있지만 확장 epel 레포 파일 추가 후 yum으로 패키지 설치해보겠습니다.

https://github.com/fail2ban/fail2ban/wiki/How-to-install-fail2ban-packages

fail2ban 설치

확장 repo 설치

cd /usr/local/src
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm

또는 

rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

한 번에 설치도 가능합니다.

yum install -y epel-release

fail2ban 설치

rpm -qa | grep fail2ban
===

===
yum install -y fail2ban fail2ban-systemd
systemctl enable fail2ban --now 

firewalld 관련 설정 삭제

iptables를 이용하므로 해당 설정파일을 삭제합니다.

rm -f /etc/fail2ban/jail.d/00-firewalld.conf

fail2ban 설정파일

폴더

/etc/fail2ban: 기본 파일 경로
/etc/fail2ban/filter.d: 로그 파일 분석 시 사용하는 필터 관련 설정 파일 저장
/etc/fail2ban/action.d: 필터링에 걸렸을 때 사용할 액션 파일 저장
/etc/fail2ban/jail.d: 룰셋 설정 파일 저장

파일

/etc/fail2ban/jail.conf: default 설정 파일
/etc/fail2ban/jail.local: 별도로 생성해야 하는 설정 파일이며, jail.conf 역할을 대신하기 때문에 jail.conf를 복사하여 생성합니다.
jail.conf는 업데이트 시 초기화되기 때문에 local이란 파일로 별도 생성하여 사용합니다.
/etc/fail2ban/fail2ban.conf: Log 설정 파일

설정파일 적용 순서는 아래와 같습니다.

/etc/fail2ban/jail.conf/etc/fail2ban/jail.d/*.conf/etc/fail2ban/jail.local/etc/fail2ban/jail.d/*.local

만일 jail.d 하단에 conf 파일이 있다면 jail.local 파일보다 우선적용되기 때문에 작업자 성향에 맞게 파일을 생서하시면 됩니다.

jail.conf 옵션

파일 내에서 []를 기준으로 설정을 구분합니다. 안에는 서비스 데몬이나 어떤 것에 적용할지 대분류할 이름을 적어주면 됩니다.

# 초기 설정에서 주석처리 되어 있으며, sshd 전용 설정을 사용하려는 경우 enabled = true 주석을 상단에서 해제하거나 별도로 넣어줘야 함
# [sshd]
# enabled = true

# INCLUDES는 추가 설정을 다루며, 아래 옵션은 fedora 기반 운영체제에서 우선적으로 설정파일을 불러오도록 하는 옵션
[INCLUDES]
#before = paths-distro.conf
before = paths-fedora.conf

# DEFAULT는 fail2ban 기본 설정을 하는 파트로 주요항목만 기재해두었음
[DEFAULT]
# 무시해야되는 로그 문자열 기재
ignorecommand =
# 얼마동안 IP를 차단할지 설정 (기본 값 10분)
bantime  = 10m
# 조건 필터링에서 N초 동안 N번에서 N초 부분 
findtime = 10m
# N초 동안 N번에서 N번 부분
maxretry = 5
# 이 곳에 기재된 IP는 조건 상관없이 허용 됨
ignoreip = 
# 로그 수집에 사용할 백엔드 지정
# 기본 값이 auto이나 systemd로도 가능
backend = auto
# 한 번의 로그 라인에서 최대 몇 번까지 일치 값을 찾을 건지 설정
# 기본 값이 maxretry 값을 참조
maxmatches = %(maxretry)s
# dns 검증 사용할지 여부
# warn: DNS 확인을 수행하되, 만약 실패하면 경고 메시지만 표시하고 계속 진행하고 역 DNS 확인이 성공하면 해당 IP 주소를 사용
# no: DNS 확인을 수행하지 않고 직접 추출한 IP 주소를 사용합니다.
# yes: DNS 확인을 수행하며, 역 DNS 확인이 실패하면 해당 로그 라인을 무시
usedns = warn
# 로그파일 인코딩 지정
# 기본 값인 auto는 기존 로그의 인코딩 방식을 감지하므로 보통의 경우 기본 값 유지
logencoding = auto
# 해당 설정(jail)을 사용할지 여부를 나타내며, 여기서 jail은 []에 감싸진 프로토콜 이름을 의미
enabled = false
# jail의 작동 모드를 설정 
# normal: 기본 모드로, findtime 동안 maxretry에 도달하면 해당 IP 주소를 차단
# aggressive: 공격을 감지하면 자동으로 차단, findtime과 maxretry 설정이 무시되고, 일정 기간 동안 공격을 감지하면 즉시 차단
mode = normal
# 로그필터를 의미
# %(__name__)s와 %(__mode__)s는 해당 jail의 이름과 모드를 나타내는 플레이스홀더
filter = %(__name__)s[mode=%(mode)s]
# 이메일 알림 설정
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
# 감지할 로그에서 사용되는 프로토콜 지정
protocol = tcp
# iptables에 대한 설정으로, 어떤 iptables chain을 사용할지를 지정
chain = <known/chain>
# jail에서 감시할 포트 번호 지정 
# 0:65535는 리눅스 모든 tcp 포트를 의미
port = 0:65535
# fail2ban에 의해 전송되는 User-Agent 헤더 값을 설정
# %()를 사용하여 변수를 참조하며, 아래 기본 양식은 버전을 출력하도록 되어 있음
fail2ban_agent = Fail2Ban/%(fail2ban_version)s
# jail에서 사용할 차단 액션
# iptables-multiport: iptables를 사용하여 IP를 차단
banaction = iptables-multiport
# 모든 포트에 대한 차단을 수행할 때 사용할 차단 액션
# iptables는 감시 결과에 따른 모든 포트에 대해서 차단을 진행
banaction_allports = iptables-allports
# 구체적인 차단 액션
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# 차단 후 메일 발송을 같이 진행 
action_mw = %(action_)s
            %(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
# 차단 후 메일 발송을 같이 진행하며, 로그 라인을 메일 내용에 포함
action_mwl = %(action_)s
             %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
# 차단 후 xarf 형식의 로그 생성
action_xarf = %(action_)s
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
# cloudflare을 사용하여 차단 후 메일 발송을 같이 진행
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"] 
# blocklist_de 사용 시 활용 옵션
action_blocklist_de  = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
# abuseipdb로 메일 발송
action_abuseipdb = abuseipdb
# 정의된 액션을 실제 실행하는 구문
action = %(action_)s

기본 apache jail 목록

[apache]: 실패한 로그인 시도를 차단합니다.
fail2ban은 Apache 서버의 로그를 모니터링하여 로그인 실패가 발생할 경우 해당 IP 주소를 차단합니다.
[apache-noscript]: 스크립트를 검색하고 실행하는 원격 클라이언트를 차단합니다.
스크립트를 탐지하고 실행하는 원격 클라이언트에 대한 차단을 수행합니다. 보안 취약점을 이용하려는 시도를 방지합니다.
[apache-overflows]: 의심스러운 URL을 요청하는 클라이언트를 차단합니다.
클라이언트가 의심스러운 URL을 요청하는 시도를 감지하고 차단합니다. 서버에 대한 공격으로부터 보호합니다.
[apache-badbots]: 악성 봇 요청을 차단합니다.
악성 봇에 의한 요청을 감지하고 차단하여 웹 서버를 보호합니다. 예를 들어, 스크랩핑 봇이나 악성 행위를 목적으로 하는 봇들을 차단합니다.


apache 관련 룰셋 설정

설정파일 생성

/etc/fail2ban/jail.conf 파일로 관리하지만 jail.local 파일로 대체하여 관리가 가능합니다.

awk '!/^ *#/ && NF' /etc/fail2ban/jail.conf > /etc/fail2ban/jail.local

apache 로그 경로 확인

로그 수집 기반으로 동작하기 때문에 apache에 적용하려는 도메인이 어떤 경로로 로그를 쌓고 있는지 확인합니다.
테스트 서버에서는 /var/log/httpd 하단에 쌓이는 것을 확인하였습니다.

tail -n 4 /var/log/httpd/access_log
===
167.248.133.182 - - [01/Feb/2024:14:06:21 +0900] "GET / HTTP/1.1" 200 3 "-" "-"
167.248.133.182 - - [01/Feb/2024:14:06:27 +0900] "GET / HTTP/1.1" 200 3 "-" "Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"
167.248.133.182 - - [01/Feb/2024:14:06:27 +0900] "PRI * HTTP/2.0" 400 226 "-" "-"
167.248.133.182 - - [01/Feb/2024:14:06:27 +0900] "GET /favicon.ico HTTP/1.1" 404 196 "-" "Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"
===

악성 봇이 마구 들이닥치고 있습니다.

apache 설정 추가

설정 파일 하단 부에 보면 가장 많이 사용되는 ssh와 apache 데몬 관련해서는 default로 설정 부분이 있습니다. log 부분을 수정해줍니다.

vi /etc/fail2ban/jail.local
===
# [DEFAULT] 부분에서 수정
findtime  = 60
maxretry = 10

# [apache-badbots] 부분
enabled  = true
port     = http,https
logpath  = /var/log/httpd/*access_log
bantime  = 48h
maxretry = 1
===

이렇게 등록을 하다보니 문득 filter를 기존 제공해주는 것이 아닌 새로 만들어서 써야 한다는 느낌이 들었습니다. 왜냐하면 기본 제공 jail이 참조하는 fileter를 /etc/fail2ban/filter.d에서 찾아보니 제가 원하는 횟수에 따라 제한하는 DoS 차단의 필터가 없었기 때문입니다.

ls -al filter.d/apache-*
===
-rw-r--r--. 1 root root 3228  41  2023 filter.d/apache-auth.conf
-rw-r--r--. 1 root root 2831  41  2023 filter.d/apache-badbots.conf
-rw-r--r--. 1 root root 1265  41  2023 filter.d/apache-botsearch.conf
-rw-r--r--. 1 root root 1619  41  2023 filter.d/apache-common.conf
-rw-r--r--. 1 root root  403  41  2023 filter.d/apache-fakegooglebot.conf
-rw-r--r--. 1 root root  511  41  2023 filter.d/apache-modsecurity.conf
-rw-r--r--. 1 root root  596  41  2023 filter.d/apache-nohome.conf
-rw-r--r--. 1 root root 1246  41  2023 filter.d/apache-noscript.conf
-rw-r--r--. 1 root root 2187  41  2023 filter.d/apache-overflows.conf
-rw-r--r--. 1 root root  362  41  2023 filter.d/apache-pass.conf
-rw-r--r--. 1 root root 1020  41  2023 filter.d/apache-shellshock.conf
===

DoS용 필터 생성

vi /etc/fail2ban/filter.d/apache-antiDos.conf
===
[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD).*
Ignoreregex =
===

/var/log/httpd/access_log 양식에 맞춰 표현해줍니다. 필터는 모든 접근 시 동일한 값으로 나오는 것을 최대한 넣어줍니다.

jail conf 파일 생성

이제 위에서 생성한 DoS용 필터 파일을 사용하는 jail을 만들어줍니다.

vi /etc/fail2ban/jail.d/apache.conf
===
[apache]
enabled = true
port = http,https
filter = apache-antiDos
logpath = /var/log/httpd/*access_log
maxretry = 10
findtime = 60
bantime = 10m
===

재시작을 해서 적용합니다.

systemctl reload|restart fail2ban

apache jail이 잘 적용되었는지 status로 확인합니다.

fail2ban-client status apache
===
Status for the jail: apache
|- Filter
|  |- Currently failed:	0
|  |- Total failed:	0
|  `- File list:	/var/log/httpd/access_log
`- Actions
   |- Currently banned:	0
   |- Total banned:	0
   `- Banned IP list:	
===

fail2ban 로그 설정

INFO 제외

vi /etc/fail2ban/fail2ban.conf
===
loglevel = NOTICE
===
systemctl restart fail2ban

로그 레벨을 NOTICE로 변경하면 IP Ban/Unban만 이력에 남고 FOUND IP 내역은 남지 않아 쓸데없는 로그를 줄일 수 있습니다.

logrotate

로그파일의 용량이 크지 않아 로그 로테이트 데몬을 이용할까 하다가 bash 스크립트로 간단히 짜보았습니다.

#!/bin/bash

log=/var/log/fail2ban.log
backupdir=/backup/fail2banLog
logdate=$(date +%Y-%m-%d)

mkdir -p $backupdir

# 7일 이상 지난 로그 백업본 삭제
find $backupdir/* -daystart -mtime +7 -exec rm -f {} \;

# 당일 로그 백업본 backup 경로에 생성
cat $log >> $backupdir/fail2ban.log_${logdate}

# 실제 로그 비우기
cat /dev/null >> $log

# fail2ban 재시작
systemctl restart fail2ban

테스트

차단 기능

설정에 60초(1분)동안 10회를 설정해두었으니 미친듯이 새로고침해줍니다.

클라이언트에서는 차단된 내역을 확인하였고 이제 fail2ban에서 확인해줍니다.

fail2ban-client status apache
===
Status for the jail: apache
|- Filter
|  |- Currently failed:	1
|  |- Total failed:	14
|  `- File list:	/var/log/httpd/access_log
`- Actions
   |- Currently banned:	1
   |- Total banned:	1
   `- Banned IP list:	비공개
===

수동 차단 또는 해제

# 차단
fail2ban-client set apache banip IP주소
# 차단해제
fail2ban-client set apache unbanip IP주소

로그 확인

/var/log/fail2ban.log에서 확인 가능합니다.

2024-02-01 14:58:01,793 fail2ban.actions        [135402]: NOTICE  [apache] IP already banned
...
2024-02-01 14:59:45,366 fail2ban.actions        [135553]: NOTICE  [apache] Unban IP
profile
Raiju Hantu Goryo Obake

0개의 댓글