BSD界隈四方山話

第113回blacklistd(8)を使ってsshd DoS攻撃を防止する方法

blacklistd(8)でsshd DoS攻撃を防止する方法

FreeBSD 11.0-RELEASEにNetBSDのblacklistd(8)がマージされました。blacklistd(8)はsyslogd(8)のように各サーバから認証失敗データなどを収集し、設定に基づいて上限に到達した通信を一定期間ブロックするといったものです。ブルートフォース攻撃やDoS攻撃に対する緩和機能として利用できます。

FreeBSD 11.1-RELEASEではsshd(8)のコードにblacklistd(8)と連動するためのコードが追加されました。このため、設定をすることでsshdに対するDoS攻撃を防止するといったことが簡単にできるようになりました。ここではファイアウォール機能ipfw(8)を利用する場合の設定方法を紹介します。

まず、/etc/rc.confファイルに次のような設定を追加します。

リスト /etc/rc.confに追加する設定
# sshd
sshd_enable="YES"
sshd_flags="-o UseBlacklist=yes"

# blacklistd
blacklistd_enable="YES"

# firewall
firewall_enable="YES"
firewall_type="OPEN"

sshdはデフォルトの設定ではblacklistd(8)に対応していませんので、⁠sshd_flags="-o UseBlacklist=yes"」のようにフラグを追加して機能を有効にします。blacklistd(8)を起動するために「blacklistd_enable="YES"」を追加し、さらにファイアウォール機能ipfwを有効にするために「firewall_enable="YES"」「firewall_type="OPEN"」を追加します。すでにipfw(8)を使っている場合には「firewall_type="OPEN"」は特に必要なく、現在の設定のままで利用してください。

このままではblacklistd(8)がipfw(8)を使わないので、次のように鍵となるファイルを作ります。これでipfw(8)が使われるようになります。

 ipfw(8)が使われるようにファイルを作成する
# touch /etc/ipfw-blacklist.rc

この状態でシステムを再起動すると、次のようにsshd(8)がblacklistd(8)を利用可能な状態で起動してきます。

 blacklistd(8)に対応したsshd(8)
# ps auxww | grep sshd
root    661  0.0  0.7  57812  6940  -  Is   17:19   0:00.00 /usr/sbin/sshd -o UseBlacklist=yes
#

ipfw(8)が有効になっているので、たとえば次のようなフィルタリングルールが動作していることを確認できます。

 ipfw(8) OPENで設定されているデフォルトのフィルタリングルール
# ipfw list
00100 allow ip from any to any via lo0
00200 deny ip from any to 127.0.0.0/8
00300 deny ip from 127.0.0.0/8 to any
00400 deny ip from any to ::1
00500 deny ip from ::1 to any
00600 allow ipv6-icmp from :: to ff02::/16
00700 allow ipv6-icmp from fe80::/10 to fe80::/10
00800 allow ipv6-icmp from fe80::/10 to ff02::/16
00900 allow ipv6-icmp from any to any ip6 icmp6types 1
01000 allow ipv6-icmp from any to any ip6 icmp6types 2,135,136
65000 allow ip from any to any
65535 deny ip from any to any
#

blacklistd(8)も次のように動作していることを確認できます。

 blacklistd(8)の動作も確認
# ps auxww | grep blacklistd
root    712   0.0  0.3  14772  2572  -  Ss   17:19    0:00.01 /usr/sbin/blacklistd
#

blacklistd(8)の保持しているルールはblacklistclt(8)コマンドで次のように確認できます。システムを再起動した段階では次のようになんのルールも入っているはずです。

 まだ何も検出していない状態のblacklistd(8)
# blacklistctl dump -a
        address/ma:port id      nfail   last access
#

blacklistd(8)の設定は/etc/blacklistd.confです。このファイルはデフォルトでは次のようになっています。この場合、sshにおける認証が3回失敗すると以後24時間はアクセスできない状態になります。

リスト blacklistd(8)の設定ファイルである/etc/blacklistd.conf
# $FreeBSD: releng/11.1/etc/blacklistd.conf 301226 2016-06-02 19:06:04Z lidl $
#
# Blacklist rule
# adr/mask:porttype	proto	owner		name	nfail	disable
[local]
ssh		stream	*	*		*	3	24h
ftp		stream	*	*		*	3	24h
smtp		stream	*	*		*	3	24h
submission	stream	*	*		*	3	24h
#6161		stream	tcp6	christos	*	2	10m
*		*	*	*		*	3	60

# adr/mask:port	type	proto	owner		name	nfail	disable
[remote]
#129.168.0.0/16	*	*	*		=	*	*
#6161		=	=	=		=/24	=	=
#*		stream	tcp	*		=	=	=

ほかのホストからsshでログインを試み、3回失敗してみます。すると次のように、4回目はそもそもサーバへの接続がブロックされるようになります。

 blacklistd(8)経由でアクセスがブロックされた状態
$ ssh 192.168.185.50
Password for daichi@virt.ongs.co.jp:
Password for daichi@virt.ongs.co.jp:
Password for daichi@virt.ongs.co.jp:
Permission denied (publickey,keyboard-interactive).
$ ssh 192.168.185.50

この状態でipfw(8)のルールをチェックすると、22番ポートへのアクセスがブロックされたことを確認できます。

 ipfw(8)のルールにブロックが追加されたことを確認
