共通テーマ:iptablesダイナミック・ファイアウォール

柔軟で有用なネットワーク・セキュリティ

ファイアウォールはきわめて有用なものです。しかし、ファイアウォールのルールに対して複雑で迅速な変更が必要な場合は、一体どうすればよいのでしょうか。その答えは簡単です。以下に示されるDaniel Robbinsのダイナミック・ファイアウォール・スクリプトを使えばよいのです。このスクリプトによって、ネットワーク・セキュリティおよびレスポンスの向上が可能となり、またユーザー独自の設計にも役立ちます。

Daniel Robbins (drobbins@gentoo.org), President/CEO, Gentoo Technologies, Inc.

Daniel Robbins氏は、ニューメキシコ州アルバカーキーに住んでいます。彼は、Gentooプロジェクトのチーフ・アーキテクト、Gentoo Technologies Inc. の社長/CEOです。著書に、Macmillanから出版されているCaldera OpenLinux Unleashed、SuSE Linux Unleashed、Samba Unleashed があります。Daniel氏は、小学2年のとき初めてLogoプログラム言語や、中毒になる恐れのあったPac Manに出会って以来、何らかの形でコンピューターに関係してきています。これで、彼がなぜSONY Electronic Publishing/Psygnosisでリード・グラフィック・アーチストを務めているかが分かるでしょう。愛妻Maryさんや、生まれたばかりの愛娘Hadassahちゃんとの時間をとても大切にしています。彼の連絡先はdrobbins@gentoo.org です。



2001年 4月 01日

このダイナミック・ファイアウォール・スクリプトの特長を知るには、その使用例を見ることが最もよいでしょう。まず、私がある インターネット・サービス・プロバイダ (ISP) のシステム管理者であるとしましょう。私は、Linuxベースのファイアウォールをセットアップしました。このファイアウォールは、インターネット上の悪意のある第三者から自分の顧客と内部システムを守るためのものです。このファイアウォールではLinux 2.4の新しいiptables機能を使用してカスタマーやサーバーに対する送受信接続を行いますが、その受信接続はWeb、ftp、ssh、SMTPのような「一般の」サービスのためのみのものでした。指定したもの以外は拒否する(deny-by-default)という設計を採用し、スクイッド・プロキシ・キャッシュ(squid proxy cache)やSambaサーバーなど、一般的ではない業務に対する、インターネット接続はすべて自動的に拒否するようにしました。これにより、このISPを利用するすべてのユーザーに対して高水準のセキュリティが提供されるようになります。

当初、このファイアウォールはきわめて順調に機能しましたが、1週間ほど経った時点で大きな問題が発生しました。私の天敵であったBob (競合のISPに勤務する) が、わが社のネットワークに大量のデータを送信することによって、わが社の顧客に対するサービスを妨害しようとしていたのです。Bobは私の設計したファイアウォールを細かく研究しており、わが社が内部サービスに対する保護を行う一方で、メール受信とHTTP送信のための外部アクセスにポート25とポート80を使用していることを知っていました。Bobはこれを利用し、わが社のWebサーバーとメール・サーバーに対して「帯域幅占有攻撃」を行おうとしていました。

Bobが攻撃を開始して約1分後、私は、アップリンクがパケットでいっぱいになりはじめたことに気付きました。tcpdumpを使ってその状況を調べると、それがBobによる新たな攻撃であることが判りました。私はすぐに、彼がその攻撃に使用しているIPアドレスを割り出しました。彼が使用しているIPアドレスが判ったことによって、後はこのIPアドレスをブロックしさえすれば問題は解決するはずでした。そして、それは私にとっては簡単な作業であるように思えました。

攻撃への対処

私は、Bobが送信してくるパケットをブロックするため、ファイアウォール・セットアップ・スクリプトをすぐにviで開いて、iptablesルールを書き換えてファイアウォールの修正を開始しました。そして約1分後、私はDROPルールを追加できる箇所を見つけ、その追加を行いました。このようにして、私はファイアウォールの起動、終了を行いましたが…しかし、ルールの追加をする際にちょっとしたミスを犯してしまいました。そこで、ファイアウォール・スクリプトを再び開いた後にミスを修正し、30秒後にファイアウォールの微調整を行いました。当初、私は攻撃の阻止に成功したと思っていましたが、ヘルプデスクに苦情の電話がかかってきたことによって、そうではないことを知りました。約10分間、Bobはネットワークの停止に成功したらしく、カスタマーから問い合わせの電話がかかってきたのです。さらに悪いことには、数分後にアップリンクが再びいっぱいになりはじめたことに私は気づきました。今回Bobは、新しいIPアドレスを攻撃に使用しているようでした。それに対して、私はファイアウォール・スクリプトを懸命に修正しましたが、今回は少しパニック状態であったため、私の対応はうまくいかない恐れもありました。

