スポンサーリンク

FIREWALL(7) FreeBSD 多方面の情報マニュアル FIREWALL(7)

名称

firewall − FreeBSD で動作する簡単なファイアウォール

ファイアウォールの基礎

ファイアウォールは一般に、外部から行われるネットワーク内部への不正なアク セスを防ぐために使われます。また、LAN 内だけでサービスされるべき NFS や SMBFS のようなサービスに対して、内部の IP アドレスを偽装して外部から行わ れる攻撃を防ぐためにも用いられます。

また、 FreeBSD のファイアウォール機構は、 dummynet(4) を用いた帯域制限を 行うこともできます。この機能は特に重要な目的のために帯域幅を保証したい場 合などに有効でしょう。たとえば、オフィスの T1 (1.5MBits/s) を用いてビデオ 会議を行う場合に、他の通信を 1MBits/s までに押えて、ビデオ会議用のコネク ションに最低でも 0.5MBits/s を確保することができます。また同様に、共用機 器で有名なウェブサイトや FTP サイトを運用している場合には、プロバイダから の高額な帯域課金を避けるために使うこともできます。

それから、 FreeBSD のファイアウォール機構はパケットが正しい到達先に行くよ うにパケットを divert したり、次のホップのアドレスを変更したりすることも できます。パケットの divert は主に、プライベート IP アドレス空間から外部 へのブラウズなどのアクセスを可能にする NAT (ネットワークアドレス変換) を 実現するために用いられます。

ファイアウォールを構築することは簡単なようですが、多くの人が間違いを犯し ています。最も多い間違いは、包括的なファイアウォールでなく、排他的なファ イアウォールを作ってしまうことです。排他的なファイアウォールは、ルール セットに適合しなかったすべてのパケットを通過させるもので、包括的なファイ アウォールはルールセットにマッチしたパケットだけを通過させます。包括的な ファイアウォールのほうが、排他的なものよりもはるかに安全ですが、正しく動 くものを作るのが難しくなります。次に多い間違いは、通過させたくないものす べてを廃棄してしまうことです。TCP/IP が正常に動作するためには、たとえば MTU ディスカバリの実装のように、いくつかの ICMP エラーを必要とします。同 様に、多くのデーモンは、コネクションを要求するユーザを認証するために、 auth サービスに逆向きのコネクションを張ります。auth は危険ですが、正しい 対応はただパケットを廃棄するのでなく、TCP reset を返すようにすることで す。以下で示す、ファイアウォールのサンプルではこれらの事項を満たすように してあります。

IPFW を使うためのカーネルの設定

IP ファイアウォールの機能を使用するためには、カスタムカーネルを作成する必 要はありません。 /etc/rc.conf (後述) でファイアウォールを有効にすれば、 ipfw カーネルモジュールが必要な時に自動的にロードされます。あなたが偏執し たいならば、 IPFIREWALL オプションを設定することで、IPFW を直接 FreeBSD カーネルに組み込むこともできます。このファイアウォールは、何も設定しない とすべてのパケットを通過させないようになっています。 /etc/rc.conf で、再 起動時に適切なルールセットを読み込むようになっていないと、コンソールに触 ることができない場合、マシンにアクセスすらできなくなります。また、新しい リリースのカーネルに更新する時に、バイナリ (訳注: コマンドやライブラリの こと) を更新する前にリブートを実行してしまうことがよくあります。この結果 ipfw(8) とカーネルが非互換になってしまい、ブートシーケンスで ipfw(8) が動 作しないことにより、マシンにアクセスできなくなってしまいます。このため に、 IPFIREWALL_DEFAULT_TO_ACCEPT というカーネルオプションが用意されてお り、これによってファイアウォールの初期状態をすべてのパケットを通過させる 設定にすることができます。しかし、このオプションを設定することは、システ ムブート中の短期間、ファイアウォールが全パケットを通すかもしれないことに 注意してください。それでも本オプションの使用は、 FreeBSD ファイアウォール に十分慣れるまでの期間には有用です。どのように動作するかすべて分かった ら、これを削除して、抜け穴を塞いてください。第 3 のオプションとして、 IPDIVERT があります。これは、ファイアウォールがパケットをユーザプログラム に divert することができるようにするもので、 natd(8) によって、プライベー トネットワークから外部へアクセスできるようにするときに必要です。トラ フィックタイプによる帯域制限には、 ipfw pipe ルールを有効にするために、 DUMMYNET オプションが必要です。

IPFW によるファイアウォールの例