# ipfw list
00100 allow ip from any to any via lo0
00200 deny ip from any to 127.0.0.0/8
00300 deny ip from 127.0.0.0/8 to any
00400 deny ip from any to ::1
00500 deny ip from ::1 to any
00600 allow ipv6-icmp from :: to ff02::/16
00700 allow ipv6-icmp from fe80::/10 to fe80::/10
00800 allow ipv6-icmp from fe80::/10 to ff02::/16
00900 allow ipv6-icmp from any to any ip6 icmp6types 1
01000 allow ipv6-icmp from any to any ip6 icmp6types 2,135,136
02022 deny tcp from table(port22) to any dst-port 22    ← ここに追加されている
65000 allow ip from any to any
65535 deny ip from any to any
#

blacklistctl(8)コマンドでブロック情報を確認すると、次のようにルールが追加されたことを確認できます。

 blacklistd(8)経由でブロックルールが追加されたことを確認
# blacklistctl dump -a
        address/ma:port id      nfail   last access
  192.168.185.1/32:22   OK      3/3     2017/08/23 18:27:01
#

blacklistctl(8)コマンドは-rを指定するとルールが適用される残り時間を表示させることもできます。次のような感じです。

 blacklistctl(8)はルールが適用される残り時間を表示させることもできる
# blacklistctl dump -ar
        address/ma:port id      nfail   remaining time
  192.168.185.1/32:22   OK      3/3     23h58m22s
#

blacklistd(8)はデフォルトの設定だと/var/db/blacklistd.dbに接続エントリ情報を保持していますので、再起動してもこのデータは保持されたままです。この保持しているデータに従ってもう一度ブロックルールを適用するか、またはルールをすべてクリアするかをblacklistd(8)のオプションで指定できます。-fならルールをクリア、-rならルールをベースにブロックルールを再適用です。設定としては次のような設定を/etc/rc.confに追加します。

リスト システムを再起動したらブロックをクリア
blacklistd_flags="-f"
リスト システムを再起動したら再度ルールを適用してブロックを開始
blacklistd_flags="-r"

blacklistd.conf(5)には[local]と[remote]という2つのエントリがあります。使い方としては[local]の方がデフォルト設定で、[remote]の方がそれを上書きするような関係になっています。たとえば、[local]の方にはデフォルトのブロックルールを書いておいて、[remote]の方にはたとえば特定のホストに関してはブロックからはずすホワイトリスト的な設定を書くとか、規制回数を変更するといった感じです。この2つのルールを使いこなすことで現実的なルールを書いていきます。

ここまでの設定でだいたい一通り基本的な操作はできるようになります。blacklistd(8)はlibblacklist APIを使うことで汎用的に利用できますので、ほかのサーバをblacklistd(8)対応にしたり、独自に開発しているサーバをblacklistd(8)に対応させるといったことも簡単に実現できます。

blacklistd(8)の使い方に関しては下記勉強会でより詳しい内容を取り上げようと思います。ご興味ある方は勉強会の方もご検討いただければと思います。

勉強会

10月4日(水)19:00~ 第66回 FreeBSD勉強会~vBSD 2017とEuroBSDCon 2017から旬な技術をご報告! - ヴァル研究所 セミナールーム

9月に米国バージニア州で開催されるvBSDcon 2017とフランスで開催されるEuroBSDCon 2017から、最新の*BSDトピックを面白いところにしぼってお伝えします。カンファレンスへの渡航費用と参加費用を見ると、日本でこの情報を得られるのはとってもお得です。みなさまのお越しをお待ちしております。

本勉強会への参加者には抽選か勝ち抜きかデーモンTシャツなどのグッズをお渡しします。ふるってご参加ください。

参加登録はこちらから。

10月26日(木)19:00~第67回 FreeBSD勉強会~blacklistd(8)でsshd DoS攻撃を防止する方法 基礎から応用まで - ドワンゴ セミナールーム

FreeBSD 11.0-RELEASEにはblacklistd(8)と呼ばれるデーモンが取り込まれました。これはNetBSDのblacklistd(8)をマージしたもので、設定に従ってサーバに対するDoS攻撃とみられるアクセスに対し、自動的にアクセスを閉じるといった処理をしてくれます。

FreeBSD 11.1-RELEASEからはシステムのsshd(8)がblacklistd(8)に対応するようになりました。ログインに何回か失敗したら何時間の間アクセスをブロックするといった設定を行うことができます。ホワイトリスト的な設定も追加することでき、全体としてのブロック設定をおこないつつ、特定のホストからのアクセスは許可したり、特定のホストからのアクセスは規制を緩くしておくといったことも可能です。

blacklistd(8)と類似した機能を提供するソフトウェアにはsshguard、fail2ban、denyhostsなどがあります。これらソフトウェアと比較したblasklistd(8)の特徴は処理の軽快さにあります。また、ipfw、pf、ipfilterというFreeBSDが提供しているすべてのファイアウォール機能に対応しているほか、もちろんNetBSD npfに対応しています。

blacklistd(8)はライブラリとしてlibblacklistを提供しているため、sshdに限らずほかのさまざまなソフトウェアからも利用できる汎用的な機能です。いくらかのコードの書き換えでblacklistd(8)を利用できるようにすることができます。

今回の勉強会ではblacklistd(8)がどのように動作しているのか紹介するとともに、設定方法などの基本的な方法から、既存のソフトウェアをblacklistd(8)に対応させる場合にどのように開発を行えばよいかなどを紹介します。

参加登録はこちらから

FreeBSD勉強会 発表者募集

FreeBSD勉強会では発表者を募集しています。FreeBSDに関して発表を行いたい場合、@daichigotoまでメッセージをお願いします。30分~1時間ほどの発表資料を作成していただき発表をお願いできればと思います。

おすすめ記事

記事・ニュース一覧