上記の例では、どのような問題があるでしょうか。この例では、優れたファイアウォールがあり、また発生したネットワーク・トラブルの原因を迅速に把握できたにもかかわらず、一定の時間内にファイアウォールの設定を修正することができませんでした。ネットワークが攻撃を受けた場合には、当然、迅速な対応が必要とされますが、パニック状態におけるファイアウォール・セットアップ・スクリプトの修正は、精神的に疲れるだけでなく、手際が悪くなりがちです。


ipdrop

もし、「ipdrop」スクリプトによって、特定のIPアドレスをブロックするためのルールを挿入できれば、その有用性はきわめて大きいでしょう。そのようなスクリプトによって、これまで2分もかかったファイアウォールのブロックであっても、わずか5秒で済むようになるでしょう。また、ファイアウォールのルールを手作業で修正する必要がなくなるため、エラーの大部分は解消されることでしょう。行うべきことは、ブロックすべきIPアドレスを判断し、それを入力するだけです。

#ipdrop 129.24.8.1 on
IP 129.24.8.1 drop on.

ipdropスクリプトによって、Bobが攻撃に用いているIPアドレス「129.24.8.1」へのブロックが行われます。このスクリプトによって、IPアドレスのブロックはきわめて簡単に行えるようになるため、攻撃への対応は劇的に向上します。次に、ipdropスクリプトの実装例を見てみましょう。

ipdrop bashスクリプト
#!/bin/bash
source /usr/local/share/dynfw.sh
args 2 $# "${0} IPADDR {on/off}" "Drops packets to/from IPADDR. Good for obnoxious
                                  networks/hosts/DoS"
if [ "$2" == "on" ] 
then
	#rules will be appended or inserted as normal
	APPEND="-A"
	INSERT="-I"rec_check ipdrop $1 "$1 already blocked" on
	record ipdrop $1
elif [ "$2" == "off" ]
then
	#rules will be deleted instead
	APPEND="-D"
	INSERT="-D"rec_check ipdrop $1 "$1 not currently blocked" off 
	unrecord ipdrop $1
else
	echo "Error: \"off\" or \"on\" expected as second argument"
	exit 1
fi	

#block outside IP address that's causing problems
#attacker's incoming TCP connections will take a minute or so to time out,
#reducing DoS effectiveness.
iptables $INSERT INPUT   -s $1 -j DROP
iptables $INSERT OUTPUT  -d $1 -j DROP
iptables $INSERT FORWARD -d $1 -j DROP
iptables $INSERT FORWARD -s $1 -j DROP

echo "IP ${1} drop ${2}."

ipdropの説明

ハイライトされた最後の4行は、ファイアウォール・テーブルに適切なルールを挿入するためのコマンド行です。ご覧のように、「オン」モード、「オフ」モードによって、$INSERT環境変数の定義は変わります。iptablesの行が実行されると、特定のルールの挿入または削除が行われます。

次に、ルールの関数を見てみましょう。これは、あらゆるタイプの既存のファイアウォール、またファイアウォールを持たないシステムにでも使用できます。このルールの使用に必要なものは、2.4カーネルによるiptablesのサポートのみです。攻撃に使用されているIPアドレスから受信したパケットをブロックし (スクリプト中のiptables行の最初) 、また、そのIPアドレスに対するパケットの送信をブロックします (iptables行の2番目) 。そして、この特定のIPアドレスに対する送受信を解除します (iptables行の最後の 2つ) 。一旦このルールが適用されれば、システムはこれらのカテゴリーに該当するあらゆるパケットを廃棄します。