ここに示すのは、3 つのインタフェースカードをもつマシンで動作している ipfw ベースのファイアウォールの例です。 fxp0 が「外側の」LAN に接続されていま す。この LAN 上のマシンは、10. で始まる内部 IP アドレスと、インターネット にルーティングされる IP アドレスを持ち、デュアルホームとなっています。た とえば、 192.100.5.x がインターネットにルーティングされる IP ブロックを指 し、 10.x.x.x が内部ネットワークを指します。例として適切ではないかもしれ ませんが、 10.0.1.x が fxp0 の接続されている LAN のアドレス、 10.0.2.x が fxp1 の接続されている LAN のアドレス、そして 10.0.3.x が fxp2 のものであ るとします。

この例では、3 つの LAN すべてをインターネットから隔離し、またそれぞれをも 隔離したいものとします。同時に、すべての内部アドレスから、このマシンで 走っている NAT ゲートウェイを経由してインターネットへアクセスが可能である ようにします。NAT ゲートウェイを動作させるためには、fxp0 に内部アドレスの 10. のほかに、インターネットから見えるアドレスを持たせる必要があります。 このアドレス (ここでは示していません) が、このマシンの公式なアドレスであ り、もうひとつの外部から見えるアドレス (この例では 192.100.5.5 です) が NAT ゲートウェイとしてのアドレスとなります。この例は、外部から見える LAN のマシンにも内部アドレス 10.0.0.x を割り当てることによって、すこし複雑に なっています。しかしこの方法によって、内部サービスは内部アドレスにのみバ インドし、インターネットから守れます。外から見える IP アドレスにバインド するサービスは、インターネットに対して公開しようとするものだけにするので す。

この例では、ネットワーク 10.0.0.x はファイアウォールによって保護されてい ません。このネットワークを外部からのアドレス偽装から守るために、インター ネットルータによる保護を確認して下さい。また例では、外部から見えるホスト が内部 IP アドレスを通じてサービスを操作する場合、内部のネットワークに非 常に自由にアクセス可能としています。この方法にはいくらかのセキュリティ上 の危険が伴っており、外部から見えるホストに問題がある場合には何が起きるか わかりません。この危険を回避するためには、ルール 01010 と 01011 を削除し て、 LAN0 経由で入ってくるものすべてを firewall を経由するようにするべき です。

また、この例では内部アドレス空間を使うことがファイアウォールによる保護機 構の重要な点であることに着目してください。適切なアドレス偽装対策を行うこ とにより、外部から、内部 (LAN1 および LAN2) のホストに直接アクセスするこ とは不可能となります。

# /etc/rc.conf
#
firewall_enable="YES"
firewall_type="/etc/ipfw.conf"

# ファイアウォールを通過する一時的なポート割り当ての範囲を設定
#
# 注意 : ファイアウォールを通じて行われるサービスの負荷が高い場合には、
# より広いポート割当の範囲を必要とすることになります。そのような際には
# 4000-10000 や 4000-30000 がより良い選択でしょう。
ip_portrange_first=4000
ip_portrange_last=5000
...
# /etc/ipfw.conf
#
# FIREWALL: ファイアウォール兼 NAT ゲートウェイ

# LAN0

10.0.0.X と 192.100.5.X (デュアルホーム)

# LAN1

10.0.1.X

# LAN2

10.0.2.X

# sw:

イーサネットスイッチ (管理対象外)

#
# 192.100.5.x は、インターネットから見える IP アドレス (インターネットから
# ルーティングされる) を意味します。10.x.x.x は、内部 IP アドレス
# (外からは見えない) を表します。
#
# [LAN1]
# ^
# |
# FIREWALL -->[LAN2]
# |
# [LAN0]
# |
# +--> 外側のホスト A
# +--> 外側のホスト B
# +--> 外側のホスト C
# |
# インターネットルータ (2 番目のファイアウォール)
# |
# [インターネット]
#
# 注意! ここには書かれていませんが、インターネットルータは発信元アドレスが
# 10. であるパケットを許可しないように設定される必要があります。
# これは、デュアルホームの 10.0.0.x ブロックを保護するためです。
# そうでなければ、外部から見えるホストは、この例では守られていません。
# これらのホストは、外部に見せるサービスのみを外部から見えるアドレスに
# バインドすべきです。内部サービスは、安全に内部アドレスにバインド可能です。
#
# NAT ゲートウェイは、内部の IP アドレスから外部の IP アドレスへ
# 向けて送られるパケットを、ポート 8668 で listen している natd に転送す
# ることによって動作します。この動作はルール 00300 によって指定されています。
# 外界から natd に返ってくるパケットも同様に、ルール 00301 によって natd に
# 送られます。この例で興味深いのは、外に見せているホストへの内部からの
# リクエストは、natd (ルール 00290) を通す必要がないということです。
# これは、外部に見せているホストも内部の 10. ネットワークのことがわかるので
# 可能であり、natd の負荷を軽減することができます。内部のトラフィックも
# natd を通す必要がありません。これらのホストは、内部の 10. ネットワークの
# ルーティングのことがわかるためです。
# /etc/rc.local からは、natd は以下のように起動されます。
# natd のカーネル組み込み型のバージョンである ipnat についても参照してく
# ださい。
#

