Ubuntu

Ubuntu20.04 fail2ban

やり方は Qiita / fail2banの使い方 に書いてあり、改めて書くようなこともない。ウチの環境にどう適用したのかを残すメモ…と思ったけれど、案外やれることが多かった。



広告


Ubuntu 20.04と書いているけれども、Ubuntu 18.04のシステムもあり、同じような設定を入れていく。
差異が見つかれば書くつもりだったが、そんなに大きなものはないと思う。

注意事項

具体的な結果を見ると納得感が出てくると思うので、IPアドレスはそのまま書いている。
この記事を書いている時点で「そうした動作」をしていたのであって、過去は分からないし、未来にどうなるのかも分からない。
サンプルとして捉えること。

どんなものなのか

インストール

インストールはaptで。whoisも一緒にインストールされるらしい。
Banをメールでレポートする機能があって、そこではwhoisが実行される模様。

$ sudo apt install fail2ban
$ fail2ban-server --version
Fail2Ban v0.11.1
$ sudo systemctl status fail2ban.service
 fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2021-11-21 05:09:37 JST; 2min 52s ago
       Docs: man:fail2ban(1)
   Main PID: 330069 (f2b/server)
      Tasks: 5 (limit: 1070)
     Memory: 14.1M
     CGroup: /system.slice/fail2ban.service
             mq330069 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

※Ubuntu 18.04では、v0.10.2がインストールされる。

インストールしただけでsshdの保護が始まり、バシバシとログが出てきたりする。

/var/log/fail2ban.log ※Ubuntu 20.04

2021-11-21 05:09:37,594 fail2ban.server         [330069]: INFO    --------------------------------------------------
2021-11-21 05:09:37,594 fail2ban.server         [330069]: INFO    Starting Fail2ban v0.11.1
2021-11-21 05:09:37,597 fail2ban.observer       [330069]: INFO    Observer start...
2021-11-21 05:09:37,628 fail2ban.database       [330069]: INFO    Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
2021-11-21 05:09:37,641 fail2ban.database       [330069]: WARNING New database created. Version '4'
2021-11-21 05:09:37,641 fail2ban.jail           [330069]: INFO    Creating new jail 'sshd'
2021-11-21 05:09:37,764 fail2ban.jail           [330069]: INFO    Jail 'sshd' uses pyinotify {}
2021-11-21 05:09:37,772 fail2ban.jail           [330069]: INFO    Initiated 'pyinotify' backend
2021-11-21 05:09:37,779 fail2ban.filter         [330069]: INFO      maxLines: 1
2021-11-21 05:09:37,828 fail2ban.filter         [330069]: INFO      maxRetry: 5
2021-11-21 05:09:37,828 fail2ban.filter         [330069]: INFO      findtime: 600
2021-11-21 05:09:37,828 fail2ban.actions        [330069]: INFO      banTime: 600
2021-11-21 05:09:37,828 fail2ban.filter         [330069]: INFO      encoding: UTF-8
2021-11-21 05:09:37,829 fail2ban.filter         [330069]: INFO    Added logfile: '/var/log/auth.log' (pos = 0, hash = ****)
2021-11-21 05:09:37,842 fail2ban.jail           [330069]: INFO    Jail 'sshd' started
…
2021-11-21 05:09:41,819 fail2ban.filter         [330069]: INFO    [sshd] Found 221.131.165.65 - 2021-11-21 05:08:46
2021-11-21 05:09:41,820 fail2ban.filter         [330069]: INFO    [sshd] Found 221.131.165.65 - 2021-11-21 05:08:55
2021-11-21 05:09:41,821 fail2ban.filter         [330069]: INFO    [sshd] Found 159.89.16.144 - 2021-11-21 05:09:10
2021-11-21 05:09:41,821 fail2ban.filter         [330069]: INFO    [sshd] Found 159.89.16.144 - 2021-11-21 05:09:11
2021-11-21 05:09:41,851 fail2ban.actions        [330069]: NOTICE  [sshd] Ban 159.89.16.144
2021-11-21 05:09:41,935 fail2ban.actions        [330069]: NOTICE  [sshd] Ban 221.131.165.65

/var/log/fail2ban.log ※Ubuntu 18.04

2021-11-21 05:11:43,785 fail2ban.server         [22924]: INFO    --------------------------------------------------
2021-11-21 05:11:43,785 fail2ban.server         [22924]: INFO    Starting Fail2ban v0.10.2
2021-11-21 05:11:43,957 fail2ban.database       [22924]: INFO    Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
2021-11-21 05:11:43,961 fail2ban.database       [22924]: WARNING New database created. Version '2'
2021-11-21 05:11:43,962 fail2ban.jail           [22924]: INFO    Creating new jail 'sshd'
2021-11-21 05:11:44,120 fail2ban.jail           [22924]: INFO    Jail 'sshd' uses pyinotify {}
2021-11-21 05:11:44,129 fail2ban.jail           [22924]: INFO    Initiated 'pyinotify' backend
2021-11-21 05:11:44,131 fail2ban.filter         [22924]: INFO      maxLines: 1
2021-11-21 05:11:44,178 fail2ban.server         [22924]: INFO    Jail sshd is not a JournalFilter instance
2021-11-21 05:11:44,179 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/auth.log' (pos = 0, hash = ****)
2021-11-21 05:11:44,238 fail2ban.filter         [22924]: INFO      encoding: UTF-8
2021-11-21 05:11:44,239 fail2ban.filter         [22924]: INFO      maxRetry: 5
2021-11-21 05:11:44,239 fail2ban.filter         [22924]: INFO      findtime: 600
2021-11-21 05:11:44,239 fail2ban.actions        [22924]: INFO      banTime: 600
2021-11-21 05:11:44,242 fail2ban.jail           [22924]: INFO    Jail 'sshd' started

