ファイアウォールの設定(1)

作成:

前回、IPマスカレードの設定をしましたが、 その他の設定で自動的にファイアウォールが設定されてしまっているため、 そのままではFTPが使えませんでした。
そこで今回はファイアウォールの設定を解説したいと思います。
(後ほど説明しますが、実はファイアウォールの設定をいじらなくてもFTPは使えるようにできます。 しかし、サーバをたてることなどを考えるとこれらの設定は必ず行わなくてはならないので・・・)

rp-pppoeの実行で設定されるファイアウォール

rp-pppoeの設定でファイアウォールの設定をMASQUERADEと設定したと思います。
そのときの設定は/etc/ppp/pppoe.confにあります。
このファイルの中にある以下のような部分で設定されています。

# Firewalling: One of NONE, STANDALONE or MASQUERADE
FIREWALL=MASQUERADE

設定を変えたい場合はここを書き変えます。
(素直にadsl-setupを実行してもいいですが、全部を再入力する必要があるので、 部分的に変更する場合はこの設定ファイルを直接編集した方が楽です)

この設定をした場合、接続時に自動的に実行される設定ファイルがあります。
それは、/etc/ppp/firewall-masqです。 (STANDALONEを設定した場合は/etc/ppp/firewall-standalone、 当然ですが、NONEを設定した場合何も実行されません。)
私はこのファイルを変更することでファイアウォールを設定します。
もし、ファイアウォールをNONEに設定した場合や、rp-pppoeを使ってインターネットに接続しない場合など、 接続時に実行される設定ファイルがない場合は、/etc/rc.d/rc.localなどの初期化スクリプトに記述します。 (直接記述するか、ファイアウォールを設定するスクリプトを実行するように記述します。)
しかし、記述する位置によっては、接続が開始されてからファイアウォールが設定されるまでに間があるので、 その間に進入される危険が出てきます。(どこに書けばいいのか詳しいことは分からないので説明できません)
一方、rp-pppoeでは接続の前にこの設定ファイルを実行してくれるので何も気にせず、設定できます。

#!/bin/sh
#
# firewall-masqThis script sets up firewall rules for a machine
#                       acting as a masquerading gateway
#
# Copyright (C) 2000 Roaring Penguin Software Inc.  This software may
# be distributed under the terms of the GNU General Public License, version
# 2 or any later version.
# LIC: GPL

# Interface to Internet
EXTIF=ppp+

ANY=0.0.0.0/0

ipchains -P input ACCEPT
ipchains -P output ACCEPT
ipchains -P forward DENY

ipchains -F forward
ipchains -F input
ipchains -F output

# Deny TCP and UDP packets to privileged ports
ipchains -A input -l -i $EXTIF -d $ANY 0:1023 -p udp -j DENY
ipchains -A input -l -i $EXTIF -d $ANY 0:1023 -p tcp -j DENY

# Deny TCP connection attempts
ipchains -A input -l -i $EXTIF -p tcp -y -j DENY

# Deny ICMP echo-requests
ipchains -A input -l -i $EXTIF -s $ANY echo-request -p icmp -j DENY

# Do masquerading
ipchains -A forward -j MASQ
echo 1 > /proc/sys/net/ipv4/ip_forward

何も変更していない場合、このような構成になっていると思います。
最後のecho 1 > /proc/sys/net/ipv4/ip_forwardは前回説明したIPフォワーディングを有効にするためのもの、 ipchains -A forward -j MASQはIPマスカレードの設定です。
単純なシェルスクリプトですが、設定をするのにipchainsというコマンドを知らなければいけないようです。 このipchainsというのはLinuxカーネル2.2.xのパケットフィルタリングツールです。 (2.0.xはipfwadm、2.4.xはiptables、基本的な考え方は同じ)
では、ここでipchainsについて解説したいと思いますが、非常に多機能なツールなので説明し切れません。 詳しくはJM Project に日本語化されたマニュアルがありますのでそちらを参照してください。

ここでは、何をしているのか具体的な説明をしたいと思います。 (マニュアルを読む前に見ると、理解しやすくなる、っていうものになるといいなぁ(希望かよ))

基本概念

基本的な概念を説明します。

パケットフィルタリングする規則をルールといいます(そのまんまか)。
ルールには適用するパケットの性質(プロトコル・宛先・送信元IPアドレス・ポート番号など)と その処理(受諾、拒否など)が記述されてます。

ipchainsではルールを管理するのにチェインと呼ばれる4つのカテゴリを使います。
input、output、forward、そしてユーザ定義チェインです。
一番最初に、入力されたパケットはinputチェインへ、出力されるパケットはoutputチェインへ、 このホストがフォワードを行うパケットがforwardへ送られます。 (註:forwardチェインに入ってくるということは入力されているので、inputチェインも通過します。 さらにforwardを通過したパケットは出力される訳ですから、outputチェインも通過します。) ユーザ定義チェインはこちらで指示された時にのみパケットが送られます。
これらチェインに入ったパケットは、その中のルールに順に照らし合わされ、処理されます。