#

natd -s -u -a 208.161.114.67

#
#
add 00290 skipto 1000 ip from 10.0.0.0/8 to 192.100.5.0/24
add 00300 divert 8668 ip from 10.0.0.0/8 to not 10.0.0.0/8
add 00301 divert 8668 ip from not 10.0.0.0/8 to 192.100.5.5

# 高い帯域のアクセスがルールセット全体を通過していくのを防ぐためのショート
# カットルールを設定します。すでに確立されている TCP コネクションはそのまま
# 通し、また外へ出るパケットも同様にします。ファイアウォールを通す
# のは入力パケットだけにします。
#
# 確立された TCP コネクションをそのまま通してしまうことは小さなセキュリティ
# ホールになりますが、ファイアウォールの過剰な負荷を避ける意味で必要
# になることもあります。もし心配ならばこのルールを、アドレス偽装チェック
# のうしろに移動することもできます。
#
add 01000 allow tcp from any to any established
add 01001 allow all from any to any out via fxp0
add 01001 allow all from any to any out via fxp1
add 01001 allow all from any to any out via fxp2

# アドレス偽装防止のルールです。これは、内部ネットワークのパケットを
# どれくらい信頼するかによって変わってきます。fxp1 を経由するパケットは必ず、
# 10.0.1.x からのものでなければなりません。fxp2 を経由するもの
# は 10.0.2.x からです。fxp0 を経由するものが LAN1 や LAN2 ブロックから
# のものであることもあり得ません。ここでは 10.0.0.x を保護することはでき
# ないので、ルータを適切に設定する必要があります。
#
add 01500 deny all from not 10.0.1.0/24 in via fxp1
add 01500 deny all from not 10.0.2.0/24 in via fxp2
add 01501 deny all from 10.0.1.0/24 in via fxp0
add 01501 deny all from 10.0.2.0/24 in via fxp0

# この例のルールセットでは、内部ホスト間には何の制約も設けていません。
# 外部から見える LAN 上のホストであっても、内部 IP アドレスを使用する
# 限りにおいてはそうです。これはセキュリティホールになる可能性があります
# (外部から見えるホストに何かがあったらどうなるでしょうか ?)。これら
# 3 つの LAN の間の通信を完全に制限したいのであれば、以下のふたつのルール
# を削除してください。
#
# LAN1 と LAN2 を孤立させて、しかし外部から見えるホスト間の自由なアクセスを
# 許したければ、ルール 01010 だけを削除して、01011 は残して下さい。
#
# (コメントアウトしてありますが、より制約の少ないファイアウォールにする
# 場合はこれらを有効にしてください)
#add 01010 allow all from 10.0.0.0/8 to 10.0.0.0/8
#add 01011 allow all from 192.100.5.0/24 to 192.100.5.0/24
#

# 特定の LAN からは特定のサービスへのアクセスを許可する場合
#
# より制約の強いファイアウォールを使う場合には、特定の LAN からファイア
# ウォール上で動作している特定のサービスにアクセスできるようにすることに
# なります。この例では、LAN1 がファイアウォール上で動いているファイル共有
# を必要とすると仮定します。もし、ルール 01010 が有効になっているような、
# 制約の緩いファイアウォールであればこれらのルールは不要です。
#
add 01012 allow tcp from 10.0.1.0/8 to 10.0.1.1 139
add 01012 allow udp from 10.0.1.0/8 to 10.0.1.1 137,138