初期設定

sshdが有効になっているのは、このファイルがあるからの模様。
/etc/fail2ban/jail.d/defaults-debian.conf

[sshd]
enabled = true

Banの動作はこの指定によって行われているようだ。
/etc/fail2ban/jail.conf

…
[DEFAULT]
…
# "bantime" is the number of seconds that a host is banned.
# "bantime"は、ホストが禁止される秒数のことです。
bantime  = 10m

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
# 最後の "findtime "秒の間に "maxretry "を発生させたホストは禁止されます。
findtime  = 10m

# "maxretry" is the number of failures before a host get banned.
# "maxretry "は、ホストが禁止されるまでの失敗回数です。
maxretry = 5
…
# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
…
# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
…

[sshd]

# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode   = normal
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
…

※翻訳はDeepLによるもの。

Ban

早速、sshdでBanと表示がされたので、Banとはどういう状態なのかを確認したい。

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     96
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 1
   |- Total banned:     8
   `- Banned IP list:   221.131.165.65

でも、ufwで状態を確認しても、状態が変わっているわけではなかった。なので、iptablesでルールを確認。

$ sudo iptables -t filter --list-rules
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N f2b-sshd
-N ufw-after-forward
-N ufw-after-input
…
-A f2b-sshd -s 221.181.185.159/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -s 221.181.185.94/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN
…

すべてのフィルターより先に、このIPからのすべてのアクセスを拒否している(REJECTなので拒否していることは相手に伝わる)。

Banの解除

BanされたIPアドレスを解除するには、以下のコマンドを使う。

$ sudo fail2ban-client set sshd unbanip 221.181.185.94

マニュアルでは、sshdの部分が JAIL と表現されていて、ログを見ると sshd という牢獄が作られている訳なので、それを指定している。

状態確認

この先でJailを追加していくのだが、それぞれがどうなっているのかを確認するのは意外と面倒。
Github / kamermans / fail2ban-allstatus.sh

こちらで提供してくれているシェル(短いので、コピペでファイルを作った)を実行したら、サクッとすべての情報が見られる。

$ sudo ./fail2ban-allstatus.sh

履歴確認

どんなIPアドレスをBanしてきたのか、というところの履歴は以下で取得できる。
serverfault / How to show all banned IP with fail2ban?

$ zgrep 'Ban' /var/log/fail2ban.log*

zgrepというのは圧縮されている可能性があるものも含めてgrepしてくれるコマンドのようで、ありったけのリストを出してくれる。

設定

大まかに考え方が分かったところで、設定をしていく。
設定は /etc/fail2ban/jail.confではなく、差分だけを/etc/fail2ban/jail.dにつくるファイルで定義していく模様。

sshd

初期設定の活用

思うに、何度かトライさせる必要なんてないのかな、一発でBANでいいんじゃないかと思ったりしている。
ウチで管理しているサーバーにアクセスするのは関係者だけだし。

/etc/fail2ban/jail.d/sshd.local ※新規作成

[sshd]
enabled = true
bantime = 10m
findtime = 10m
maxretry = 1

※BANする時間はもっと長くてもいいのかなとも思うけれど、まぁ、とりあえずはこれで。

設定を反映してみる。

$ sudo systemctl reload fail2ban

/var/log/fail2ban.log

…
2021-11-21 09:29:13,988 fail2ban.server         [330069]: INFO    Reload all jails
2021-11-21 09:29:13,989 fail2ban.server         [330069]: INFO    Reload jail 'sshd'
2021-11-21 09:29:13,990 fail2ban.filter         [330069]: INFO      maxLines: 1
2021-11-21 09:29:13,991 fail2ban.filter         [330069]: INFO      maxRetry: 1
2021-11-21 09:29:13,992 fail2ban.filter         [330069]: INFO      findtime: 600
2021-11-21 09:29:13,992 fail2ban.actions        [330069]: INFO      banTime: 600
2021-11-21 09:29:13,992 fail2ban.filter         [330069]: INFO      encoding: UTF-8
2021-11-21 09:29:13,993 fail2ban.server         [330069]: INFO    Jail 'sshd' reloaded
2021-11-21 09:29:13,993 fail2ban.server         [330069]: INFO    Reload finished.
2021-11-21 09:29:14,781 fail2ban.actions        [330069]: NOTICE  [sshd] Ban 159.89.2.74
2021-11-21 09:29:23,616 fail2ban.filter         [330069]: INFO    [sshd] Found 222.187.238.58 - 2021-11-21 09:29:23
2021-11-21 09:29:24,009 fail2ban.actions        [330069]: NOTICE  [sshd] Ban 222.187.238.58

一発でBANとなっている。

Apache

プリセットの活用

Webサーバーへの攻撃をどう見るのかよく分からないけれど…/etc/fail2ban/filter.dにapache-*というファイルが幾つか入っている。
また、この定義が /etc/fail2ban/jail.confに書かれている。

ファイルファイルの中にある説明
apache-common.conf他のApacheフィルタでの汎用設定項目(補間として使用される)。
※実際に、他のファイルからincludeされている。
apache-auth.conf※Apacheで認証をしている場合に定義すれば使えそう。
apache-badbots.conf既知のスパムボットやソフトウェアを同様に捕捉するための正規表現。上記のボットによって動かされたIPをブロックする意図があることを確認してください。
apache-botsearch.confこのフィルターは、存在しない特定のURLをブロックすることを目的としています。これは、robots.txtのDisallow:ディレクティブで指定された一連のURLであったり、ボットが悪用可能なコンテンツを探している原因となっている存在しないウェブサービスであったりします。このフィルタは、誤検知率が低くなるように設計されています。
これに代わるものとして、存在しないすべての種類のスクリプトをブロックする apache-noscript フィルタがあります。
これは通常、隠されていたり、実際にはインストールされていない、悪用可能な、または価値のあるウェブサービスの事前定義されたリストです。
apache-fakegooglebot.conf偽Googleボットのユーザーエージェントフィルタ。
※.Googlebot. という文字が含まれる行を見つけると作動する模様。
apache-modsecurity.confApache modsec フィルタ。
※ModSecurity: Access denied with code 4xx あるいは 5xx という行を見つけると作動する模様。
apache-nohome.confサーバー上のホームディレクトリの検索に失敗した場合にマッチさせるための正規表現で、最近人気があります。ほとんどの場合、攻撃者はドメイン名の代わりに IP を使用しているので、ドメインごとのログファイルがある場合には、一般的な error.log で見ることができます。
apache-noscript.confこれにより、存在しない多くの種類のスクリプトにマッチします。ウィキやフォーラムのように、ウェブサイトとは無関係のユーザーが存在しないファイルやスクリプトへのリンクをページに挿入し、悪意のないサイトのブラウザがこのフィルターに反応してしまうようなケースでは、多くの誤判定が発生する可能性があります。
存在しない特定の URL にマッチさせたい場合は、 apache-botsearch フィルタを参照してください。
apache-overflows.con長い、または、不審な性質のWebリクエストをブロックする。
apache-pass.confこのフィルターは、access.log用で、error.log用ではない。
ノックされたリクエストには、リファラーが必要です。
apache-shellshock.confシェルショックを悪用したカスタムヘッダを含むWebリクエストをブロックする。
説明はDeepLにて翻訳

この中から、利用するフィルターを選んで設定する。例えば、こんな感じで。
/etc/fail2ban/jail.d/apache.local ※新規作成

[apache-auth]
enabled = false

[apache-badbots]
enabled = false

[apache-noscript]
enabled = false

[apache-overflows]
enabled = true

[apache-nohome]
enabled = false

[apache-botsearch]
enabled = false

[apache-fakegooglebot]
enabled = false

[apache-modsecurity]
enabled = false

[apache-shellshock]
enabled = false

テストとしてoverflowをオンにして、設定を反映してみる。

$ sudo systemctl reload fail2ban

/var/log/fail2ban.log

…
2021-11-21 15:15:56,092 fail2ban.jail           [22924]: INFO    Creating new jail 'apache-overflows'
2021-11-21 15:15:56,092 fail2ban.jail           [22924]: INFO    Jail 'apache-overflows' uses pyinotify {}
2021-11-21 15:15:56,097 fail2ban.jail           [22924]: INFO    Initiated 'pyinotify' backend
2021-11-21 15:15:56,100 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/apache2/hogehoge-error.log' (pos = 0, hash = ****)
2021-11-21 15:15:56,102 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/apache2/hagehage-error.log' (pos = 0, hash = ****)
2021-11-21 15:15:56,102 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/apache2/pakapaka-error.log' (pos = 0, hash = ****)
2021-11-21 15:15:56,103 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/apache2/rerorero-error.log' (pos = 0, hash = ****)
2021-11-21 15:15:56,104 fail2ban.filter         [22924]: INFO      encoding: UTF-8
2021-11-21 15:15:56,104 fail2ban.filter         [22924]: INFO      maxRetry: 2
2021-11-21 15:15:56,104 fail2ban.filter         [22924]: INFO      findtime: 600
2021-11-21 15:15:56,104 fail2ban.actions        [22924]: INFO      banTime: 600

エラーログを見つけて、監視対象にしているのが確認できたので、必要と思う監視を有効にする。

Postfix

プリセットをモード変更して活用

これも、まぁまぁな勢いでノックされていて、それが全然関係のないところからだったりしていて厄介。
/etc/fail2ban/filter.d/postfix.conf を確認すると、アグレッシブモードにしないと、いまの攻撃を回避できそうもない感じ。

/etc/fail2ban/jail.d/postfix.local ※新規作成

[postfix]
enabled = true
mode = aggressive

設定を反映。

$ sudo systemctl reload fail2ban

/var/log/fail2ban.log

…
2021-11-21 21:13:59,956 fail2ban.server         [22924]: INFO    Reload all jails
2021-11-21 21:13:59,964 fail2ban.jail           [22924]: INFO    Creating new jail 'postfix'
2021-11-21 21:13:59,965 fail2ban.jail           [22924]: INFO    Jail 'postfix' uses pyinotify {}
2021-11-21 21:13:59,969 fail2ban.jail           [22924]: INFO    Initiated 'pyinotify' backend
2021-11-21 21:13:59,981 fail2ban.server         [22924]: INFO    Jail postfix is not a JournalFilter instance
2021-11-21 21:13:59,981 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/mail.log' (pos = 0, hash = ****)
2021-11-21 21:13:59,983 fail2ban.filter         [22924]: INFO      encoding: UTF-8
2021-11-21 21:13:59,983 fail2ban.filter         [22924]: INFO      maxRetry: 5
2021-11-21 21:13:59,983 fail2ban.filter         [22924]: INFO      findtime: 600
2021-11-21 21:13:59,983 fail2ban.actions        [22924]: INFO      banTime: 600
2021-11-21 21:13:59,986 fail2ban.jail           [22924]: INFO    Jail 'postfix' started

実際にaggressiveになっているのかよく分からないけれど、とりあえずこれで様子見。

ポートスキャン

新規作成する設定

ufw.logをみると、まースゴい量のスキャンがされているわけだけれども、これを使ったBanができないものか。
ポートスキャンといっても、何をそれと判定するか、という話があるにはあるけれど…。

たとえば、こんなログが出ている。
ufw.log

Nov 21 00:00:41 router kernel: [2773313.371997] [UFW BLOCK] IN=ppp0 OUT= MAC= SRC=46.101.60.54 DST=nnn.nnn.nnn.nnn LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=5446 PROTO=TCP SPT=58030 DPT=2294 WINDOW=1024 RES=0x00 SYN URGP=0
Nov 21 00:00:43 router kernel: [2773315.631504] [UFW BLOCK] IN=ppp0 OUT= MAC= SRC=89.248.165.60 DST=nnn.nnn.nnn.nnn LEN=40 TOS=0x00 PREC=0x00 TTL=241 ID=54321 PROTO=TCP SPT=41004 DPT=22224 WINDOW=65535 RES=0x00 SYN URGP=0

これには用意されたものはなくて、手作りする必要があるらしい。
serverfault / Trouble with Fail2Ban UFW Portscan Filter

/etc/fail2ban/jail.d/ufw.local ※新規作成

[ufw-port-scan]
enabled = true
filter = ufw-port-scan
logpath = /var/log/ufw.log
maxlines = 1
bantime = 1h
findtime = 10m
maxretry = 3

※元記事ではufwを使ってブロックしているようだったけれども、sshd同様にiptablesでブロックしようと考えた。

フィルターとして、こんなものを用意。
/etc/fail2ban/filter.d/ufw-port-scan.conf ※新規作成

[Definition]
failregex = .*\[UFW BLOCK\].* SRC=<HOST>
ignoreregex =

設定を反映。

$ sudo systemctl reload fail2ban

/var/log/fail2ban.log

…
2021-11-21 16:12:45,695 fail2ban.jail           [330069]: INFO    Creating new jail 'ufw-port-scan'
2021-11-21 16:12:45,695 fail2ban.jail           [330069]: INFO    Jail 'ufw-port-scan' uses pyinotify {}
2021-11-21 16:12:45,723 fail2ban.jail           [330069]: INFO    Initiated 'pyinotify' backend
2021-11-21 16:12:45,726 fail2ban.filter         [330069]: INFO      maxLines: 1
2021-11-21 16:12:45,726 fail2ban.filter         [330069]: INFO      maxRetry: 3
2021-11-21 16:12:45,726 fail2ban.filter         [330069]: INFO      findtime: 600
2021-11-21 16:12:45,726 fail2ban.actions        [330069]: INFO      banTime: 3600
2021-11-21 16:12:45,726 fail2ban.filter         [330069]: INFO      encoding: UTF-8
2021-11-21 16:12:45,727 fail2ban.filter         [330069]: INFO    Added logfile: '/var/log/ufw.log' (pos = 0, hash = ****)
2021-11-21 16:12:45,731 fail2ban.jail           [330069]: INFO    Jail 'ufw-port-scan' started

実際には、ポートスキャンはかなりゆっくりと実行されるらしいので、もっと長いスパンで設定しても良いかと思う。
この後、少しパラメーターをいじってみて、BanされたIPを確認してみた。

$ sudo fail2ban-client status ufw-port-scan
Status for the jail: ufw-port-scan
|- Filter
|  |- Currently failed: 6
|  |- Total failed:     7
|  `- File list:        /var/log/ufw.log
`- Actions
   |- Currently banned: 5
   |- Total banned:     5
   `- Banned IP list:   185.156.73.63 45.155.205.131 45.155.205.93 5.252.195.34 92.63.197.94

