fail2ban은 log파일을 참조하여 filter에 정의된 정규표현식 등을 사용하여 필터링에 부합할 경우 해당 로그 파일 안에 있는 IP를 기록하고 block하는 brute force 차단 시스템이다.
기본적으로 인증이 필요한 nginx, apache 및 smtp, ssh 등 다양한 서비스에 대한 방어가 가능하다.
또한 기본 제공되는 filter template의 종류가 많기 때문에 config 설정만 진행하여 사용할 수도 있는데 적합한 filter가 없는 경우 별도로 생성해주어야 할 경우가 있다. 기본적으로 정규표현식을 기반으로 로그 파일을 탐색하기 때문에 정규표현식에 대한 이해가 필요하다.
우선 fail2ban 설치 방법은 아래와 같다.(ubuntu 22.04 기준)
1. fail2ban 설치
sudo apt update ; sudo apt install fail2ban -y
2. fail2ban 서비스 시작 및 부팅 시 자동 실행 등록
systemctl start fail2ban.service
systemctl enable fail2ban.service
3. fail2ban 설치 상태 및 버전 확인
4. 기본 설정 파일
/etc/fail2ban/jail.conf #fail2ban 기본 설정 파일
/etc/fail2ban/filter.d/ #filter 설정 폴더
native 설치 시 기본적으로 여러 jail이 설정되어 있다. jail.conf 파일의 설정 항목은 아래와 같다.
설정 항목 | 내용 |
bantime = 10m | 로그 발견 시 차단할 시간( -1 : 영구 차단) |
findtime = 10m | 로그 파일 내 검색할 시간 범위 |
maxretry = 5 | 차단할 시도 횟수 |
ignoreip = 127.0.0.1/8 ::1 | 차단을 유예할 IP 지정(whitelist IP) |
destemail = root@localhost | 메일 서버 설정 시 action 결과 메일 발송 |
이후 밑에 각 jails 별로 설정을 추가하여 사용하면 된다.
만약 원하는 서비스나 filter가 없는 경우 fail2ban 설정과 filter를 추가해 설정한다.
# vi /etc/fail2ban/jail.conf
[test]
enabled = true
port = http,https
filter = nginx_test
logpath = /var/log/nginx/access.log
jail.conf에 추가할 jail을 입력한다.
# vi /etc/fail2ban/filter.d/nginx_test.conf
[Definition]
failregex = ^<HOST>.*"(GET|POST).*" (4[0-9]{2}) .*$
ignoreregex =
filter.d 경로에 filter 파일을 생성하고 기본적으로 위와 같은 형태로 설정한다.
failregex : 로그 파일 내 fail 패턴을 지정(해당 패턴에 매치 되는 경우 action에 따라 처리)
ignoreregex : 로그 파일 내 무시할 패턴을 지정(로그 파일 내 해당 패턴이 존재할 경우 ignore)
위의 예시는 /var/log/nginx/access.log 로그에 failregex에 정의한 패턴에 매치 되는 지를 확인하는 것이고 HTTP method가 GET or POST이고 HTTP status code가 4xx 인 로그가 발생하면 해당 로그에 대한 ban을 수행한다.
filter를 생성 후 테스트는 아래와 같이 수행한다.
#fail2ban-regex [로그명] [필터명]
설정이 완료되면 fail2ban 데몬을 재기동 시킨다.
systemctl restart fail2ban.service
이후 아래와 같이 nginx에 접근 시 filter에 정의한 regex 패턴에 매칭 되는 로그가 확인되면 try count가 증가하고 설정된 횟수를 초과하면 jail에 등록된다.
# tail -f /var/log/nginx/access.log
xxx.xxx.xxx.30 - - [23/Jul/2024:15:51:43 +0900] "GET / HTTP/1.1" 400 396 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0"
xxx.xxx.xxx.30 - - [23/Jul/2024:15:51:43 +0900] "GET /favicon.ico HTTP/1.1" 404 197 "http://xxx.xxx.xxx.10/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0"
#tail -f /var/log/fail2ban.log
2024-07-23 15:58:33,789 fail2ban.jail [6245]: INFO Jail 'test' uses pyinotify {}
2024-07-23 15:58:33,794 fail2ban.jail [6245]: INFO Initiated 'pyinotify' backend
2024-07-23 15:58:33,795 fail2ban.filter [6245]: INFO maxRetry: 5
2024-07-23 15:58:33,795 fail2ban.filter [6245]: INFO findtime: 600
2024-07-23 15:58:33,795 fail2ban.actions [6245]: INFO banTime: 600
2024-07-23 15:58:33,795 fail2ban.filter [6245]: INFO encoding: ISO-8859-1
2024-07-23 15:58:33,795 fail2ban.filter [6245]: INFO Added logfile: '/var/log/nginx/access.log' (pos = 8xx6, hash = 2a6d04xxxxxxxxxxa17f68cbced7e632)
2024-07-23 15:58:33,798 fail2ban.jail [6245]: INFO Jail 'test' started
2024-07-23 15:59:16,268 fail2ban.filter [6245]: INFO [test] Found xxx.xxx.xxx.30 - 2024-07-23 15:59:15
2024-07-23 16:04:09,605 fail2ban.filter [6245]: INFO [test] Found xxx.xxx.xxx.30 - 2024-07-23 16:04:09
2024-07-23 16:04:12,312 fail2ban.filter [6245]: INFO [test] Found xxx.xxx.xxx.30 - 2024-07-23 16:04:11
2024-07-23 16:04:13,916 fail2ban.filter [6245]: INFO [test] Found xxx.xxx.xxx.30 - 2024-07-23 16:04:13
2024-07-23 16:04:15,519 fail2ban.filter [6245]: INFO [test] Found xxx.xxx.xxx.30 - 2024-07-23 16:04:15
2024-07-23 16:04:15,609 fail2ban.actions [6245]: NOTICE [test] Ban xxx.xxx.xxx.30
ban list 확인은 아래 명령어로 수행한다.
root@ubuntu:/etc/fail2ban# fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: test
root@ubuntu:/etc/fail2ban# fail2ban-client status test
Status for the jail: test
|- Filter
| |- Currently failed: 0
| |- Total failed: 5
| `- File list: /var/log/nginx/access.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: xxx.xxx.xxx.30
차단된 IP unban은 아래와 같이 수행한다.
root@ubuntu:/etc/fail2ban# fail2ban-client unban xxx.xxx.xxx.30
1
root@ubuntu:/etc/fail2ban# fail2ban-client status test
Status for the jail: test
|- Filter
| |- Currently failed: 0
| |- Total failed: 5
| `- File list: /var/log/nginx/access.log
`- Actions
|- Currently banned: 0
|- Total banned: 1
`- Banned IP list:
root@ubuntu:/etc/fail2ban#
[fail2ban docs] https://fail2ban.readthedocs.io/en/latest/filters.html