玩式草子─ソフトウェアとたわむれる日々

第94回 サイトの防御とFail2ban[その1]

この記事を読むのに必要な時間:およそ 4.5 分

Fail2banの仕組み

Fail2banの実体はPythonで書かれたスクリプトで,起動すると各種設定ファイルを読み込んだ上で,デーモンプロセスとして常駐し,ログファイルを監視し続けます。

Fail2banの設定ファイルには,全体的な動作を設定するための/etc/fail2ban/fail2ban.confと,どのようなサービスとログファイルを監視するかを設定する/etc/fail2ban/jail.confの2種があります。これらのファイルにはあらかじめデフォルト値が設定されているものの,監視したいサービスやログファイルはサイトごとに異なるため,/etc/fail2ban/jail.localというファイルでこれらデフォルトの設定値を書き換えるようになっています。jail.localはFail2banを更新しても上書きされないので,サイトごとの設定はこのファイルで指定するのがいいでしょう。

jail.{conf,local}では,ブラケット([...])で監視対象のサービスを指定し,監視すべきログファイルとどのようなメッセージをチェック対象にするかのフィルタ,攻撃があった場合にどのような処理をするかのアクション,を設定します。

たとえば,手元の/etc/fail2ban/jail.confではsshdに関する監視はこのように設定されています。

[ssh-iptables]
enabled  = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
           sendmail-whois[name=SSH, dest=you@example.com, sender=fail2ban@example.com, sendername="Fail2Ban"]
logpath  = /var/log/secure
maxretry = 5

この設定は,logpathで指定したログファイル(/var/log/secure)を"sshd"というフィルタを使ってチェックし,一定時間内に5回以上(maxretry)該当するエラーメッセージが出力されれば総当たり攻撃が行なわれたと見なし,action欄に指定されたiptablesとsendmail-whoisという処理を[...]内に指定された引数を使って実行する,という意味になります。なお,"enabled = true"行は,この設定を有効にする,という指定で,"enabled = false"とすれば設定を一時的に無効化できます。

filter行に指定している各種フィルタは/etc/fail2ban/filter.d/以下に用意されており,今回の"sshd"フィルタは/etc/fail2ban/filter.d/sshd.confに該当します。このフィルタにはsshdの出力するエラーメッセージのさまざまなパターンが登録されています。

# Fail2Ban filter for openssh
#
...  
[Definition]

_daemon = sshd

failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \S+)?\s*$
            ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
            ^%(__prefix_line)sFailed \S+ for .*? from <HOST>(?: port \d*)?(?: ssh\d*)?(: (ruser .*|(\S+ ID \S+ \(serial \d+\) CA )?\S+ %(__md5hex)s(, client user ".*", client host ".*")?))?\s*$
            ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
            ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
...

このファイルのfailregex行に指定されているのが,正規表現で記述したエラーメッセージの各種パターンです。たとえば,最初の行では"authentication failure"や"Authentication error"というエラーが,その次の行では"User not known"のエラーが捉えられることになります。その後も"ROOT LOGIN REFUSED"や"User not allowed"等のメッセージを捉えるための表現が並び,sshdが出力するたいていのエラーメッセージが捕捉できるようになっています。

筆者が"Fail2ban"に感心したのはこのフィルタ用ファイルの豊富さで,sshdだけではなく,メールサーバのpostfixやexim,qmail,dovecot,FTPサーバのproftpdやvsftpd,wuftpd,その他,apache httpdやPHP,mysql,named 等,広く使われているサーバにはたいていフィルタが用意されているようです。

これらのフィルタにより総当たり攻撃が検出されるとjail.confのaction行で指定した処理が実行されます。action行で指定する処理は/etc/fail2ban/action.d/に収められており,Linux用のiptablesを使う処理のみならず,tcpwrapper用にhosts.denyファイルを修正する処理やBSD系OSで使われているpfやipfw用の処理も用意されています。また,接続を拒否する処理以外にも,ブロックしたIPアドレスを外部のデータベースに登録したり,攻撃元の情報をwhoisで調べてメールで送信するような処理も用意されています。

今回の例でactionとして指定したのはiptablessendmail-whoisで,前者がiptablesコマンドを利用して攻撃元サイトをブロックするための処理,後者が攻撃元サイトをwhoisで調べた結果をsendmailで通知する処理です。

前者の設定は/etc/fail2ban/action.d/iptables.confに記述されているので,一部を眺めてみましょう。

# Fail2Ban configuration file
#
# Author: Cyril Jaquier
...
# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = <iptables> -N f2b-<name>
              <iptables> -A f2b-<name> -j <returntype>
              <iptables> -I <chain> -p <protocol> --dport <port> -j f2b-<name>

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop = <iptables> -D <chain> -p <protocol> --dport <port> -j f2b-<name>
             <iptables> -F f2b-<name>
             <iptables> -X f2b-<name>
...
# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
...

これらの処理は設定ファイルで指定した[name=SSH, port=ssh, protocol=tcp]という引数を使って実行されます。Fail2banが起動されると,まずactionstart部の処理が実行され,iptablesコマンドを使ってそれぞれのサービスごとにチェーンを用意します。その後,攻撃元のIPアドレスを拒否する際は,actionban部で該当するIPアドレスからのパケットをREJECTするように,それぞれのチェーンに登録していきます。なお,actionban部にある<blocktype>は事前に読み込むiptables-common.confで定義されており,デフォルトでは"REJECT --reject-with icmp-port-unreachable"という設定になっています。

sendmail-whoisの処理は/etc/fail2ban/action.d/sendmail-whois.confに記述され,攻撃元のIPアドレスと共に,そのアドレスをwhoisで検索した結果を指定した宛先にメールで送信します。actionban部の<sendername>や<sender>,<dest>にはjail.confで[...]内に指定した引数が展開されます。

# Fail2Ban configuration file
#
# Author: Cyril Jaquier
...
[Definition]
...
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from `uname -n`
            Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
            From: <sendername> <<sender>>
            To: <dest>\n
            Hi,\n
            The IP <ip> has just been banned by Fail2Ban after
            <failures> attempts against <name>.\n\n
            Here is more information about <ip> :\n
            `/usr/bin/whois <ip> || echo missing whois program`\n
            Regards,\n
            Fail2Ban" | /usr/sbin/sendmail -f <sender> <dest>
...

このsendmail-whois.confが実行されると,実際にはこんなメールが飛んできます。

図2 sendmail-whois.confの実行例

図2 sendmail-whois.confの実行例

なお,本文中で紹介したssh-iptableはサンプル例のため,メールの画面は手元で運用しているpostfixに対する監視から届いたものを用いました。

以上見てきたようにFail2banは,⁠ログファイルを監視して,異常があればそれに応じた対応を取る」という作業をスクリプトで自動化するという設計方針になっており,状況とそれに応じた対策をわかりやすく指定できます。

次回は,Fail2banの実際の動作例を紹介しつつ,最近の総当たり攻撃の状況を検討してみる予定です。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html