概要
fail2ban をコンテナで動作させる方法を紹介します
よく紹介されているのはホストに直接インストールする方法かなと思います
今回は nginx の不正アクセスを ban する方法を紹介します
環境
- Ubuntu 24.04
- docker
- linuxserver/fail2ban 1.1.0-r2-ls26
- fail2ban 1.1.0
compose.yaml
fail2ban は linuxserver/fail2ban を使います
fail2ban は仕組み上 iptables を使うのでホストネットワークを使う必要があります
services:
nginx:
image: nginx:latest
container_name: nginx
network_mode: host
volumes:
- ./nginx/log:/var/log/nginx # このログをfail2banで監視
restart: unless-stopped
fail2ban:
image: linuxserver/fail2ban:latest
container_name: fail2ban
network_mode: host
cap_add:
- NET_ADMIN # BANに必須
- NET_RAW # BANに必須
volumes:
- ./config/jail.local:/config/fail2ban/jail.d/jail.local
- ./config/filter.d/nginx-404.conf:/config/fail2ban/filter.d/nginx-404.conf
- ./nginx/log:/remotelogs/nginx:ro # nginxログを読み取り専用で監視
environment:
- TZ=Asia/Tokyo
restart: unless-stopped
./config/jail.local
[DEFAULT]
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
# default ban time
bantime.increment = true
# "bantime.maxtime" is the max number of seconds using the ban time can reach (doesn't grow further)
bantime.maxtime = 5w
# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier
bantime.factor = 24
# "bantime" is the number of seconds that a host is banned.
bantime = 1h
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 24h
# "maxretry" is the number of failures before a host get banned.
maxretry = 5
# Prevents banning LAN subnets
ignoreip = 127.0.0.1/8 ::1
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
# The ban action "iptables-multiport" (default) should work for most
# The ban action "iptables-allports" can be used if multiport causes issues
banaction = iptables-multiport
banaction_allports = iptables-allports
# Read https://github.com/sebres/PoC/blob/master/FW.IDS-DROP-vs-REJECT/README.md before changing block type
# The block type "REJECT --reject-with icmp-port-unreachable" (default behavior) should respond to, but then instantly reject connection attempts
# The block type "DROP" should not respond to connection attempts, resulting in a timeout
#banaction = iptables-multiport[blocktype=DROP]
# Add additional actions
action = %(action_)s
apprise-api[host="127.0.0.1", tag="fail2ban"]
cloudflare[cfuser="YOUR-EMAIL", cftoken="YOUR-TOKEN"]
# [sshd]
# configuration inherits from jail.conf
# enabled = true
# chain = INPUT
# action = %(action_)s
[nginx-http-auth]
# configuration inherits from jail.conf
enabled = true
chain = DOCKER-USER
action = %(action_)s
[nginx-badbots]
# configuration inherits from jail.d/nginx-badbots.conf
enabled = true
chain = DOCKER-USER
action = %(action_)s
[nginx-botsearch]
# configuration inherits from jail.conf
enabled = true
chain = DOCKER-USER
action = %(action_)s
[nginx-deny]
# configuration inherits from jail.d/nginx-deny.conf
enabled = true
chain = DOCKER-USER
action = %(action_)s
[nginx-unauthorized]
# configuration inherits from jail.d/nginx-unauthorized.conf
enabled = true
chain = DOCKER-USER
action = %(action_)s
[nginx-404]
# Custom filter to detect excessive 404 errors
enabled = true
chain = INPUT
port = http,https
filter = nginx-404
logpath = /remotelogs/nginx/access.log
maxretry = 3
findtime = 10s
bantime = 1h
banaction などは適切なものを設定しましょう
ポイントは一番下の nginx-404 です
これで 404 を連発する IP を ban にできます
それ以外も nginx の ban ルールですが認証エラーなどで発生させるのが難しいので今回 404 を追加しています
config/filter.d/nginx-404.conf
# Fail2Ban filter to detect excessive 404 errors from nginx
# Detects clients making too many requests to non-existent pages
[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*" 404
ignoreregex =
datepattern = {^LN-BEG}%%d/%%b/%%ExY:%%H:%%M:%%S
nginx のログで 404 を正規表現でマッチさせます
起動
- docker compsoe up -d
動作確認
今回は10秒間に3回404発生でbanなのですぐにbanになります
localhost/test など存在しないページにアクセスしましょう
そして ban になっているか確認します
- docker compose exec fail2ban fail2ban-client status nginx-404
Status for the jail: nginx-404
|- Filter
| |- Currently failed: 0
| |- Total failed: 6
| `- File list: /remotelogs/nginx/access.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: xxx.xxx.xxx.xxx
ban されると i-Filter のお馴染みの画面が表示されるようになります
また iptables -L でホスト側を確認するとちゃんと REJECT ルールがあることが確認できると思います
sudo iptables -L f2b-nginx-404
Chain f2b-nginx-404 (1 references)
target prot opt source destination
REJECT all -- xxx.xxx.xxx.xxx anywhere reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere
ban解除
- docker compose exec fail2ban fail2ban-client set nginx-404 unbanip xxx.xxx.xxx.xxx
テストなどですぐに解除したい場合は IP を指定して ban 解除できます
iptables にもないことが確認できます
最後に
今回使った linuxserver/fail2ban は /config/fail2ban/filter.d に大量のプリセットがあるのでログをセットするだけでも簡単に ban 監視を開始することができます
今回は 404 ルールだけなかったので手動で追加しています
fail2ban は iptables を操作するツールなので iptables を使ってアクセス制御しているケースとは親和性は高い気がします
逆にクラウドなどのファイアウォールでアクセス制御している場合は fail2ban とは少し相性が悪いので使い分けが必要かなと思います
結局 iptables なのでホストにインストールしても変わりませんが docker compose でアプリを管理していたりホストにはなるべくアプリをインストールしたくないという場合にはやはり docker で fail2ban を動かしたくなるかなと思います
0 件のコメント:
コメントを投稿