fail2ban 설정하기
fail2ban?
GitHub - fail2ban/fail2ban: Daemon to ban hosts that cause multiple authentication errors
log파일을 참조하여 filter에 정의된 조건에 맞는 IP를 기록하고 차단하기 위한 brute force 방어 시스템이다.
jail 과 filter라는 개념을 사용하는데,
jail은 특정 필터에 의해 걸러진 IP를 가두는 감옥과 같은 개념으로,
감옥별로 차단 단계까지 도달하기 위해 반복될 실패횟수나 시간, 차단할 시간 등을 지정할 수 있다.
filter는 간단하게 IP 차단 여부를 판단하기 위한 기준이 되는 필터를 의미한다.
설치(ubuntu 기준)
$ apt-get update apt-get install fail2ban
설치를 완료하면 /etc/fail2ban 경로에 아래처럼 파일이 생성된다.
📁 /etc/fail2ban/
├── 📂 action.d/
├── 📂 fail2ban.d/ 필터 설정 파일 보관
├── 📂 filter.d/
├── 📂 jail.d/ jail 설정 파일 보관
├── 📄 backup.local
├── 📄 fail2ban.conf
├── 📄 jail.conf 기본 jail 설정 파일
├── 📄 paths-arch.conf
├── 📄 paths-common.conf
├── 📄 paths-debian.conf
├── 📄 paths-opensuse.conf
주의사항
jail.conf 파일은 fail2ban 버전 업데이트시 변경될 수 있기 때문에,
해당 파일을 직접 수정하지 않고 jail.local 등의 파일을 생성하여 수정하는 것을 강력하게 권장하고 있다.
jail.local 파일을 만들어 수정하면 해당 파일로 설정이 덮어써진다.
# WARNING: heavily refactored in 0.9.0 release. Please review and
# customize settings for your setup.
# Changes: in most of the cases you should not modify this
# file, but provide customizations in jail.local file,
# or separate .conf files under jail.d/ directory, e.g.:
# HOW TO ACTIVATE JAILS:
# YOU SHOULD NOT MODIFY THIS FILE.(fail2ban.conf)
# It will probably be overwritten or improved in a distribution update.
-> jail.conf에 있는 경고문
CONFIGURATION FILES FORMAT
*.conf files are distributed by Fail2Ban.
It is recommended that *.conf files should remain unchanged to ease upgrades.
If needed, customizations should be provided in *.local files.
In .local files specify only the settings you would like to change,
and the rest of the configuration will then come from the corresponding .conf file which is parsed first.
-> man 명령어를 통해 확인한 매뉴얼에 있는 내용
jail.conf 내에 지정된 [DEFAULT] 이하 설정은 말 그대로 기본 설정으로, 이후 이어질 jail 설정에 따라 override된다.
.local 파일 내에서 재정의된 설정 외 다른 설정은 앞서 파싱된 jail.conf의 설정이 적용된다.
아래는 fail2ban.conf 예시 파일
https://github.com/fail2ban/fail2ban/blob/master/config/fail2ban.conf
# Fail2Ban main configuration file
#
# Comments: use '#' for comment lines and ';' (following a space) for inline comments
#
# Changes: in most of the cases you should not modify this
# file, but provide customizations in fail2ban.local file, e.g.:
#
# [DEFAULT]
# loglevel = DEBUG
#
[DEFAULT]
# Option: loglevel
# Notes.: Set the log level output.
# CRITICAL
# ERROR
# WARNING
# NOTICE
# INFO
# DEBUG
# Values: [ LEVEL ] Default: INFO
#
loglevel = INFO
# Option: logtarget
# Notes.: Set the log target. This could be a file, SYSTEMD-JOURNAL, SYSLOG, STDERR or STDOUT.
# Only one log target can be specified.
# If you change logtarget from the default value and you are
# using logrotate -- also adjust or disable rotation in the
# corresponding configuration file
# (e.g. /etc/logrotate.d/fail2ban on Debian systems)
# Values: [ STDOUT | STDERR | SYSLOG | SYSOUT | SYSTEMD-JOURNAL | FILE ] Default: STDERR
#
logtarget = /var/log/fail2ban.log
# Option: syslogsocket
# Notes: Set the syslog socket file. Only used when logtarget is SYSLOG
# auto uses platform.system() to determine predefined paths
# Values: [ auto | FILE ] Default: auto
syslogsocket = auto
# Option: socket
# Notes.: Set the socket file. This is used to communicate with the daemon. Do
# not remove this file when Fail2ban runs. It will not be possible to
# communicate with the server afterwards.
# Values: [ FILE ] Default: /var/run/fail2ban/fail2ban.sock
#
socket = /var/run/fail2ban/fail2ban.sock
# Option: pidfile
# Notes.: Set the PID file. This is used to store the process ID of the
# fail2ban server.
# Values: [ FILE ] Default: /var/run/fail2ban/fail2ban.pid
#
pidfile = /var/run/fail2ban/fail2ban.pid
# Option: allowipv6
# Notes.: Allows IPv6 interface:
# Default: auto
# Values: [ auto yes (on, true, 1) no (off, false, 0) ] Default: auto
#allowipv6 = auto
# Options: dbfile
# Notes.: Set the file for the fail2ban persistent data to be stored.
# A value of ":memory:" means database is only stored in memory
# and data is lost when fail2ban is stopped.
# A value of "None" disables the database.
# Values: [ None :memory: FILE ] Default: /var/lib/fail2ban/fail2ban.sqlite3
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
# Options: dbpurgeage
# Notes.: Sets age at which bans should be purged from the database
# Values: [ SECONDS ] Default: 86400 (24hours)
dbpurgeage = 1d
# Options: dbmaxmatches
# Notes.: Number of matches stored in database per ticket (resolvable via
# tags <ipmatches>/<ipjailmatches> in actions)
# Values: [ INT ] Default: 10
dbmaxmatches = 10
[Definition]
[Thread]
# Options: stacksize
# Notes.: Specifies the stack size (in KiB) to be used for subsequently created threads,
# and must be 0 or a positive integer value of at least 32.
# Values: [ SIZE ] Default: 0 (use platform or configured default)
#stacksize = 0
매뉴얼 보기 명령어(참고)
$ man jail.conf man fail2ban
github보다 훨씬 자세한 매뉴얼을 열람할 수 있다. (fail2ban 설치 전에는 볼 수 없음)
실행
$ fail2ban-client start
Server ready 가 뜨면 정상적으로 실행되었다는 뜻
jail 설정 예시
jail.local 파일 내에 jail별로 설정할 수 있다.
jail명을 대괄호 내에 작성하고, 속성을 명시하면 된다.
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
backend = polling
[nginx-login-scan]
enabled = true
filter = nginx-login-scan
logpath = /var/log/nginx/access.log
maxretry = 30
findtime = 60
bantime = 600
backend = polling
# access.log를 감시하여 동일 IP로 1분 이내에 30번 이상의 로그인 요청이 발생하면 10분간 차단
대괄호 내에는 jail의 이름, filter와 동일할 필요는 없다.
기본 설정은 fail2ban.conf에 있는데다, 필요한 설정은 덮어씌워지기 때문에 필요한 설정만 남기고 다 지워도 상관없다.
- enabled: jail 활성화 (true | false)
- port: fail2ban으로 감시할 타겟 포트
- filter: 모니터링을 위한 filter.d 폴더 내 필터 이름
- logpath: 모니터링할 로그 파일 경로
- bantime: ip 차단할 시간(초) (-1인 경우 수동 해제 전까지 영구 차단)
- findtime: maxretry회 반복되는 데까지 걸리는 시간(초)
→ findtime초 동안 maxretry회 이상 filter에 해당하는 요청이 발생하면 차단된다. - maxretry: ip 차단 전까지 허용된 filter에 해당하는 요청 수
- backend: ip 차단 등 액션을 위한 백엔드 설정 (pyinotify | gamin | polling | systemd | auto )
→ 외부 라이브러리 없이 polling 알고리즘을 사용하는 polling을 제외하면 별도 라이브러리 설치가 필요하며,
auto의 경우 pyinotify, gamin, polling 순으로 시도한다.
filter 설정 예시
# nginx-login-scan.conf
[Definition]
failregex = .*<HOST>.*\/api\/login.* #/api/login 경로로 오는 요청을 감지한다.
ignoreregex =
filter 파일에는 감시 대상인 로그의 형식에 맞춘 regex로 어떤 걸 실패로 간주할 건지, 무시할 건지 지정한다.
ignoreregex는 지정하지 않으면 어떤 것도 무시하지 않는다.
설정에 따라 요청을 보내기만 해도 차단을 위한 실패요청으로 간주하거나 무시할 수 있다.
200요청은 무시하고 싶다면 무시할 수도 있는 것이다~
설정을 바꾸고 나서는 fail2ban을 재시작해 주어야 적용된다.
$ systemctl restart fail2ban
현재 실행 상태 확인
$ fail2ban-client status
Status
|- Number of jail: 4
`- Jail list: nginx-login-scan, sshd
현재 활성화된 jail 목록과 그 숫자가 나타난다.
수동 차단
$ fail2ban-client set <JAIL> banip <IP> ... <IP>
<JAIL> 에 <IP> 를 수동으로 차단 처리한다.
여러 IP를 지정하는 경우 공백(" ") 으로 구분한다.
차단된 IP 목록 확인
$ fail2ban-client banned
jail별로 차단된 IP 목록을 확인할 수 있다.
결과는 이런식으로 나온다.
[
{'sshd': []},
{'nginx-http-auth': []},
{'nginx-access-scan': []},
{'nginx-auth-scan': ['192.168.xx.xx']}
]
차단 해제
$ fail2ban-client unban 192.168.xx.xx # 특정 ip 해제
$ fail2ban-client unban --all # 전체해제
차단 테스트를 직접 내 맥북 환경에서 하다가 회사 와이파이 공인IP 자체가 차단되어
사내 모든 개발자가 해당 서버에 접근할 수 없게 차단당해버리는 민망한 실수도 했다. ^_^
사내 운영중인 다른 서버에서 ssh로 해당 서버로 연결해서 해제하는 방식으로 해결했다... 다행이다 빨리 해결책을 떠올려서...
'TIL > ETC' 카테고리의 다른 글
일렉트론 자동 업데이트 설정하기 (electron auto-updater) (0) | 2025.07.21 |
---|---|
VPN 해제 후 공인 IP 기반 서비스 오픈과 보안 구성 (0) | 2025.07.16 |
파이썬으로 Google SheetAPI 사용하기 (0) | 2025.06.23 |