また、もうひとつ気づく点は「rec_check」、「unrecord」、「record」、「args」へのコールがあることです。これらは「dynfw.sh」で定義される、特別なヘルパーbash関数です。「record」関数は、ブロックされたipを (/root/.dynfw-ipdrop) ファイルに記録し、また「unrecord」は (/root/.dynfw-ipdrop) からエントリーを削除します。「rec_check」関数は、既にブロックされているIPアドレスに再ブロックを行おうとしたり、また現在ブロックされていないIPアドレスに対してブロック解除を行おうとした場合に、エラー・メッセージを表示してスクリプトの実行を中止するために使用します。「args」関数は、コマンド・ライン引数を必要な個数だけ正確に受け取る処理を行ない、また有用な使用情報の印刷も行います。私はこれらのツールをすべて組み込んだ dynfw-1.0.tar.gz を作成しました。詳細については、この記事の最後にある 「参考文献」 のセクションをご覧ください。


tcplimit

このダイナミック・ファイアウォール・スクリプトは、TCPベースの特定のネットワーク・サービスの使用を制限する場合に有用です。クライアントのCPUに対して重い負荷を与えるサービスが、そのようなものの例です。このスクリプトは「tcplimit」と呼ばれ、TCPポート、回数、単位時間、「オン/オフ」を引数として指定します。

#tcplimit 873 5 minute on
Port 873 new connection limit (5/minute, burst=5) on.

tcplimitは、新たなiptablesの「記述」モジュールを使用して、一定の時間内の新規受信接続の上限を設定することが可能です(カーネルで使用可能となっているか、あるいはモジュールがロードされていることを確認してください) 。上記の例では、rsyncサーバー (ポート873) への接続は、ファイアウォールによって1分間に 5 回に制限されています。必要に応じて、秒/分/時間/日あたりの接続数を指定することが可能です。

tcplimitによって重要性の低いサービスを制限できるため、そのようなサービスの過剰なトラフィックによるネットワークやサーバーの停止を防ぎます。私の例では、tcplimitを使ってrsyncの使用に上限を設定することで、過剰なrsync接続によってDSLラインがビジーになることを回避できます。接続を限定したサービスはin/root/dynfw-tcplimitに記録されます。新規の接続に対する制限を解除したい場合には、以下のように入力します。

#tcplimit 873 5 minute off
Port 873 new connection limit off.

tcplimitは、「フィルター」テーブルに、まったく新しいチェーンを生成することで機能します。この新たなチェーンにより、設定された制限を超えるパケットはすべて拒否されることになります。コマンドが入力された後、そのルールがこのINPUTチェーンに挿入されます。ターゲット・ポート (この場合はポート873) に対し、設定を超えて受信接続が発生した場合は、その接続から送られてくるパケットは、この特別なチェーンに転送されます。このことにより、すでに確立された接続で送受信されるパケットには影響を与えることなく、新たな受信接続を制限することができます。

tcplimitが解除された場合、INPUTルールおよび付随したチェーンは削除されます。このような機能は、十分なテストを受けた信頼性の高いスクリプトによってファイアウォールのルールを管理することの重要性を際立たせるものです。ipblockと同様、カーネル内に適切なiptables機能が組み込まれている限り、tcplimitのスクリプトはあらゆるタイプのファイアウォールに対して、またファイアウォールがまったくない場合にも使用できる筈です。


host-tcplimit

host-tcplimitはtcplimitにきわめてよく似ていますが、特定のIPアドレスからの新たなTCP受信接続や、サーバー内の特定のTCPポートへの接続を制限します。host-tcplimitは、特定のユーザーによるネットワーク・リソースの乱用を防ぐ場合に特に有用です。例えば、CVSサーバーを使用していたとします。そして、10分ごとにソースとリポジトリの更新を行うスクリプトを新入りの開発者が設定したために、一日中莫大なネットワーク・リソースを無駄に使っているらしいことに気づいたとします。その新入りの開発者に、彼のやり方の間違いを説明するためe-mailを作成している矢先、以下のようなメールを受けとりました。

皆さん、
この開発プロジェクトに参加して、刺激的な毎日を送らせていただいています。
今、自分のマシンにあるコードのローカル・コピーを、10分ごとに最新のレベル
にするスクリプトを設定したところです。今から2週間のクルーズ旅行に出かけますが、
戻ってきた時には、ぼくのソースは完璧に最新の状態で、すぐにお手伝いできると思います。
もう、出かけなくては。それでは2週間後に。
新入りより

このような場合、簡単なhost-tcplimitコマンドによって問題を解決することができます。

#host-tcplimit 1.1.1.1 2401 1 day on