また、ローカルからIPv6でブロックさせてみたが、検知してBanされた。
しばらく運用してみて、何か設定に変更が必要になったら、記事を更新する。

再犯への対応

プリセットの活用

現実には、一度Banしても、Unbanすると、再度攻撃してくるのが実態。

こうした接続への対応に、recidiveという設定がある模様。
/etc/fail2ban/jail.conf

…
# Jail for more extended banning of persistent abusers
# !!! WARNINGS !!!
# 1. Make sure that your loglevel specified in fail2ban.conf/.local
#    is not at DEBUG level -- which might then cause fail2ban to fall into
#    an infinite loop constantly feeding itself with non-informative lines
# 2. Increase dbpurgeage defined in fail2ban.conf to e.g. 648000 (7.5 days)
#    to maintain entries for failed logins for sufficient amount of time
# 執拗な悪用者への禁止措置を強化するための刑務所
# !!! 注意事項 !!!
# 1. fail2ban.conf/.localで指定するlogoglevelがDEBUGレベルではないことを確認してください。
# 2. fail2ban.confで定義されているdbpurgeageを648000(7.5日)などに増やし、
#    失敗したログインのエントリを十分な時間維持する。
[recidive]

logpath  = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime  = 1w
findtime = 1d
…

※翻訳はDeepLによるもの。

