訳: 佐伯 隆司 <[email protected]>
. 11 November
1996.
ファイアウォールは、 インターネットに参加している人はもちろんのこと、 プライベートネットワークのセキュリティ向上のための アプリケーションを 探している人にとっても、 ますます興味深くなりつつある分野です。 このセクションではファイアウォールとは何か、 ファイアウォールの使用法、 そしてファイアウォールを構築するために FreeBSD のカーネルで 提供されているファシリティ (機能) の使用法について説明したいと思います。
注意: 社内のネットワークと “巨大かつ信頼のおけない インターネット”との間にファイアウォールを構築することで セキュリティ上のすべての問題が解決できると考える人がいます。 ファイアウォールはセキュリティ上の問題を 解決する助けになる場合もありますが、 充分な設定がなされていないファイアウォールは、 まったくファイアウォールを 持たない場合よりもセキュリティ上の危険を増大させてしまいます。 ファイアウォールにできることは、 あなたのシステムにもう一つのセキュリティ層を 追加することだけで、 本気でアタックをしかけてくるクラッカーが内部ネットワークに 侵入するのを妨げることはできません。 ファイアウォールを侵入不可能と過信して 内部のセキュリティをおろそかにすることは、 単にクラッカーの仕事を少し簡単にするだけでしか ありません。
現在インターネットで普通に使用されている ファイアウォールには 二つの異なるタイプがあります。一つは、 厳密には パケットフィルタリングルータ と 呼ばれるタイプのものです。これはマルチホームのホストマシン (複数の ネットワークに接続されているマシン) のカーネルが、 ある規則にしたがって パケットを転送したりブロックしたりするものです。もう一つは、 proxy (代理) サーバ として知られているタイプのものです。これは、 おそらくはマルチホームのホストマシン上で、 カーネルによるパケット転送を 禁止して、 デーモンにより認証の提供とパケットの転送とを おこなうものです。
二つのタイプのファイアウォールを組み合わせて使用して、 特定のマシン (要塞ホスト と呼ばれる) だけが パケットフィルタリングルータを通して内部ネットワークへ パケットを送ることができるよう設定している サイトがしばしば存在します。proxy (代理) サービスは通常の認証機構よりもセキュリティを 強化してある 要塞ホストで動作させます。
FreeBSD は (IPFW として知られる) カーネルパケットフィルタ込みで提供されています。 この節の残りでは、このフィルタについて集中して説明します。 サードパーティから提供されるソフトウェアを使用することにより、 Proxy サーバを FreeBSD 上に構築することができます。 しかし、現在入手可能な proxy サーバはたいへんバラエティに富んでいるので、 この節でそれらすべてをカバーすることはできません。
ルータとは、二つまたはそれ以上のネットワークの間で パケットの転送をおこなう マシンのことです。 パケットフィルタリングルータは、そのカーネルの内部に、 一つ一つのパケットをルールリストと比較して 転送するかしないかを決める 特別なコードを持っています。 最近の IP ルーティングソフトウェアのほとんどは、内部に パケットのフィルタリングをおこなうためのコードを持っていて、 デフォルトでは すべてのパケットを転送するようになっています。 このフィルタを有効にするためには、 パケットの通過を許すべきかどうかを決める ルールを自分で定義する必要があります。
パケットを通すべきか通すべきでないかを決めるために、 パケットヘッダの内容にマッチするものが ルールリストから探されます。マッチするルールが見つかると、 ルールアクションが実行されます。ルールアクションには、 パケットを捨てる、パケットを転送する、 またはパケットの発信元に ICMP メッセージを送り返すというものがあります。 ルールの検索は先頭から順番におこなわれ、 通常は最初にマッチしたものだけが 適用されます。そのため、 このルールリストは“ルールチェーン” と呼ばれることもあります。
パケットマッチングの基準は使用するソフトウェアに よって異なりますが、通常はパケットの発信元 IP アドレス、 宛先 IP アドレス、発信元ポート番号、宛先ポート番号 (ポート番号はポートをサポートするプロトコルの場合のみ)、 パケットタイプ (UDP, TCP, ICMP など) に基づくルールを指定することができます。
Proxy サーバとは通常のシステムデーモン (telnetd, ftpd など) を 特別なサーバで置き換えたマシンのことです。 これらのサーバは、 通常は中継をおこなって特定方向への接続だけを許すため、 proxy サーバ と呼ばれます。(たとえば) proxy telnet サーバをファイアウォールホストで走らせておきます。 外部からユーザがファイアウォールに対して telnet を実行すると、proxy telnet サーバが応答して、 何らかの認証機構を実行します。これを通過した後で、 内部ネットワークへのアクセスがおこなえるように なるのです。 (内部ネットワークからの信号は proxy サーバがかわりに受け取り、外へ向けて送り出します)。
Proxy サーバは通常、 普通のサーバより堅固に構築されていて、しばしば “使い捨て”パスワードシステムなどを含む、 多様な認証機構を持っています。 “使い捨て”パスワードシステムとは、 どういうものなのでしょうか。仮に誰かが何らかの方法で、 あなたが使用したパスワードを手に入れたとします。しかし、 一度使用したことで、 そのパスワードは既に無効になっているのです。ですから、 そのパスワードをもう一度使用したとしても、あなたのシステムへ アクセスすることはできないというわけです。 これらのサーバは中継をおこなうだけで、 実際のところサーバホスト自身への アクセスをユーザに許してはいません。そのため、 何者かがセキュリティシステムに 侵入用の裏口を取り付けることは、 より困難になっています。
proxy サーバはアクセス制限の方法をいくつも持っていて、 特定のホスト だけがサーバへのアクセス権を得ることができるように なっていることがあります。 そして目的のマシンと通信できるユーザを制限するように 設定することもできます。もう一度言いますが、 どんなファシリティ (機能) が使えるかは、どんな proxy サービスをおこなうソフトウェアを選ぶかに大きく 依存します。
FreeBSD とともに配布されている IPFW は、 カーネル内部にあってパケットのフィルタリングとアカウンティングをおこなうシステムであり、 ユーザ側のコントロールユーティリティである ipfw(8) を含んでいます。 ルーティングの決定をおこなう際に、これらは互いに協力して、 カーネルで使用されるルールを定義したり、 現在使用されているルールを問い合わせたりすることができます。
IPFW は互いに関連する二つの部分からなっています。 ファイアウォールセクションは パケットフィルタリングをおこないます。また、IP アカウンティングセクションはファイアウォールセクションのものと 似たルールに基づいてルータの使用を追跡します。これにより、 (たとえば) 特定のマシンからルータへのトラフィックがどのくらい 発生しているか調べたり、どれだけの WWW (World Wide Web) トラフィックが フォワードされているかを知ることができます。
IPFW は、 ルータではないマシンにおいても入出力コネクションの パケットフィルタリングのために使用することができるように設計されています。 これは一般的な IPFW の使用法とは異なる特別な使い方ですが、 こういった状況でも同じコマンドとテクニックが使用されます。
IPFW システムの中心となる部分はカーネル内部にあります。 そのため、どのファシリティ (機能) を必要とするかによって、 1 つまたは複数のオプションをカーネルコンフィグレーションファイルに追加し、 カーネルを再コンパイルする必要があるでしょう。 カーネルの再コンパイル方法の詳細については、 「カーネルのコンフィグレーション」(第9章) をご覧ください。
現在、IPFW に関係するカーネルコンフィグレーションオプションは 三つあります。
パケットフィルタリングのためのコードを カーネルに組み込みます。
syslogd(8) を通じて パケットのログを取るためのコードを有効にします。 フィルタルールでパケットのログを取るように指定しても、 このオプションが指定されていなければ、 ログを取ることはできません。
syslogd(8) を通じて ログを取るパケットの数をエントリ毎に制限します。 敵対的な環境においてファイアウォールの 動作のログを取りたいけれど、 syslog の洪水によるサービス拒絶攻撃に対し 無防備でありたくないという場合に、 このオプションを使用したいと思うことが あるかもしれません。
チェーンエントリのログが指定された制限数に達すると、 そのエントリに関するログ取りは停止されます。 ログ取りを再開するには、ipfw(8) ユーティリティを使用して 関連するカウンタをリセットする必要があります。
# ipfw zero 4500
4500 とは、 ログ取りを続行したいチェーンエントリの番号です。
注意: 以前のバージョンの FreeBSD は IPFIREWALL_ACCT というオプションを 持っていました。しかし、 ファイアウォールコードがアカウンティングファシリティ (機能) を 自動的に含むようになったため、 現在では使用されることはなくなっています。
IPFW ソフトウェアの設定は ipfw(8) ユーティリティを通じておこないます。 このコマンドの構文は非常に複雑に見えますが、 一旦その構造を理解すれば比較的単純です。
このユーティリティでは今のところ四つの異なる コマンドカテゴリが 使用されています: それは追加 / 削除、表示、 フラッシュ、およびクリアです。追加 / 削除はパケットの受け入れ、拒絶、ログ取りをどのようにおこなうか というルールを構築するのに使用します。表示はルールリスト (またはチェーン) と (アカウンティング用) パケットカウンタの 内容を調べるのに使用します。 フラッシュはチェーンからすべてのエントリを 取り除くのに使用します。 クリアは一つまたはそれ以上のアカウンティングエントリを ゼロにするのに 使用します。
この形式での使用法は:
ipfw [-N] コマンド [index] アクション [log] プロトコル アドレス [オプション]
この形式で使用する際に有効なフラグは一つだけです。
アドレスやサービス名を 文字列に変換して表示します。
コマンド は一意である限り短縮可能です。有効な コマンド は
ファイアウォール / アカウンティングルールリストに エントリを追加します。
ファイアウォール / アカウンティングルールリストから エントリを削除します。
以前のバージョンの IPFW では、 ファイアウォールエントリと パケットアカウンティングエントリが別々に利用されていました。 現在のバージョンでは、それぞれのファイアウォールエントリ毎に パケットアカウンティングエントリが備えられています。
index 値が指定されていると、 エントリはチェーン中の指示された位置に置かれます。 index 値が指定されて いなければ、 エントリは (65535 番のデフォルトルールである パケット拒絶を別にして) 最後のチェーンエントリの index に 100 を足した 位置 (チェーンの最後) に置かれます。
カーネルが IPFIREWALL_VERBOSE つきでコンパイルされている場合、log オプションはマッチしたルールを システムコンソールに出力させます。
有効な アクション は:
パケットを捨てます。ICMP ホスト / ポート到達不能パケットを (適切な方を) 発信元へ送ります。
通常通りパケットを通過させます。(別名: pass および accept)
パケットを捨てます。発信元は ICMP メッセージによる 通知を受けません (そのためパケットが 宛先に到達しなかったように見えます)。
このルールはパケットカウンタを更新するだけで、 パケットを 通過させたり拒絶したりしません。 検索は次のチェーンエントリから続けられます。
それぞれの アクション は一意な先頭部分だけでも認識されます。
指定可能な プロトコル は以下の通りです。
任意の IP パケットにマッチします。
ICMP パケットにマッチします。
TCP パケットにマッチします。
UDP パケットにマッチします。
アドレス の指定は:
from address/mask [port] to address/mask [port] [via interface]
port はポートをサポートする プロトコル (UDP と TCP) の 場合にだけ指定可能です。
via
は必須ではなく、
特定のインタフェースを通ってきたパケット だけにマッチするように、IP
アドレスまたはローカル IP インタフェースの ドメイン名、またはインタフェース名
(たとえば ed0) を 指定することができます。
インタフェースユニット番号はオプションで、 ワイルドカードで指定することが
できます。たとえば、 ppp* はすべてのカーネル PPP
インタフェースに マッチします。
address/mask の指定は:
addressまたは
address/mask-bitsまたは
address:mask-pattern
IP アドレスのかわりに有効なホスト名を指定することも可能です。 mask-bits
はアドレスマスクで上位何ビットを1にするべきかを
示す十進数値です。たとえば次の指定、 192.216.222.1/24
はクラス C のサブネット (この場合 192.216.222)
の任意のアドレスにマッチするマスクを作成します。 mask-pattern
は与えられたアドレスと 論理 AND
される IP アドレスです。 キーワード any は“任意の IP
アドレス”を指定するために 使用することができます。
ブロックするポート番号は以下のように指定します:
port [, port [, port [… ]]]
のように単独のポートまたはポートのリストを指定します。 またはport- port
のようにポートの範囲を指定します。 単独のポートとポートのリストを 組み合わせて指定することも可能ですが、 その場合は常に範囲の方を 最初に指定しなければなりません。使用可能な オプション は:
データグラムの最初の フラグメントでなければマッチします。
入力途中のパケットであればマッチします。
出力途中のパケットであればマッチします。
IP ヘッダが spec に指定された カンマで区切られた オプションのリストを含んでいればマッチします。 サポートされている IP オプションのリストは: ssrr (ストリクトソースルート)、 lsrr (ルーズソースルート)、 rr (レコードパケットルート)、 そして ts (タイムスタンプ) です。 特定のオプションを含まないことを指定するには ! を先頭につけます。
パケットが既に確立されている TCP コネクションの一部であれば (つまり RST または ACK ビットがセットされていれば) マッチします。 established ルールをチェーンの最初の方に置くことで、 ファイアウォールのパフォーマンスを向上させることが できます。
パケットが TCP コネクションを確立しようとするものであれば (SYN ビットがセットされ ACK ビットはセットされていなければ) マッチします。
TCP ヘッダが flags に指定された カンマで区切られたフラグの リストを含んでいればマッチします。 サポートされているフラグは、fin, syn, rst, psh, ack と urg です。 特定のフラグを含まないことを指定するには ! を先頭につけます。
ICMP タイプが types リストに 存在していればマッチします。 リストはタイプの範囲または個々のタイプを カンマで区切った任意の組合せで指定できます。 一般的に使用されている ICMP タイプは: 0 エコーリプライ (ping リプライ)、 3 相手先到達不可能、 5 リダイレクト、 8 エコーリクエスト (ping リクエスト)、そして 11 時間超過 (traceroute(8) で使用されているように、TTL 満了を示すのに使用されます) です。
この形式での使用法は:
ipfw [-a] [-t] [-N] l
この形式で使用する際に有効なフラグは三つあります。
リスト表示の際にカウンタの値も表示します。 このオプションは アカウンティングカウンタの 内容を見る唯一の手段です。
各チェーンエントリが最後に マッチした時刻を表示します。この時刻表示は ipfw(8) ユーティリティで使用される入力形式と 互換性がありません。
(可能であれば) アドレスやサービス名を文字列に変換して表示します。
チェーンをフラッシュするには:
ipfw flush
カーネルに固定されているデフォルトルール (インデックス 65535 番) 以外の、 ファイアウォールチェーンの中のすべてのエントリを削除します。 デフォルトではすべてのパケットが拒絶されるので、 一旦これを実行すると、 パケットを許可するエントリがチェーンに追加されるまで、 あなたのシステムがネットワークから切り放されてしまいます。 そのため、 ルールのフラッシュをおこなうときは注意が必要です。
一つまたはそれ以上のパケットカウンタをクリアするためには:
ipfw zero [index]
index が指定されていなければ、 すべてのパケットカウンタが クリアされます。 index が指定されていれば、 特定のチェーンエントリだけが クリアされます。
このコマンドは、ホスト evil.crackers.org から ホスト nice.people.org の telnet ポートへの すべてのパケットを拒絶します。
# ipfw add deny tcp from evil.crackers.org to nice.people.org 23
次の例は、ネットワーク crackers.org (クラス C) 全体から マシン nice.people.org (の任意のポート) への 任意の TCP トラフィックを拒絶し、 ログを取ります。
# ipfw add deny log tcp from evil.crackers.org/24 to nice.people.org
あなたの内部ネットワーク (クラス C のサブネット) に対する X セッションを 張れないようにする場合、 以下のコマンドで必要なフィルタリングがおこなえます。
# ipfw add deny tcp from any to my.org/28 6000 setup
アカウンティングレコードを見るには:
# ipfw -a listまたは短縮形式で
# ipfw -a l
最後にチェーンエントリがマッチした 時刻を見ることもできます。
# ipfw -at l
注意: 以下の提案は、ただの提案にすぎません: 必要な処理はそれぞれのファイアウォールで異なるため、 あなた独自の要求にあったファイアウォールを構築する方法を ここで述べることはできないのです。
最初にファイアウォールをセットアップするとき、 コントロールされた環境でファイアウォールホストの 設定がおこなえるような テストベンチセットアップが用意できない場合には、 カーネルのログ取りを 有効にしてログ取り版のコマンドを使用することを 強くおすすめします。そうすることで、 大した混乱や中断なしに問題となる範囲の特定と処置を 素早くおこなうことができます。 初期セットアップフェーズが完了してからであっても、 アタックの可能性のあるアクセスをトレースしたり、 要求の変化に応じてファイアウォールルールを 変更したりできるので、`deny' に対するログ取りをおこなうことをおすすめします。
注意: accept コマンドでログを取っていると、 ファイアウォールをパケットが一つ通過する毎に 1 行のログが生成されるため 大量の ログデータが発生します。そのため、大規模な FTP/HTTP 転送などをおこなうと、システムが非常に 遅くなってしまいます。 また、パケットが通過するまでにカーネルにより 多くの仕事を要求するため、パケットのレイテンシ (latency) を増加させてしまいます。syslogd もログをディスクに記録するなど、より多くの CPU タイムを 使用し始め、実に容易に /var/log が置かれているパーティションを溢れさせてしまう可能性があります。
ファイアウォールは、 /etc/rc.conf.local か、もしくは /etc/rc.conf によって有効化されるべきです。 関連マニュアルページには、どのドアノブ (訳注: ポートや IP アドレスなど、 ネットワークからの入口を示すもののこと) に手をつければ良いのかに ついての説明と、ファイアウォール設定の既定値のリストがあります。 もし、設定の既定値を使わない場合には、 ipfw list とすることで、 現在のルールセットを rc.conf から読み込める形で ファイルに出力できます。 また、/etc/rc.conf.local や /etc/rc.conf によってファイアウォールを有効化しない場合には、 すべての IP インタフェースが設定されるよりも前に、 確実にファイアウォールの有効化が行なわれるようにすることが重要です。
次の問題は、ファイアウォールが実際には何を する べきかです ! これは外部からそのネットワークへのどんなアクセスを許したいか、 また内部から外界へのアクセスを どのくらい許したいかに大きく依存します。 いくつか一般的なルールを挙げると:
1024 番以下のポートへのすべての TCP 入力アクセスをブロックします。ここは finger, SMTP (mail) そして telnet など、最もセキュリティに敏感な サービスが存在する場所だからです。
すべての 入力 UDP トラフィックをブロックします。これは UDP を使用しているサービスで有用なものは極めて少ないうえ、 (Sun の RPC と NFS プロトコルのように) 有用なトラフィックであったとしても、 通常セキュリティに対する脅威となるためです。UDP はコネクションレスプロトコルであるため、入力 UDP トラフィックを拒絶することは すなわち出力 UDP トラフィックに対する返答をも ブロックすることになるので、 このことはそれなりの不利益をもたらします。たとえば外部の archie (prospero) サーバを使用している (内部の) ユーザに とって問題となる可能性があります。もし archie へのアクセスを許したければ、191 番と 1525 番のポートから 任意の UDP ポートへ来るパケットがファイアウォールを通過することを 許可しなければなりません。123 番のポートから来るパケットは ntp パケットで、 これも通過の許可を考慮する必要がある もう一つのサービスです。
外部から 6000 番のポートへのトラフィックをブロックします。6000 番のポートは X11 サーバへのアクセスに使用されるポートで、 セキュリティに対する脅威となりえます。 (特に自分のワークステーションで xhost + をおこなう癖を持っている人がいればなおさらです)。X11 は実際に 6000 番以降のポートを使用する可能性があるため、 通過許可に 上限を定めると、 そのマシンで走らせることのできる X ディスプレイの 個数が制限されます。RFC 1700 (Assigned Numbers) で定義されているように、上限は 6063 です。
内部のサーバ (たとえば SQL サーバなど) がどのポートを使用するかを チェックします。 それらのポートは通常、上で指定した 1-1024 番の範囲から外れていますので、 これらも同様にブロックしておくことは おそらく良い考えです。
これとは別のファイアウォール設定に 関するチェックリストが CERT から 入手可能です。http://www.cert.org/tech_tips/packet_filtering.html
前にも述べたように、これはただの ガイドライン にすぎません。 ファイアウォールでどのようなフィルタルールを使用するかは、 あなた自身が 決めなければなりません。 これまでのアドバイスに従ったにも関わらず、 誰かがあなたのネットワークに 侵入してきたとしても、 わたしたちは「いかなる」責任もとることはできません。
多くの人が IPFW がどのくらいのオーバヘッドをシステムに加えるかを知りたがっています。 この答えは、使っているルールセットとプロセッサのスピードによってほぼ決まります。 イーサネットを使っていてルールセットが少ないアプリケーションにとって答えは、 “その影響は無視できる程度” です。 実際の測定値を見ないと満足できない方は、引き続きお読みください。
次の測定は 486-66 (訳注: Intel 社製 CPU i486, 66MHz のこと) 上で 2.2.5-STABLE を使用して行なわれました (IPFW はその後の FreeBSD のリリースで多少変更されていますが、 現在も同程度の速度で動きます)。IPFW には、 ip_fw_chk ルーチン内でかかる時間を測定して、 1000 パケット毎に結果をコンソールに表示する変更が加えられています。
それぞれ 1000 ずつのルールからなる 2 つのルールセットでテストが行なわれました。 1 つ目のルールセットは最悪のケースを見るために、 次のルールを繰り返しています。
# ipfw add deny tcp from any to any 55555
これは、最終的にパケットが (ポート番号から) ルールにマッチしないことがわかるまでに IPFW のほとんどのパケットチェックルーチンが実行されるような、 最悪の場合を示します。このルールを 999 個繰り返し並べた後に allow ip from any to any がきます。
2 つ目のルールセットは、 なるべく早く確認が終了するように書かれたものです。
# ipfw add deny ip from 1.2.3.4 to 1.2.3.4
このルールでは、発信元の IP アドレスが一致しないので、 すぐに確認が終わります。前とおなじように、1000 個目のルールは allow ip from any to any です。
前者のパケットあたりのオーバヘッドはおよそ 2.703�ms/packet または 1 つのルールにつき 2.7�マイクロ秒です。したがって、 このルールにおけるパケット処理時間の理論的な限界は、 毎秒約 370�パケットです。10�Mbps の Ethernet で 1500�バイト程度のパケットサイズを仮定すると、 バンド幅の利用効率は 55.5% が限界です。
後者では、それぞれのパケットがおよそ 1.172�ms または、1 つのルールにつき 1.2�マイクロ秒で処理されていました。 パケット処理時間の理論的な限界は、 毎秒約 853�パケットとなりますので、10�Mbps Ethernet のバンド幅を使い切ることができます。
このテストに使われたルールの数が多過ぎることと、 その性質から、これは実際の状況を反映したものではありません。 これらは上に示したタイミング情報を出すためだけに用いられたものです。 効率の良いルールセットを作るためには、 次のような事を考えればよいでしょう。
established ルールは TCP トラフィックの大半を処理するため、 先頭の方に持ってきてください。このルールの前には allow tcp という記述を置かないでください。
良く使われるルールを、 あまり良く使われないルールよりも前の方に (もちろんファイアウォールの許可設定を変えない範囲で) 持ってきてください。ipfw -a l でパケット数の統計を取ることで、 どのルールが最もよく使われているかを調べられます。
本文書、および他の文書は ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/ からダウンロードできます。
FreeBSD に関する質問がある場合には、ドキュメント を読んだ上で <[email protected]> まで (英語で)
連絡してください。
本文書に関する質問については、<[email protected]> まで電子メールを (英語で)
送ってください。