fail2banでブルートフォース攻撃からsshdを守る2018/12/22CentOSLinuxセキュリティ勉強としてたまにハードニング大会に参加しています。とあるシステムが与えられて、そこにレッドチームが攻撃をしかけるので、ブルーチームとしてその攻撃からシステムを防御する、というイベントです。私は基本いつもブルーチーム。そんな中、真っ先に守らねばならない大穴なのがsshd。sshdは公開鍵認証のみを受け付ける設定にするか、アクセス元のセグメントでアクセス制御を行ってしまえばとりあえず防御完了なのですが、それができないシステムがたまにあります。参加人数が大人数かつ、攻撃側と防御側のセグメントが分けられていなかったり、すでにシステム内部に侵入済みであることを想定した大会であったり。今回は、そんな状況でもsshdを防御するために、fail2banというツールを使ってみます。100221234567891011vagrantで作ったCentOS7のマシンです。sshdのパスワード認証を有効にしており、ポート番号は変更してあります。Linuxから、hydraというツールを使ってsshにブルートフォースをかけてみます。vagrantユーザとして、3557行のパスワードが記載された辞書ファイルから総当たりでログイン試行を行います。辞書ファイルはネットに転がっているものを適当に拾ってきて、末尾にvagrantのパスワードを追記してあります。パスワードリストのサイズに合わせて、-tオプション(1ホストに対する同時実行数)は要調整です。13:20:401234567891011123000回超のログイン試行がものの15分で完了し、パスワードを特定できました。/var/log/secureは大変なことになっているので、ハードニングやってる現場ならログみてfirewall-cmdでドロップさせればいいですが、ログとにらめっこしIP一つ一つ手作業でドロップさせる時間は、できれば他のセキュア化の時間に回したい。fail2banとはfail2banとは、システムの各ログを監視し、不正アクセスだと疑わしいアクセスをしてきたIPアドレスをバンするiptablesやfirewalldのポリシーを自動的に追加するプログラムです。sshdはもちろん、httpdやvsftpd、PostfixなどいろいろなMWのログからファイアウォールポリシーを生成できます。ログ監視方式(フィルターと言います)と、どうバンするか(アクションと言います)は自前で定義せねばなりませんが、有名なMWのフィルター、アクションはデフォルトで定義されています。httpdやnginxはBASIC認証のログイン監視もデフォルトでできるっぽいのでやってみたいです。fail2banのインストールepelから。fail2banの設定ファイル類fail2banの設定ファイルはたくさんあります。原則、設定ファイルはそのまま編集せず、.confを.localにリネームしてコピーしたファイルを編集します。update時に上書きされちゃうので。fail2ban自体のログの設定やpidファイルの場所、バックエンドで使用するdbのパスなど、fail2ban全体の設定が記載されています。原則変更する必要はありません。paths-*.confは、ディストリごとに異なる各ログのパスが定義してあります。同じメールログでも、ディストリごとにログファイル名は異なるため、定義しておかねばなりません。読み込みの流れは複雑です。ファイルを読むか定義しておきます。ログパスを修正したい場合、paths-overrides.localという名前で設定ファイルを作成すればいいようです。jail.conf、fail.d/*は、どのフィルターを有効化するか、どのログをフィルターするか、フィルターに引っかかったときどうアクションするかを定義するファイルです。普通に利用する分には、主にこのファイルを編集することになります。編集はjail.localにリネームコピーして行います。filter.dの中には、どうログ監査を行うのかの設定(フィルター)が記載されたファイルがたくさんあります。sshd関連だと以下の3種類がデフォルトでありました。sshd-ddos.conf12action.dの中には、実際にどうバンを行うかの設定(アクション)が記載されたファイルがたくさんあります。firewalldで行うアクションだと、以下の6種類がデフォルトでありました。これも自分で作るのは難しそう。上記の通り、普通に利用する分には、fail.confのみを編集することになります。編集する際はjail.localにリネームコピーしてから行います。00-firewalld.conf1234jail.localの中身を見ていきます。[INCLUDES]セクションここでどのログパスを読むかを指定します。今回はCentOSなのでfedoraです。デフォルトでfedoraに設定してありました。[DEFAULT]セクションここでfail2banの基本動作を定義します。ここで定義した動作は、後述のMWごとのセクションでオーバーライド可能です。基本的な部分のみ書いておきます。ignoreipfail2banが無視するホストを定義します。信頼できるホストをここで定義します。IPアドレス、CIDRでのマスク、DNSホスト名いずれも定義に使えます。複数ホストを列挙する場合はスペース区切りで。bantimeバンする期間を定義します。デフォルトだと600秒。findtimeとmaxretryfindtimeの期間中に、maxretryの回数ログイン試行が失敗した場合にバンします。デフォルトだと600秒中に5回。backendログを監視するバックエンドモジュールの指定。pythonモジュールpyinotifyを利用したりsystemdのjounalctlを利用したりいろいろあります。デフォルトはauto。性能を求めるならこれは変更しないといけない。usedns各ログにホストネームにてアクセスログが記載されていた場合に、自前でIPアドレスを逆引きするかどうかを指定します。firewalldやそのバックのiptablesは、ホスト名でアクセス制御を行うことができないため、IPアドレスの情報は必須です。ログにホストネームしか記載がなかった場合、それをIPアドレスに解決しないといけません。ホストネームはいくらでも変更できるため信用できませんし、大量のアクセスを食らった際にいちいち名前解決を行うとそれだけでDoSです。usednsは、yesだと黙って逆引きをする、warnだと逆引きはするけど警告をログに残す、noだと逆引きを行わずバンも行わず、情報をログに残す、の3択です。rawはホスト名が関係ない(例えばユーザ名のみを見る、など)フィルタ/アクションの際に指定します。noが一番性能いいですが、ホストネームでアクセスしてきた場合にまったくバンができません。いいのは、fail2banを使うサービスのログにはホスト名を記載しない設定にし、usednsをnoにすること。enabledfail2banを有効にするかどうか。DEFAULTセクションでは無効にしておいて、有効化するサービスのセクションで有効に上書きするのがいいと思います。banactionとbanaction_allportsバンを行うときのアクションの基本を定義します。実際は、アクション定義ファイルにてメール通報を行ってログに書いてバンする、と細かく書いてありますが、この実際のバンをどうやるか指定するのがここです。デフォルトでは、下記のようにiptablesがバンを実施する設定になっています(このiptables-*というファイルはactions.d/内にあります)。iptables-allports12しかし、CentOS7はiptablesをfirewalldがラッピングしており、iptablesは起動していないので、firewalldがバンを行うよう設定せなばなりません。その設定は、jail.localではなく、jail.d/00-firewalld.confに記載があります。ここでfirewalldに上書きされています(このfirewallcmd-*というファイルもactions.d/内にあります)。firewallcmd-ipset123456なぜかデフォルトではbanaction_allportsのみfirewalldで定義されていなかったため、別ファイルで追記しておきました。[sshd]セクションここから各MWごとの設定になります。portバンを行うポート番号です。デフォルトでsshという定義(22)がされています。カンマ区切りで列挙、コロンで連番を指定できます。ちなみにudpを指定したい場合は、portではなくprotocolというディレクティブで別に定義します。logpath監視を行うsshdのログのパス。この変数はpaths-common.confで定義されていました。backendsshdのログを監視するバックエンドモジュール。[DEFAULT]セクションではautoに設定されていましたが、paths-fedora.confでsystemdへオーバーライドされていました。enabled有効化するのでenabledに。filter基本的に、セクション名(今回はsshd)と同名のフィルタが、filter.d/に存在していれば、それが使用されます。それ以外にフィルタを追加したい場合はこのディレクティブを使います。なんかより積極的な検知ができるフィルタがあるとのことなので、追加で有効化しておきます。動作確認fail2banの動作確認は以下のfail2ban-clientコマンドでできます。引数なしのstatusだと、なんのサービスを監視しているかがわかり、そのサービス名を引数に取ると、バンの状況が見れます。Linuxからhydraをかけてみます。refusedが大量に表示されていつまでたっても完了しませんでした。fail2ban側から見ても、きちんとバンできています。192.168.100.20112345678910これでなんとなくハードニングでも使えることがわかりました。BASIC認証にも使えるらしいので、早めに試してみたいです。REJECTとDROPデフォルトだと、バンされたホストはREJECTされるようです。これをDROPに変えて、何も通知を出さないようにするには、アクション設定ファイルのblocktypeを変更すればいいようです。actions.d/でgrepかけてみます。DROP1234567出てきたfirewalldcmd-rich-*の2つはもちろん、iptables-commonも下記のようにfirewallcmd-*から読み込まれているので、修正します。iptables-common.conf12345つまるところ、以下のファイルのblocktypeをdropに変更すればいいものと思います。firewallcmd-rich-logging.conffirewallcmd-rich-rules.confiptables-common.confおわり。