これに、デフォルト値の maxretry = 5 が適用されるので、1日5回Banしたら、1週間Banする、という動作になる見込み。

/etc/fail2ban/fail2ban.conf

# Options: dbpurgeage
# Notes.: Sets age at which bans should be purged from the database
# Values: [ SECONDS ] Default: 86400 (24hours)
#dbpurgeage = 1d
dbpurgeage = 8d

/etc/fail2ban/jail.d/recidive.local ※新規作成

[recidive]
enabled = true

設定を反映。

$ sudo systemctl reload fail2ban

/var/log/fail2ban.log

…
2021-11-21 21:30:53,750 fail2ban.jail           [22924]: INFO    Creating new jail 'recidive'
2021-11-21 21:30:53,750 fail2ban.jail           [22924]: INFO    Jail 'recidive' uses pyinotify {}
2021-11-21 21:30:53,755 fail2ban.jail           [22924]: INFO    Initiated 'pyinotify' backend
2021-11-21 21:30:53,759 fail2ban.server         [22924]: INFO    Jail recidive is not a JournalFilter instance
2021-11-21 21:30:53,760 fail2ban.filter         [22924]: INFO    Added logfile: '/var/log/fail2ban.log' (pos = 0, hash = ****)
2021-11-21 21:30:53,761 fail2ban.filter         [22924]: INFO      encoding: UTF-8
2021-11-21 21:30:53,762 fail2ban.filter         [22924]: INFO      maxRetry: 5
2021-11-21 21:30:53,762 fail2ban.filter         [22924]: INFO      findtime: 86400
2021-11-21 21:30:53,762 fail2ban.actions        [22924]: INFO      banTime: 604800
2021-11-21 21:30:53,770 fail2ban.jail           [22924]: INFO    Jail 'recidive' started
2021-11-21 21:30:53,772 fail2ban.server         [22924]: INFO    Reload finished.

