インターネット上に公開するサーバーは、従来のファイアウォールやIDS/IPSでは防ぐことができない攻撃に対しても対策するのが当たり前になってきました。
動的フィルターとして動作するFail2Banのインストール手順を解説します。
- Fail2Banって何?
- IDS/IPSの代わりを探している
- 動的ファイアウォールを構築したい
私は Rocky Linux を利用しています。「Rocky Linux (ロッキーリナックス)」と「AlmaLinux(アルマリナックス)」という Linux ディストリビューションは CentOS Linux の後継として RHEL(Red Hat Enterprise Linux)の完全クローンです。
Fail2Banってなに?
Fail2Banとは
Fail2Banとはログを監視し、不審なアクセスを検出すると通信を遮断(BAN)します。指定時間が経過したらブロックを自動的に解除(UNBAN)を実行してくれる便利なツールです。
fail2banは、サーバーのログファイルを監視し、不正なアクセスを自動的にブロックすることで、セキュリティを向上させるツールです。自動化されたブロックや拡張性の高さ、監視と通知機能、オープンソースの無料利用など、多くのメリットがあります。
Fail2Ban自体に遮断する機能はありません。iptablesやfirewalldと連携して遮断と解除を自動で実施します。
- Fail2Banはログの分析と解析を実施する
- Fail2Ban自体が通信遮断を行わない
- 通信遮断はiptablesやFirewalldが行う
つまり、Fail2banはログを解析し不正アクセスを見つけたら、iptablesやfirewalldに命令を送り通信許可リストを自動的に更新します。通信の遮断・解除はデファクトスタンダートのiptablesやfirewalldに実施されるので、安定性がピカイチです。
Fai2Banが再検知した場合、より厳しい条件で付加するルールを作成することもできます。
Fail2Banが提供している定義
Fail2Banは非常に多くの定義を最初から提供してくれます。不正アタックがよく行われる各種プロトコル(HTTP,HTTPS,SMTP,POP,IMAP,SSH,FTP,DNSなど)は標準でサポートしています。
雑感としてはログが出力でくるものは「何でも使える」って感じでしょうか。
3proxy.conf apache-auth.conf apache-badbots.conf apache-botsearch.conf apache-common.conf apache-fakegooglebot.conf apache-modsecurity.conf apache-nohome.conf apache-noscript.conf apache-overflows.conf apache-pass.conf apache-shellshock.conf assp.conf asterisk.conf bitwarden.conf botsearch-common.conf centreon.conf common.conf counter-strike.conf courier-auth.conf courier-smtp.conf cyrus-imap.conf directadmin.conf domino-smtp.conf dovecot.conf dropbear.conf drupal-auth.conf ejabberd-auth.conf exim-common.conf exim-spam.conf exim.conf freeswitch.conf froxlor-auth.conf gitlab.conf grafana.conf groupoffice.conf gssftpd.conf guacamole.conf haproxy-http-auth.conf horde.conf kerio.conf lighttpd-auth.conf mongodb-auth.conf monit.conf murmur.conf mysqld-auth.conf nagios.conf named-refused.conf nginx-botsearch.conf nginx-http-auth.conf nginx-limit-req.conf nsd.conf openhab.conf openwebmail.conf oracleims.conf pam-generic.conf perdition.conf php-url-fopen.conf phpmyadmin-syslog.conf portsentry.conf postfix.conf proftpd.conf pure-ftpd.conf qmail.conf recidive.conf roundcube-auth.conf screensharingd.conf selinux-common.conf selinux-ssh.conf sendmail-auth.conf sendmail-reject.conf sieve.conf slapd.conf softethervpn.conf sogo-auth.conf solid-pop3d.conf squid.conf squirrelmail.conf sshd.conf stunnel.conf suhosin.conf tine20.conf traefik-auth.conf uwimap-auth.conf vsftpd.conf webmin-auth.conf wuftpd.conf xinetd-fail.conf znc-adminlog.conf zoneminder.conf
実際に利用できる定義は少ないのかもしれません。しかし、多くの定義が提供されているので、参考にしながらカスタマイズし自分に最適な定義を作ることが可能です。
Fail2Ban のインストール
Firewalldの設定
Fail2Ban自体は通信遮断を行わず、実際に遮断を行うのはiptablesやfirewalldです。Rocky Linux は firewalld がインストールされているのでサービスを起動させます。合わせてOSが起動した時に自動起動するように設定を行います。
# systemctl start firewalld # systemctl enable firewalld
firewalld のデフォルト設定ではSSHしか通信許可されていません。
firewalld の動作状況を確認します。
# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens160 sources: services: dhcpv6-client ssh protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
必要に応じて対象プロトコルを追加してください。
Fail2Banのインストール
fail2ban は標準リポジトリでは提供されておらず、EPELリポジトリにて提供されています。はじめにEPELリポジトリを登録します。
# dnf install epel-release
EPELリポジトリを取り込んだら、fail2ban をインストールします。
# dnf install fail2ban
fail2ban のインストールが完了したらサービスの起動と自動起動の設定を行います。初期設定ではブロックする動作はありません。気にせず fail2ban 起動させてください。
# systemctl start fail2ban # systemctl enable fail2ban
fail2ban のログが出力され状況を確認することができます。ログには遮断したプロトコルやIPなどが出力されるので、ログを追うことで経緯を調査できます。
/var/log/fail2ban.log fail2ban.server [48544]: INFO -------------------------------------------------- fail2ban.server [48544]: INFO Starting Fail2ban v0.11.2 fail2ban.observer [48544]: INFO Observer start... fail2ban.database [48544]: INFO Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
Fail2Ban 設定の作法について
fail2ban 設定の考え方
fail2ban の設定はちょっとクセがあります。
- 設定ファイルを変更しない
- 新規ファイル(.local)で設定変更を行う
- セクション毎に設定を行う
- パラメーター名が重複している
- フィルターは個別ファイルにする
理屈さえ理解すれば簡単なので、お作法と理解して設定を行いましょう。
設定ファイルを変更しない(fail2ban.conf jail.conf)
バージョンアップを行うと、各種設定ファイルを上書きしてしまうようです。設定ファイルを新規作成してパラメーターを制御します。
/etc/fail2ban/fail2ban.local /etc/fail2ban/jail.local
fail2ban は jail.local に記述されたパラメーターを jail.conf に上書きして動作します。よって変更が必要な部分だけ記入すれば動作します。
後から見ると、変更したい部分だけ設定が記載されているのでわかりやすいです。
セクション毎に設定を行う
[]で囲ったセクション(JAILルール名)に続いて、設定を記述するとセクションの設定になります。
[DEFAULT] bantime = 1h ・・・ [sshd] enabled = true ・・・ [apache-auth] port = http,https ・・・
パラメーター名(port,logpath など)が重複しているので、別のセクションを変更してしまう時があるので気おつけてください。
フィルターは個別の設定ファイル
最近はプログラムはfail2banに限らず、設定を1つのファイルに詰め込まず、まとまり毎にファイルを作成するようになっています。
/etc/fail2ban/jail.d
/etc/fail2ban/jail.d の配下に設定ファイルを作成してください。
Fail2Ban の設定
fail2banの基本的な設定(fail2ban.local)
/etc/fail2ban/fail2ban.local (fail2ban.conf) は、ログ出力の場所や、ログレベルといった fail2ban 本体の設定を記述します。
[DEFAULT] loglevel = INFO logtarget = /var/log/fail2ban.log syslogsocket = auto socket = /var/run/fail2ban/fail2ban.sock pidfile = /var/run/fail2ban/fail2ban.pid dbfile = /var/lib/fail2ban/fail2ban.sqlite3 dbpurgeage = 1d dbmaxmatches = 10
カスタマイズの必要性が無ければ、デフォルトのままで構いません。ログの出力先を変更した際は logrotate などのログローテーションにも修正を行ってください。
フィルターの基本的な共通設定(jail.local)
/etc/fail2ban/jail.local (jail.conf) はフィルターで検出したときの振る舞いを制御する設定ファイルです。
jail.local は共通設定になり、個別で動作を変えたい場合は個別のJAIL設定を記述して制御を行います。よって、個別のJAIL設定がなければ jail.local の設定がデフォルト値として反映します。
個別のJAIL設定(/etc/fail2ban/jail.d/)
/etc/fail2ban/jail.d/ に個別設定を記述します。jail.local と異なった設定で動作を変更することができます。
各パラメーターの説明
通信遮断の条件や動作について代表的なものを記載します。
例外設定 : ignoreip
通信遮断しないホストを「IPアドレス」「CIDR」形式で記述します。
[DEFAULT] # "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban # will not ban a host which matches an address in this list. Several addresses # can be defined using space (and/or comma) separator. # 例外として除外IP ignoreip = 127.0.0.1/8 192.168.0.0/16 172.18.1.1
例外として除外IPと認識されるとログに表示されます。
/var/log/fail2ban.log fail2ban.filter : INFO [apache-sqlinject] Ignore xxx.xxx.xxx.xxx by ip
セクションの有効・無効 : enabled
[]で囲ったセクション(JAILルール名)の有効・無効を制御します。
設定を有効にする場合は「1」または「true」、無効にする場合は「0」または「false」を指定します。
[sshd] # 有効化 enabled = true
制御するポート : port
遮断するポートを制御します。「ニーモニック表示」か「ポート番号」で指定します。
# ニーモックの場合 port = http,https # ポート番号の場合 port = 80,443
遮断に利用するフィルターとログファイル: filter logpath
ログから遮断情報を抽出するためのフィルターを指定します。指定するフィルターは /etc/fail2ban/filter.d/ に保存します。
# フィルター filter = apache-sqlinject # ログファイル logpath = /var/log/httpd/access.log
遮断時間や監視の設定 : bantime findtime maxretry
フィルターで検出されたとき、挙動を制御する設定項目です。
[DEFAULT] # "bantime" is the number of seconds that a host is banned. # 遮断時間 bantime = 10m # A host is banned if it has generated "maxretry" during the last "findtime" # 監視時間 findtime = 10m # "maxretry" is the number of failures before a host get banned. # リトライ回数 maxretry = 5
メール通知の設定 : action
fail2ban が検知した時の通知に関する設定で3種類が提供されています。初期設定はログに出力されるだけでメール通知はありません。
[DEFAULT] # 遮断した時のアクション #「%(action_)s」:遮断のみ(デフォルト) #「%(action_mw)s」:遮断してWhois情報を付加してメール通知 #「%(action_mwl)s」:遮断してWhois情報とログ情報を付加してメール通知 action = %(action_mwl)s
再検知した場合の設定 : recidive
fail2ban がトラフィックを検知し遮断しても、同じように通信が来る場合のための設定を行うことができます。
デフォルトでは無効化されているので有効化する必要があります。
[recidive] # 有効化 enabled = true # 遮断時間 bantime = 1w # 監視時間 findtime = 1d
1日5回 fail2ban が遮断(BAN)すると、遮断期間を1週間に伸ばす動作になります。
設定が有効化されると、ログに出力されるようになります。
/var/log/fail2ban.log fail2ban.jail [12804]: INFO Creating new jail 'recidive' fail2ban.jail [12804]: INFO Jail 'recidive' uses poller {} ← recidiveの設定が有効化 fail2ban.jail [12804]: INFO Initiated 'polling' backend fail2ban.filter [12804]: INFO maxRetry: 5 fail2ban.filter [12804]: INFO encoding: UTF-8 fail2ban.filter [12804]: INFO findtime: 86400 ← 1週間 fail2ban.actions [12804]: INFO banTime: 604800 ← 1日 fail2ban.filter [12804]: INFO Added logfile: '/var/log/fail2ban.log' (pos = 7423, hash = bcae681f5638050c4a7cf4c7553181d6)
フィルターの実例設定
SQLインジェクション対策のFail2Ban構成
今回は Fail2Ban をSQLインジェクション対策を目的に簡易WAFとして構築します。
SQLインジェクション対策は、プログラムコードの中にエスケープ処理、サニタイジングを組み込むのは当然なのですが、どうしても「抜け」が発生したり、動作しなかったりすることが出てします。
不正対策は多段で防御することで安全性を向上させます。SQLインジェクションを試みるトラフィックは、通信自体をDropしてしまいます。トラフィックが流れてこないことは最強の不正対策です。
関連記事 Fail2BanでSQLインジェクション対策(WAF)
fail2ban-regex コマンド(テストツール)
fail2ban フィルター動作テスト
フィルターが想定通りに動作するか、ログファイルと、作成したフィルターを利用して動作テストを行うことができます。
# fail2ban-regex [ログファイル] [フィルターファイル]
# fail2ban-regex /var/log/httpd/access.log /etc/fail2ban/filter.d/apache-sqlinject.conf Running tests ============= Use failregex filter file : apache-sqlinject, basedir: /etc/fail2ban Use log file : /var/log/httpd/access.log Use encoding : UTF-8 Results ======= Failregex: 5 total |- #) [# of hits] regular expression | 1) [5] ^ -.*(union.*select|UNION.*SELECT|select.*from|delete.*from|update.*set|insert.*into|replace.*(value|set)|and(\+|%20)ascii%28substring|and(\+|%20)Length|union(\+|%20)all(\+|%20)select|and(\+|%20)1%3C1|and(\+|%20)1%3D1|and(\+|%20)1%3E1|and(\+|%20)%27.%27%3D%27|%2F\*%21[0-9]+((\+|%20)[0-9]*)?\*%2F)[^"]*HTTP[^"]* `- Ignoreregex: 0 total Date template hits: |- [# of hits] date format | [108236] Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)? `- Lines: 108236 lines, 0 ignored, 5 matched, 108231 missed ← 5件のログがマッチ [processed in 34.43 sec]
動作テストとしてSQLインジェクションと認識するアクセスをブラウザから実施しました。その時のApacheのログをfail2ban-regexコマンドに読み込ませて解析したところ、想定通りSQLインジェクションとして認識しました。
fail2ban-client コマンド
fail2ban-client コマンドが出来ること
fail2ban-client コマンドは、稼働中Fail2Banのステータスを確認したり、手動で遮断・解除したりと色々できます。色々なことができるのでよく利用するコマンドを解説します。
もっと詳細を知りたい場合はヘプルを参照してください。
# fail2ban-client -h
動作中 JAIL ルール一覧
稼働中Fail2BanのJAILルールを確認したい場合には引数に [status] を与えます。
# fail2ban-client status
# fail2ban-client status Status |- Number of jail: 1 `- Jail list: apache-sqlinject, sshd
JAILルールの apache-sqlinject, sshd が動作していることが確認できます。
動作中 JAIL ルールの個別ステータス
個別のJAILルールの状態について、もっと詳細を知りたい場合は、対象をしていすると詳細を確認することができます
# fail2ban-client status [JAILルール名]
# fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list:
手動による遮断と解除
手動による遮断ブロック(BAN)
手動で通信遮断する際には fail2ban-client コマンドを利用してBANします。
# fail2ban-client set [JAILルール名] banip [IPアドレス]
# fail2ban-client set sshd xxx.xxx.xxx.xxx
手動でBANしたあとは、fail2ban-client status [JAILルール名] で状態を確認してください。
手動によるブロック解除(UNBAN)
JAILルールの個別解除
手動で通信遮断を解除する際には fail2ban-client コマンドを利用してUNBANします。
# fail2ban-client set [JAILルール名] unbanip [IPアドレス]
# fail2ban-client set sshd unbanip xxx.xxx.xxx.xxx
手動でBANしたあとは、fail2ban-client status [JAILルール名] で状態を確認してください。
JAILルールの一括解除
手動で通信遮断を解除する際には fail2ban-client コマンドを利用してUNBANします。
# fail2ban-client unban --all
手動でBANしたあとは、fail2ban-client status [JAILルール名] で状態を確認してください。
あとがき
fail2banは、IPアドレスをブロックするためのセキュリティソフトです。主にSSHやFTP、Webサーバーなどのログイン認証の保護に使用されます。
fail2banは、ログファイルを監視し、定義された規則に基づいて、IPアドレスが一定回数のログイン失敗をした場合に、そのIPアドレスを自動的にブロックすることができます。規則はユーザーが定義することができ、ログファイルの種類やログインの失敗回数、ブロック時間などを指定することができます。
ログファイルを利用してブロックさせることができるので、利用用途は無限大に広がります。