ルールという様々な網目の「ふるい」の積み重なったものだと考えると分かりやすいかもしれません。
パケットという材料は上からつぎ込まれて、順に網に引っかかり、引っかからなかったものは さらに下の網で分けられる・・・といった感じです。
そして、各層で引っかかったパケットはそこで指定された運命をたどります。 場合によってはこの後他のチェインに入ったりもします。

ルールの形を砕けていえば、~というチェインに入ってきた~という性質を持つパケットは~へ行け。という形です。

標準設定では何をやっているのか

まず、変数ですが、(どうでもいいのだが、一応)
$EXTIFという変数にppp+という値が設定されています。
これはインターフェイスを指定するのに使われます。 +という記号は前方一致を示していて、pppから始まるデバイスという意味です。(汎用性を持たせた設定です)
私の場合、pppoeでできるデバイスはppp0なのでppp0と書いても動きますが、結局ppp接続が一つなので無意味 むしろ3文字目までしかマッチングしないのでこの書き方の方が動作は速い・・・と思う。 (本当に文字列マッチングで判定してるかどうかさえも知らない)
$ANYという変数に0.0.0.0/0という値が設定されています。
宛先・送信元IPアドレスの指定に使われ、すべてのIPアドレスを意味します。


ipchains -P input ACCEPT
ipchains -P output ACCEPT
ipchains -P forward DENY

-P・・・ポリシーの設定
どのルールにもマッチングしなかったパケットに適用されるディフォルトの処理です。
入力と出力は受諾、フォワーディングは拒否と設定されています。


ipchains -F forward
ipchains -F input
ipchains -F output

-F・・・すべてのルールの削除
現在各チェインに設定されているルールをすべて削除して初期化しています。


# Deny TCP and UDP packets to privileged ports
ipchains -A input -l -i $EXTIF -d $ANY 0:1023 -p udp -j DENY
ipchains -A input -l -i $EXTIF -d $ANY 0:1023 -p tcp -j DENY

-A・・・ルールの追加
コメントに書いてあるように、TCPとUDPのパケットのうち特別な意味を持つポート宛のパケットを拒否しています。
特別な意味を持つというのは、ポート番号0~1023番のポート番号はwell-known portsと呼ばれ、 主要なサーバプロトコルの待ち受けポートとして使われます。
つまりこのルールによって、外部からこのホストで動いているサーバにはいっさいアクセスできなくなります。 (サーバによっては1023以降のポートを使うように設定もできるけど)
またユーザが一般に使うアプリケーションはこの範囲のポートを使わないので、何の影響もなく使うことができます。
各オプションの意味は、-l・・・ログをとる、-i・・・インターフェイスの指定、-d・・・宛先の情報の指定、 -p・・・プロトコルの指定、-j・・・このルールにマッチしたパケットの行き先の指定、となっています。

2行目を読み下すと「inputチェインに入ってきたパケットのうち、$EXTIF(ppp0)から来たもので、 UDPパケットで、宛先IPアドレスはどこでもいいが宛先ポート番号が0~1023のものであれば、 ログをとって、DENYへ持っていく(拒否する)」という意味になります。


# Deny TCP connection attempts
ipchains -A input -l -i $EXTIF -p tcp -y -j DENY

ここでも新しいルールを追加する指定です。
-yはTCPパケットのうちSYNフラグが1で、ACKフラグとFINフラグが0のパケットを意味しています。
このパケットは接続要求パケットと呼ばれるTCPコネクションを開始するときにのみ現れるパケットです。
ここでは外部からの接続要求パケットを拒否するようにしているのですが、 こうすると、内部から始められる通信に関しては許可するが、外部から始められる通信を拒否するという意味になります。
通信をするには双方向でのデータのやりとりが必要だが、 接続要求パケットだけはその通信を始めようとする側からしか送られない、という理屈です。
当然のことながら、コネクションレス型のプロトコルであるUDPではこのような設定はできません。 (接続要求なんてしないから)


# Deny ICMP echo-requests
ipchains -A input -l -i $EXTIF -s $ANY echo-request -p icmp -j DENY

ここではICMPのecho-requestタイプのパケットを拒否します。
ICPMのecho-requestは通信が可能かどうかを調べるために用いられるパケットで、 このパケットを受け取ったホストはecho-replyを返します。
これは、通信の確認の時に使ったコマンドpingなどで使われています。
なんでこれを拒否するのか?外部から、参照可能かどうか調べるのにも使えますし、 実際公開されているWebサーバでもpingを返してくれるサーバもたくさんあります。
真意のほどは分かりませんが、DoS攻撃に荷担しないための対策かな?と思います。 pingを送信元アドレスを偽って、ブロードキャストアドレスへ送信すると、受け取ったすべてのホストが、 偽られたアドレスを持つホスト向けにecho-replyを返します。 これによってトラフィックを増大させ、サーバを応答できなくさせる。といった攻撃があるそうです。 (自信はないので詳しい人のツッコミ待ってます。全く的はずれなことを書いてる可能性も・・・)


# Do masquerading
ipchains -A forward -j MASQ

最後に、forwardに入ってきたパケットはマスカレードします。

こんな感じです。
これからしなくてはならない設定等については次回にしたいと思います。