これで「新入り君」 (IPアドレス1.1.1.1) は、1日に1回のCVS接続 (ポート2401) に制限されるため、ネットワークの帯域幅を大幅に節約できます。


user-outblock

最後に、私のダイナミック・ファイアウォール・スクリプトのなかで、おそらく最も興味深いと思われるuser-outblockについて説明します。このスクリプトは、特定のユーザーにtelnetやsshの使用を許可する一方で、そのユーザーによるコマンドラインからの新しい送信接続の確立を阻止します。user-outblockの使用例をここに紹介します。私が勤務しているISPのアカウントを持っている家族がいるとします。両親は、グラフィカルe-mailクライアントによって、メールを読んだり、またときどきネット・サーフィンをしています。しかし、その息子はハッカーのようなことをしていて、自分のシェル・アクセスを使って他人のコンピューターにいたずらをします。

ある日、この息子はパキスタン軍のシステムに対してssh接続を行いました。さあ、大変です。あなたは、この息子に危険な行動をとらせないようにするために、次のことを行ってください。

まず、あなたのシステムを調べて、sshのようなsuidビットを、すべてのネットワーク・バイナリから削除します。

#chmod u-s /usr/bin/ssh

これで、彼がネットワークと通信するために使おうとするどのプロセスも、彼のUIDによって所有されるようになります。これで、このUID (2049とします) によって開始されるTCP送信接続は、すべてuser-outblockによってブロックすることができます。

#user-outblock 2049 on
UID 2049 block on.

彼は、ログインしてメールを読むことができますが、あなたのサーバーを使用してssh接続などを行うことはできません。彼はまた、自分のPCにsshクライアントをインストールすることができますが、彼のPCをWebやメール、およびssh送信接続 (あなたのサーバーに対してのみ) に制限するダイナミック・ファイアウォール・スクリプトの作成は簡単にできます。

参考文献

  • これらのダイナミック・ファイアウォール・スクリプトはきわめて有用であるため、1つの tarball (dynfw-1.0.tar.gz) にまとめ、ダウンロードできるようにしました。

    インストールの際には、このtarballを抽出してその中のinstall.shスクリプトを実行してください。このスクリプトによって、/usr/local/share/dynfw.shに対して共有bashスクリプトがインストールされ、また、/usr/local/sbinに対してダイナミック・ファイアウォール・スクリプトがインストールされます。これらを /usr/shareあるいは /usr/sbinにインストールする場合には、以下を入力してinstall.shを実行してください。

    # export PREFIX=/usr

    さらに、Gentoo Linux Webサイトに ダイナミック・ファイアウォール・スクリプトのセクション を追加しましたので、そちらからtarballの最新版をご利用ください。これからも、改良、追加を通して、システム管理者のための世界規模でのリソースの提供を続けていきたいと考えています。カーネルの中のiptablesをこれから大いに活用しましょう!
  • tcpdumpは、低位のパケット交換を調査してファイアウォールが正常に動作していることを確認するための重要なツールです。お持ちでない場合には、手に入れてください。そして、是非お使いください! :)
  • ネットフィルター・チームのためのホームページ にアクセスして、iptablesソースをはじめとするたくさんのリソースや、Rustyの優れた 「unreliable guides」 を利用してください。これらには、ネットワーキングの基本的な概念に関する「HOWTO」、ネットフィルター (iptables) の「HOWTO」、NATの「HOWTO」、ディベロッパーのためのネットフィルター・ハッキングの「HOWTO」が含まれています。また、 ネットフィルターFAQ その他も利用できます。
  • 幸い、ネットフィルターに関して、オンラインの優れた参考文献が数多くあります。しかし、基本的なことを忘れてはいけません。iptablesマニュアル・ページはとても詳しく、マニュアル・ページの模範となるものです。
  • 「Advanced Linux Routing and Traffic Control HOWTO」 が現在利用可能です。iptablesによってパケットをマークする方法、また、これらのマークに基づいたパケットをLinuxのルーティング機能によってルートする方法を示しているセクションがあります。
  • ネットフィルター (iptables) メーリングリスト および ネットフィルター・ディベロッパー が利用可能です。これらのURL上のメーリングリスト・アーカイブにもアクセスできます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=228241
ArticleTitle=共通テーマ:iptablesダイナミック・ファイアウォール
publish-date=04012001