# 内部と外部の LAN の横断を許可する一般的なサービス
#
# DNS 参照、ntalk, ntp といった特定の UDP サービスは通過させます。
# 内部サービスはアドレス偽装不可の内部アドレス (10. ネット) を持つことにより
# 保護されているので、これらのルールは外部から見える IP アドレスにバインド
# されているサービスに対してのみ意味を持ちます。また、UDP フラグメントは
# 許可する必要があります。そうしないと、フラグメントされるような大きな
# UDP パケットはファイアウォールを通過できません。
#
# DNS 参照に対する応答など、大きなポート番号を用いた一時的なサービスを
# 行う必要があるかもしれません。この例ではそのようなポート番号を
# 4000-65535 としています。外部から見える全マシンが一時ポートをこの
# 外部から見えるポートにバインドするように、/etc/rc.conf の変数で設定
# しています (上の、rc.conf の例を参照してください)。
#
add 02000 allow udp from any to any 4000-65535,domain,ntalk,ntp
add 02500 allow udp from any to any frag

# 同様のサービスを TCP についても許可します。ここでも、外部から見える
# アドレスにバインドするサービスにのみ適用されます。また、この例では
# ’auth’ を通過させていますが、実際には外部から見えるポートでは identd
# を動作させていません。これによって、auth 要求を受け取ったマシンは
# TCP RESET を発行します。パケットを捨ててしまうと、ident 参照を行ってくる
# サービスへの接続の遅延の原因となります。
#
# TCP フラグメントを許可していないことに注意して下さい。UDP 以外では、
# 一般にフラグメントを許さないのです。TCP の、MTU ディスカバリプロトコル
# が正しく動作して、TCP フラグメントが存在しないものと期待しています。
#
add 03000 allow tcp from any to any http,https
add 03000 allow tcp from any to any 4000-65535,ssh,smtp,domain,ntalk
add 03000 allow tcp from any to any auth,pop3,ftp,ftp-data

# いくつかのタイプの ICMP を通過させることは重要です。
# 一般形な ICMP タイプをここに列挙します。
# ICMP タイプ 3 を通過させることが重要であることに注意してください。
#

#

0

エコーリプライ

#

3

到達不能

#

4

始点抑制 (通常は許可されません)

#

5

リダイレクト (通常は許可されません。危険です !)

#

8

エコー

#

11

時間超過

#

12

パラメータ問題

#

13

タイムスタンプ

#

14

タイムスタンプリプライ

#
# 状況によってはタイプ 5 の ICMP リダイレクトパケットを許可しなければな
# らない場合がありますが、そのような場合にはインターネットルータでそれが
# 禁止されていることを確認して下さい。

add 04000 allow icmp from any to any icmptypes 0,3,8,11,12,13,14

# ここまで通って残ったフラグメントのログをとります。役にたつかもしれ
# ませんが、邪魔なだけかもしれません。最後の deny ルールは、カーネルの設定
# がどうであっても、ファイアウォールが包括的なものであることを保証する
# ものです。
#
add 05000 deny log ip from any to any frag
add 06000 deny all from any to any

内部向け、外部向けサービスのポートバインディング

マルチホームなホストで、サービスをどちらのアドレスにバインドするかという ことについて触れましたが、説明はしていません。複数の IP アドレスを持つホ ストでは、それぞれのサービスをすべての IP アドレスにバインドするのではな く、特定の IP アドレスやインタフェースにバインドすることが可能です。たと えばこの例のファイアウォールマシンには、インタフェースが 3 つあり、その 1 つには 2 つの外部から見える IP アドレスがあるので、このマシンには 5 つの IP アドレス (10.0.0.1, 10.0.1.1, 10.0.2.1, 192.100.5.5, 192.100.5.1) があ ることになります。Windows の LAN セグメント (LAN1 とします) に対してファ イル共有サービスを提供するのであれば、samba の ’bind interfaces’ という設 定項目で、LAN1 の IP アドレスにだけ samba をバインドできます。こうするこ とで、他の LAN セグメントではこのファイル共有サービスを利用できなくなりま す。また、LAN2 に UNIX エンジニアリングワークステーションがあれば、nfsd を 10.0.2.1 にバインドするように設定することで NFS でも同様のことができま す。どのサービスをどのようにバインドするかはほとんどの場合に指定できます し、またそれが指定できない場合には jail(8) を使うことによって、間接的にそ れを行うこともできます。

関連項目

ipnat(1), dummynet(4), ipnat(5), rc.conf(5), smb.conf(5) (ports/net/samba), samba(7) (ports/net/samba), config(8), ipfw(8), jail(8), natd(8), nfsd(8)

関連文書

ipf(5), ipf(8), ipfstat(8)

歴史

firewall マニュアルページは最初、 Matthew Dillon によって書かれ、2001 年 5 月に FreeBSD 4.3 ではじめて登場しました。

FreeBSD 10.0 May 26, 2001 FreeBSD 10.0

スポンサーリンク