心配なのは、dbpurgeageがどんな値になっているのか、ということ。

$ sudo fail2ban-client get dbpurgeage
Current database purge age is:
`- 691200seconds

設定できている。

で、実際にどんな感じになっているかというと…
/var/log/fail2ban.log

2021-11-21 22:08:14,363 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 159.89.16.144
2021-11-21 22:08:14,392 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 221.131.165.65
2021-11-21 22:08:14,410 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 221.181.185.94
2021-11-21 22:08:14,429 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 222.186.42.13
2021-11-21 22:08:14,448 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 222.187.238.58
2021-11-21 22:08:14,467 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 221.181.185.159
2021-11-21 22:08:14,485 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 221.131.165.62
2021-11-21 22:08:14,505 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 221.131.165.50
2021-11-21 22:08:14,522 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 164.90.179.137
2021-11-21 22:08:14,542 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 159.89.2.74
2021-11-21 22:08:14,562 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 222.186.42.137
2021-11-21 22:08:14,586 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 176.111.173.238
2021-11-21 22:08:14,605 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 176.111.173.237
2021-11-21 22:08:14,625 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 68.183.221.184
2021-11-21 22:08:14,644 fail2ban.actions        [337596]: NOTICE  [recidive] Ban 165.22.80.128

という具合で、これだけのIPがBanとなった。

Apacheその2

新規作成するアグレッシブな設定

エラーログを見ていると、何しに来ているのかなー?と不思議になるようなアクセスが幾つか見つかる。

これをベースに牢獄を作るが、これはあくまでもウチの場合に使えそうというもの。
使っているシステムと出力されるログを確認して、適用して良いのかどうかを判断していく。

また、書きながら思っているのは

  • こうやって手口と対策を書くと、それ以外の方法で攻撃を始めるのだろう。
    • 分かっていれば避けられる。
    • そうでなくても、新しい手口が出てくれば、それを使った攻撃をされるだろう。
  • このエラーをわざと出させてBanさせることで、アクセス妨害をする、という考え方もあるかもしれない。
    • 何らかの組織で出口が1つのIPアドレスだったりすれば、その配下の人達は全滅。
    • v6プラスみたいなサービスだと、知らない誰かを巻き添えにして全滅。

ということだった。なので、アクセスログやエラーログの分析はずっとしていくべきだし、あえてBanしないでアクセスさせるという考え方もあると思われる。

kerbynet

/var/log/error.log

[Mon Nov 22 12:43:22.745282 2021] [cgi:error] [pid 9067] [client 203.248.175.71:25819] AH02811: script not found or unable to stat: /usr/lib/cgi-bin/kerbynet

kerbynetというのを調べてみると、Zeroshellというルーター・ファイアウォールを実装するLinuxディストリビューションがあって、それは2021年9月にEOLを迎えているが、過去そこに脆弱性があったようだ。

wp-login.php

/var/log/error.log

[Mon Nov 22 13:15:47.493805 2021] [authz_core:error] [pid 9280] [client 45.134.225.229:51599] AH01630: client denied by server configuration: /var/www/html/wp-login.php

wp-login.phpというのは、Wordpressのログイン処理のヤツ。リンクを用意していないし、これにアクセスする必要があるのは自分だけ(他にライターはいない)。

xmlrpc.php

/var/log/error.log

[Tue Nov 23 14:14:46.121883 2021] [authz_core:error] [pid 26323] [client 47.114.4.136:51446] AH01630: client denied by server configuration: /var/www/html/xmlrpc.php

xmlrpc.phpというのは、Wordpressで外部からコンテンツをいじったりできる機能を提供しているらしく、脆弱性云々と書かれている。
とはいえ、そもそも外から実行できないように設定がされていたので、ウチでは機能しないことが分かっている。

AWSからもアクセスがあったりするので、Banして良いものか迷ったのだけれど、ニュージーランドの歯医者さんだと分かって、あぁ、そういうことかと。
それ以外のアクセスも、まず、ウチの記事にアクセスしに来ているとは思えない

internal redirects

/var/log/error.log

[Mon Nov 22 15:45:13.621501 2021] [core:error] [pid 10070] [client 104.198.89.53:1233] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

このIPアドレスからのアクセスは、こんなのだった。ログのフォーマットは…/etc/apache2/apache2.confにある、これ。
LogFormat “%h %l %u %t \”%r\” %>s %O \”%{Referer}i\” \”%{User-Agent}i\”” combined

書式は公式をみるとして…

/var/log/access.log

104.198.89.53 - - [22/Nov/2021:10:19:34 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:10:19:35 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:10:19:36 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:10:19:36 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:11:23:05 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:11:23:05 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:11:23:14 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Edg/95.0.1020.53"
104.198.89.53 - - [22/Nov/2021:12:02:50 +0900] "GET / HTTP/1.1" 200 492292 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0"
104.198.89.53 - - [22/Nov/2021:14:13:17 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:14:13:17 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:14:42:37 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:14:44:18 +0900] "GET / HTTP/1.1" 200 492292 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:23:17 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:23:30 +0900] "GET /rohhie.net:443 HTTP/1.1" 404 466874 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
104.198.89.53 - - [22/Nov/2021:15:45:02 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:45:03 +0900] "GET /rohhie.net/zabbix4-0lts-add-printer-as-a-monitoring-target HTTP/1.1" 301 5305 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:45:03 +0900] "GET /zabbix4-0lts-add-printer-as-a-monitoring-target/ HTTP/1.1" 200 513261 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:45:13 +0900] "GET /rohhie.net/wp-admin/admin-ajax.php HTTP/1.1" 500 5531 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:45:13 +0900] "GET /rohhie.net/cocoon-manifest.json HTTP/1.1" 404 466747 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:15:45:13 +0900] "GET /rohhie.net HTTP/1.1" 404 466747 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:16:34:50 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:16:34:52 +0900] "GET /rohhie.net/esxi-upgrading-esxi-from-65-to-70 HTTP/1.1" 301 5291 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:16:34:52 +0900] "GET /esxi-upgrading-esxi-from-65-to-70/ HTTP/1.1" 200 554728 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:16:34:53 +0900] "GET / HTTP/1.1" 200 492293 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
104.198.89.53 - - [22/Nov/2021:18:02:08 +0900] "GET / HTTP/1.1" 200 491887 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"

特徴をみてみると、こんな感じ。

  • 戻しているデーターが多い(492293バイト)、普通より断然多い、なんでかなぁ。
  • IEからのアクセスと書かれているけれど、NT 6.1(Windows 7/Windows Server 2008 R2)か…NT 10.0だと、/rohhie.net:443というリクエストは残らない。何か特別なことをしているのだろう。
  • 最後に/がないと、一旦301を戻し、最後に/がついたURLにリダイレクトされるのは、まぁ正常動作。だけど、admin-ajax.phpのところが普通ではなく、結果としてInternal Errorが発生している。
  • そもそも、こんなパーマリンクをどうやって見つけたんだろう?

同じエラーが発生したパターンとして…

/var/log/error.log

[Mon Nov 22 20:31:31.459828 2021] [core:error] [pid 12850] [client 185.12.15.132:57390] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace., referer: rohhie.net

/var/log/access.log

185.12.15.132 - - [22/Nov/2021:20:31:31 +0900] "GET /wp-includes/js/tinymce/plugins/lists/lists/index.php?ARRAY=5o3939313633373430323231302p22687474703n5p2s5p2s7777772r73686s7061747n6s652r636s6q5p2s6s70616p656634305p2s7374796p652r637373225q HTTP/1.1" 500 5443 "rohhie.net" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36"

結構的確にディレクトリを探りに来ていて、このindex.phpにながーいパラメーターを渡して何かをしようとしているのか。
そもそもこんなファイルにアクセスしにくるのは1日1回とか、そんなもの。これも、良いアクセスではなさそう。

/bin/sh

なんかちょっと危ない感じのログが出ている。
/cgi-bin/../../../../bin/sh とか、CGIを設置している場所によるとは思うけれども、ミートする場合があるんじゃないだろうか。

/var/log/error.log

[Mon Nov 22 15:59:06.241391 2021] [core:error] [pid 10242] [client 45.146.164.110:50236] AH00126: Invalid URI in request POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1

この攻撃は、443番ポートではなく、80番ポートに行われていて、こちらで400を返している。
/var/log/other_vhosts_access.log

rohhie.net:80 45.146.164.110 - - [22/Nov/2021:15:59:06 +0900] "POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1" 400 399 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"

※今更気付いたのだけれど、ポート80番の側は、ログ出力の指定をしていなかったー。だからother vhosts扱いになっている。直しておこう。

/var/log/access.log

45.146.164.110 - - [22/Nov/2021:12:15:18 +0900] "GET / HTTP/1.1" 200 74807 "http://rohhie.net/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
45.146.164.110 - - [22/Nov/2021:12:49:15 +0900] "GET / HTTP/1.1" 200 74806 "http://rohhie.net/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
45.146.164.110 - - [22/Nov/2021:13:21:34 +0900] "GET / HTTP/1.1" 200 74808 "http://rohhie.net/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"

※エラーが発生した時間のアクセスログはなかった。

どうも、これは最近発表されたものらしく、任意のコマンドを実行できる脆弱性を突こうとしている模様。
Internal Errorは起きていないので、どうにか守られているように思うけれども、ちょっと。

ちなみに、zgrepでApacheのログを確認してみたところ、425行のログが出てきた。
どうにも普通のアクセスをしに来ているようには見えない。

これらのアクセスをBan

どれも、普通にアクセスしてくれている場合には出力されないログばかり。
何かの調査なのかもしれないが、うちにとって友好的なアクセスには見えないので、一発でBanする。

/etc/fail2ban/filter.d/apache-origin.conf ※新規作成

[INCLUDES]

before = apache-common.conf

[Definition]

failregex = ^%(_apache_error_client)s AH02811: script not found or unable to stat:.*$
            ^%(_apache_error_client)s AH01630: client denied by server configuration:.*$
            ^%(_apache_error_client)s AH00124: Request exceeded the limit of 10 internal redirects.*$
            ^%(_apache_error_client)s AH00126: Invalid URI in request.*$

ignoreregex =

作ったファイルターをテストする。
パラメーターの最初はテスト対象のログファイルを、最後にフィルターファイルを指定している。

$ fail2ban-regex -v /var/log/apache2/error.log.1 /etc/fail2ban/filter.d/apache-origin.conf
Running tests
=============

Use   failregex filter file : apache-origin, basedir: /etc/fail2ban
Use      datepattern : Default Detectors
Use         log file : /var/log/apache2/error.log.1
Use         encoding : UTF-8


Results
=======

Failregex: 29 total
|-  #) [# of hits] regular expression
|   1) [8] ^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\] AH02811: script not found or unable to stat:.*$
|      203.248.175.71  Mon Nov 22 12:43:22 2021
|      203.248.175.71  Mon Nov 22 12:43:22 2021
|      203.248.175.71  Mon Nov 22 12:43:23 2021
|      203.248.175.71  Mon Nov 22 12:43:23 2021
|      203.248.175.71  Mon Nov 22 13:50:46 2021
|      203.248.175.71  Mon Nov 22 13:50:49 2021
|      203.248.175.71  Tue Nov 23 05:15:52 2021
|      203.248.175.71  Tue Nov 23 05:15:53 2021
|   2) [18] ^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\] AH01630: client denied by server configuration:.*$
|      78.38.123.110  Mon Nov 22 06:52:00 2021
|      45.134.225.229  Mon Nov 22 13:15:47 2021
|      45.134.225.229  Mon Nov 22 13:15:48 2021
|      216.250.254.221  Mon Nov 22 15:03:50 2021
|      216.250.254.221  Mon Nov 22 15:03:50 2021
|      45.134.225.229  Mon Nov 22 20:37:23 2021
|      45.134.225.229  Mon Nov 22 20:37:23 2021
|      79.124.8.3  Mon Nov 22 22:51:51 2021
|      79.124.8.3  Mon Nov 22 22:51:52 2021
|      124.79.123.237  Tue Nov 23 00:52:17 2021
|      193.142.146.138  Tue Nov 23 01:50:12 2021
|      193.142.146.138  Tue Nov 23 01:50:13 2021
|      79.124.8.3  Tue Nov 23 03:35:49 2021
|      79.124.8.3  Tue Nov 23 03:35:49 2021
|      193.142.146.138  Tue Nov 23 05:02:01 2021
|      193.142.146.138  Tue Nov 23 05:02:02 2021
|      79.124.8.3  Tue Nov 23 05:15:40 2021
|      79.124.8.3  Tue Nov 23 05:15:41 2021
|   3) [2] ^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\] AH00124: Request exceeded the limit of 10 internal redirects.*$
|      104.198.89.53  Mon Nov 22 15:45:13 2021
|      185.12.15.132  Mon Nov 22 20:31:31 2021
|   4) [1] ^\[\]\s\[(:?error|\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\] AH00126: Invalid URI in request.*$
|      45.146.164.110  Mon Nov 22 15:59:06 2021
`-
…

Jailを作るファイルはどんなものでも良さそうだけれど、先程Apache用にファイルを作っているので、それを利用する。
/etc/fail2ban/jail.d/apache.local

[apache-origin]
enabled  = true
port     = http,https
filter   = apache-origin
logpath  = %(apache_error_log)s
maxlines = 1
bantime  = 1w
findtime = 1d
maxretry = 1

※この定義を追加。bantimeは1 monthとか1 yearとかでも良さそうだ。

jail.confにない新しい牢獄なので、ポート、フィルター、ログなどを個別に設定する必要がある。

さて、設定を反映してみる。

$ sudo systemctl reload fail2ban

既にログファイルは他の定義でチェック済みなので、反映後に発生した事象でBanし始める。
しばらく待ってみたところ、こんな感じでBanしはじめた。

$ sudo fail2ban-client status apache-origin
Status for the jail: apache-origin
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/apache2/check-error.log /var/log/apache2/jitsi-error.log /var/log/apache2/error.log /var/log/apache2/kopano-error.log
`- Actions
   |- Currently banned: 2
   |- Total banned:     2
   `- Banned IP list:   45.146.164.110 79.124.8.3

この後も、サクサクとBanを繰り返している。大丈夫かな?と思って調べてみたけれども、アレな感じのアクセスばっかりだったので、この設定でいいや。

ルーターの場合の設定

以前構築したルーターは、LAN内にある他のホストにポートフォワーディング(転送)して、サービスをインターネット側に公開している。

今まで行った設定では、ルーター自体を保護するためのBanができるようになっているが、ポートフォワーディングを止められない。
これは、Fail2BanのルールがINPUTチェーンに追加されていて、FORWARDチェーンには追加されないため。

そこで、FORWARDチェーンからも同じチェーンにジャンプするように設定する。
Ban動作はiptables-multiportとiptables-allportsが定義されている。

/etc/fail2ban/action.d/iptables-multiport.local ※新規作成

[Definition]

actionstart = <iptables> -N f2b-<name>
              <iptables> -A f2b-<name> -j <returntype>
              <iptables> -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
              <iptables> -I FORWARD -p <protocol> -m multiport --dports <port> -j f2b-<name>

actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
             <iptables> -D FORWARD -p <protocol> -m multiport --dports <port> -j f2b-<name>
             <actionflush>
             <iptables> -X f2b-<name>

.localファイルを作ると、変更分だけを定義できると書かれていたので、ファイルを作って定義する。
iptables-multiport.confからactionstartとactionstopのところをコピーしてきて、赤文字部分を追加している。

同様に、iptables-allports.localも定義する。
/etc/fail2ban/action.d/iptables-allports.local

[Definition]

actionstart = <iptables> -N f2b-<name>
              <iptables> -A f2b-<name> -j <returntype>
              <iptables> -I <chain> -p <protocol> -j f2b-<name>
              <iptables> -I FORWARD -p <protocol> -j f2b-<name>

actionstop = <iptables> -D <chain> -p <protocol> -j f2b-<name>
             <iptables> -D FORWARD -p <protocol> -j f2b-<name>
             <actionflush>
             <iptables> -X f2b-<name>

設定を反映する。

$ sudo systemctl restart fail2ban

※サービスを再起動している。リロードでは、ジャンプする設定が追加されなかった。

これで、ポートフォワーディングを止めることができた。

起きたこと

iptablesにゴミが残った

設定をミスした状態で起動したところで、こんなのが残ってしまった。
fail2banを止めても消えない。

$ sudo iptables --list-rules
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N f2b-ufw-port-scan
-N ufw-after-forward
…
-A OUTPUT -j ufw-track-output
-A f2b-ufw-port-scan -j RETURN
-A f2b-ufw-port-scan -j RETURN

このとき、fail2banにはこんなログが出ていた。

2021-11-21 16:57:33,931 fail2ban.actions        [336402]: NOTICE  [ufw-port-scan] Ban 45.155.205.93
2021-11-21 16:57:33,947 fail2ban.utils          [336402]: ERROR   nnnnnnnnnnnn -- exec: iptables -w -N f2b-ufw-port-scan
iptables -w -A f2b-ufw-port-scan -j RETURN
iptables -w -I INPUT -p tcp -m multiport --dports all -j f2b-ufw-port-scan
2021-11-21 16:57:33,947 fail2ban.utils          [336402]: ERROR   nnnnnnnnnnnn -- stderr: "iptables v1.8.4 (legacy): invalid port/service `all' specified"
2021-11-21 16:57:33,947 fail2ban.utils          [336402]: ERROR   nnnnnnnnnnnn -- stderr: "Try `iptables -h' or 'iptables --help' for more information."
2021-11-21 16:57:33,948 fail2ban.utils          [336402]: ERROR   nnnnnnnnnnnn -- returned 2
2021-11-21 16:57:33,948 fail2ban.actions        [336402]: ERROR   Failed to execute ban jail 'ufw-port-scan' action 'iptables-multiport' info 'ActionInfo({'ip': '45.155.205.93', 'family': 'inet4', 'fid': <function Actions.ActionInfo.<lambda> at 0x7efd9d6bab80>, 'raw-ticket': <function Actions.ActionInfo.<lambda> at 0xnnnnnnnnnnnn>})': Error starting action Jail('ufw-port-scan')/iptables-multiport: 'Script error'

このとき、こんな設定を入れていた。
/etc/fail2ban/jail.d/ufw.local ※新規作成

[ufw-port-scan]
enabled = true
port = all
filter = ufw-port-scan
logpath = /var/log/ufw.log
maxlines = 1
bantime = 1h
findtime = 10m
maxretry = 3

問題自体は、port = allを削除して解消するのだけれど、iptablesは汚れたまま。
サーバー自体を再起動すればきれいになるハズだけれど、これでiptablesをきれいにすることができた。

$ sudo systemctl stop fail2ban-server
$ sudo iptables --flush f2b-ufw-port-scan
$ sudo iptables --delete-chain f2b-ufw-port-scan
$ sudo systemctl start fail2ban-server

WordPressのログ

こんなログが出力されていた。

/var/log/apache/error.log

PHP Warning: Invalid argument supplied for foreach() in /var/www/html/wp-cron.php on line 117, referer: https://example.net/subdirectory/wp-cron.php?…

サブサイトの方にcron的な処理が入っていないため、配列ができていなくてエラーが発生している模様。
githubmemory / PHP Warning: Invalid argument supplied for foreach() in /var/www/html/wp-cron.php
WordPress support / cron errors

<wordpress root>/wp-cron.php

… 117行目
    if ( is_array( $cronhooks ) ) foreach ( $cronhooks as $hook => $keys ) {

        foreach ( $keys as $k => $v ) {
…

※赤文字を追加。

でもこれ、Wordpressがアップデートされるたびに、元に戻されてしまうかもしれない…。

さいごに

Webページへの攻撃をログから確認したので、そっか…そういうことならFBIにリダイレクトしてあげようか、等と考えて探してみたら、10年前にこのようなやりとりが。
serverfault / reroute DDOS to FBI Illegal? [closed]

そりゃ駄目だよね。

さておき、攻撃元を調べていると、ちょいちょいDigitalOceanというのが出てくる。
ここでは、インターネットホスティングサービスを安価に提供しているようだ。きっと使いやすいんだろうなぁと思ったり。

コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他