■ インストール
iptables
は通常、カーネルモジュールとしてロードされるので、実装に関してはパッケージとモジュールについて頭の切り替えが必要である。ただし、2.4系以降のカーネルでなければ
iptables は使えないので念のため。
1.パッケージのインストール
RedHat
のようなディストリビューションの2.4系カーネルをサポートするバージョンでは
iptables はデフォルトでインストールされる。もしも、何かの事情でインストールされていない場合は、現在の最新バージョン
iptables-1.2.8.tar.bz2 をnetfilter
ホームページからダウンロードし、/usr/local/src
などの適切なディレクトリに置く。インストールに関しては特にむずかしいことはなく、アーカイブを展開したのちは通常のアプリケーションの通り
make, make install の手順でインストールすればよい。
[root@
/root]# cd /usr/local/src [root@ src]# bzip2 -cd
/tmp/iptables-1.2.8a.tar.bz2 | tar xvf - [root@ src]# cd
iptables-1.2.8a [root@ iptables-1.2.8a]# make [root@
iptables-1.2.8a]# make install
ここでエラーが表示されなければ問題なくインストールできている。
ちなみに、RedHat
ではバージョン7.1Jからカーネルが2.4系に変更されている。iptables
は2.4以上のカーネルバージョンでサポートされているが、これ以前のカーネルバージョンでは
ipchains を使用する必要がある。両者の間には構文の違い( deny →
drop 、アクション/チェインでの大文字の使用等)があり、機能的にも iptables は ipchains から拡張されている。
2.FORWARDの有効化
チェインについては後述するが、FORWARDチェインを使うのならシステム起動後にonになるように、ローカル起動スクリプトrc.localに次のスイッチを記述する必要がある。
echo 1 > /proc/sys/net/ipv4/ip_forward
この設定を怠るとFORWARDできないので注意すること。また、複数のNICが組み込まれている場合でも単にFORWARDスイッチを1にセットしたからといって、すぐにパケットの転送ができるようになるわけではない。iptables
の ipmasquread の設定によってそれぞれの転送パケットを制御できるようにしなければならないので、通信制御の方向は前もって煮詰めておく必要がある。カーネルスイッチの設定の詳細については、別項ネットワーク設定の「ネットワーク設定のための /proc 仮想ファイルシステム」を参照のこと。
3.モジュールのロード
早い時期のカーネル2.4系のディストリビューション(RedHat
では 7.1J〜7.3 あたり)では両者がインストールされているので、少し注意が必要である。ここで問題になるのは両モジュールが排他的で同時にロードすることができず、しかも旧版の
ipchains の方に起動優先権が与えられたバージョンがあることである。もしもこの設定になっている場合は
iptables を起動できないので、まず lsmod コマンドでモジュールがどのようにロードされているか調べておく。以下にRedHat8における
lsmod コマンドの実行例を示す。
この例では赤枠で囲まれた部分のモジュールが示すとおり
iptables がロードされていることがわかるが、次のようなメッセージが出ればまだ
iptables を使える環境になっていない。
ipchains 38976 0 (unused) (ipchains がロードされている)
このような場合はまず
rmmod コマンドで ipchains のモジュールを削除し、chkconfig
コマンドで自動起動を停止する。
# rmmod ipchains # chkconfig ipchains off
続いて
iptables を使えるようにする。(ここでは modprobe コマンドのパスを
RedHat 系にならって /sbin 以下に仮定している。不確実な場合は
which modprobe で確認すること。)なお、iptables 関連のモジュールには優先関係があり、通常、ip_tables から以下の順番にロードする。
#
/sbin/modprobe ip_tables #
/sbin/modprobe ip_conntrack #
/sbin/modprobe iptable_nat #
/sbin/modprobe iptable_filter #
/sbin/modprobe iptable_tables
ここで再び lsmod コマンドを投入する。出力に次の5つのモジュールが揃っていればOKである。
iptable_mangle iptable_nat ip_conntrack iptable_filter ip_tables
以上、古いバージョンを使わなければならない事情がある場合は
ipchains と iptables モジュールがおたがいに排他的であることを十分理解しておくこと。
なお、ftp
をはじめとして、固有のモジュールをロードしなければ機能しないプロトコルもあることを知っておきたい。これは
ftp プロトコルがコネクション制御用のチャネルとデータ転送用のチャネルを別々に持っており、コネクショントラッキングを実現するモジュールが必要になるためである。以下に
ftp 用のモジュールのロードと2枚NICにおける制御の例を示す。
##
ftp通信用モジュールのロード(FTPの通過および応答を許可)
/sbin/modprobe
ip_nat_ftp /sbin/modprobe ip_conntrack_ftp
/sbin/iptables
-t filter -A FORWARD -i eth0 -p tcp --dport 21
-j ACCEPT /sbin/iptables -t filter
-A INPUT -i
eth1 -p tcp --dport 21 -j ACCEPT
■ ネットワークの設定とNICの有効化
iptables
はカーネルモジュールを使い、ネットワークカードの設定をもとに機能する。これらの設定はインストール時にできるが、変更したり暫定的に設定した場合は次の二つのファイルによって再設定を行う。
1./etc/sysconfig/network
--- ホストマシン全体の設定
このファイルにはホストマシン全体の設定がされる。設定項目は次のとおり。
設定項目
|
説 明
|
NETWORKING
|
ネットワーク利用の有無(使用する場合は
yes)
|
NETWORKING_IPV6
|
V6ネットワークを使用するかどうか
|
HOSTNAME
|
ホスト名の指定
|
GATEWAY
|
デフォルトゲートウェイの指定
|
GATEWAYDEV
|
DGWに接続されているNICの指定(1枚しかないときは一意に決定する)
|
USERCTL
|
NICの制御を一般ユーザに許可するかどうか(普通は
no)
|
通常、NIC一枚で構成されるホストマシンの
netwwork ファイルには次のような内容が記述されている。
NETWORKING=yes HOSTNAME=server GATEWAY=192.168.1.1
ネットワーク設定を変更した場合は、次のコマンドでネットワークが再設定されたことをカーネルに知らせること。
#
/etc/rc.d/init.d/network start
(これはデーモン起動スクリプトと全く同じ書式であるが、ネットワーク専用デーモンが存在するわけではない。あくまで「起動スクリプトでシステムをコントロールする」というポリシーである。)
2./etc/sysconfig/network-scripts/ifcfg-eth0
--- ネットワークインタフェースごとの設定
このファイルでは名前の示すとおり、インタフェースごとの設定が行われる。RedHat
ではインタフェース番号を eth0,eth1,eth2 …で定義し、ifcfg-ethX
の名称でインタフェース設定ファイルが作られる。これらのファイルのフォーマットは次のようになっている。(RedHat
9 では/etc/sysconfig/network-scripts/device 以下にあるので注意)
DEVICE=eth0 BOOTPROTO=none BROADCAST=192.168.1.254 IPADDR=192.168.1.1 NETMASK=255.255.255.0 NETWORK=192.168.1.0 ONBOOT=yes USERCTL=no PEERDNS=no GATEWAY=192.168.0.1 TYPE=Ethernet
ここで重要なのは、ONBOOTを
yes に設定しておくことである。これによって起動時に指定したインタフェースがアクティブになるので必ず確認すること。その他は普通にネットワーク設定を行えばよい。また、NICを増やす場合は2枚目から順番に
ifcfg-eth1…の名前で設定ファイルを作っておく。これらはGUIレベルからツールによって設定できるが、サーバとしてXwindowをインストールせず、ランレベル3でだけ動作させる場合は構築時に作成しておく。
なお、上記の設定は
ifconfig コマンドや route コマンドによって作成することもできる。(インタフェースの設定コマンドをスクリプトに記述して/etc/rc.local
に登録しておいてもよい。)
#
ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up #
route add -net 192.168.0.0 netmask 255.255.255.0 eth0 #
route add default gw 192.168.0.1
ブートローダに
lilo を使っている場合は、lilo の設定ファイルに起動時にアクティブにする設定を書いておくことができる。そのためには
lilo.conf に次の一行を加えればよい。ここでは eth0, eth1,
eth2 の3枚のNICを起動時にアクティブにするものとする。
append
= "ether = 0,0,ether1 ether = 0,0,ether2"
eth0
の設定が見えないが、これはネットワークを利用する設定ではデフォルトで
eth0 を認識できるからである。すなわち、追加するインタフェース
eth1 と eth2 の設定を書いておけばよい。なお
lilo.conf を変更した場合もコマンドによるカーネルへの通知が必要になる。通知は次のコマンドによって行う。
# /sbin/lilo
■ iptables の設定コマンドの概要
ルールを追加するときは
iptables コマンドを使用するが、これは最終的にシェルスクリプトファイルにまとめることができ、なおかつシステム再起動時に再定義しないで済むようにセーブすることができる。 iptables コマンドの書式は次のとおり。
# iptables [ パラメータ(-t tableなど) ] [ オプション(-A chainなど) ] [
条件(-i interfaceなど) ] [ アクション(DROPなど) ]
以下にごく基本的なコマンドの一覧を示す。詳しくは
man ページ参照のこと。
1.パラメータ
パラメータ
|
-p(--protocol) プロコトル |
ルールで使うプロトコル(tcp、udp、icmp、all)を指定 |
-s(--source) IPアドレス[/mask] |
送信元アドレス。IPアドレスのほかにホスト名などでも指定できる |
-d(--destination)
IPアドレス[/mask] |
接続先アドレス。IPアドレスのほかにホスト名などでも指定できる |
-i(--in-interface) デバイス |
パケットが入ってくるインターフェイス(eth0、eth1など)を指定 |
-o(--out-interface) デバイス |
パケットが出ていくインターフェイスを指定 |
-j(--jump) ターゲット |
パケットがマッチしたときのアクション(ターゲット)を指定 |
-t(--table) テーブル |
テーブル(filter、nat、mangle)を指定 |
! |
-p、-s、-dなどで、条件を反転する。「!
192.168.0.1」とすると、「192.168.0.1以外」という意味になる |
2.オプション
オプション
|
-A(--append) |
指定チェインに1つ以上の新しいルールを追加 |
-D(--delete) |
指定チェインから1つ以上のルールを削除 |
-P(--policy) |
指定チェインのポリシーを指定したターゲットに設定 |
-N(--new-chain) |
新しいユーザー定義チェインを作成 |
-X(--delete-chain) |
指定ユーザー定義チェインを削除 |
3.条件
条件 |
-i interface |
条件として入力インタフェースを指定(eth0 や eth1 等) |
-p protocol |
条件としてプロトコルを指定(tcp , udp , icmp , all 等)
※ TCP ・ UDP
は以下のオプションでポート番号の指定可能。
--sport ポート番号 : 送信元ポート番号 --dport ポート番号 :
宛先ポート番号
|
-o interface |
インタフェース や eth1 等 |
-s IPaddr |
source アドレスの指定(サブネットマスクを用いた指定が可) |
-d IPaddr |
destination アドレスの指定(サブネットマスクを用いた指定が可) |
4.ターゲットへのアクション
ターゲットへのアクション
|
ACCEPT |
パケットの通過を許可 |
DROP |
パケットを破棄(ipchains
では deny) |
REJECT |
パケットを拒否するがICMPメッセージは返信する |
REDIRECT |
特定ポートにリダイレクト |
■ テーブル・チェイン・アクション
次に使用頻度の高いテーブル・チェイン・アクションの設定項目ごとにまとめる。
-t table |
-t table |
テーブル名の指定 |
table |
指定できる table の種類は以下の通り。
1.filter
フィルタリングテーブル
2.nat アドレス変換用テーブル 3.mangle パケットに追加的な操作を行うテーブル(特殊用途・manページ参照のこと)
※ table
名省略時は filter 用のテーブルになる |
-A chain |
-A chain |
chain に条件やアクション(ルール)の追加 |
-P chain |
chain の基本となるルールの決定 |
-F chain |
条件の合致する chain を削除(-F
のみで chain 省略時は全て削除になるので注意) |
chain |
指定できる chain の種類は以下の通り。
1.PREROUTING 受信時に変換するチェイン 2.FORWARD フォワード(転送)するパケット 3.POSTROUTING 送信時に変換するチェイン 4.INPUT
入力(受信)パケット 5.OUTPUT 出力(送信)パケット
※ chain は自分で定義することができる |
-j アクション |
-j ACCEPT |
パケットの通過を許可 |
-j DROP |
パケットの通過を拒否(ipchains
では deny アクション) |
-j MASQUERADE |
「 -t nat 」と「 -A POSTROUTING 」を同時に用いて、送信元IPアドレスとポート番号の書き換えを行う。 |
-j DNAT |
「 -t nat 」と「 -A PREROUTING
」を同時に用いて、宛先IPアドレスを書き換えを行う。
※ 以下のオプションで書き換える宛先IPアドレスとポート番号の指定が可能。
--to
IPアドレス [ ポート番号 ] |
■ ファイアウォールの設計から構築への工程
ファイアウォールを設計する上で最も重要なのがポリシーの設計である。これはネットワーク資源の「何を・何から・どのように」守るのか、という基本的な構想である。ポリシーを決定することはファイアウォール設計の中核であるが、ポリシーだけを独立して設計するというものではなく、全体の流れの中の一部分として明確化されるべきものである。全体の流れを把握するため、ここでファイアウォール構築の工程例を示す。
1.要求仕様の定義 2.ネットワーク構成の検討と利用プロトコルの洗い出し 3.入出力パケットの検討 4.ファイアウォールポリシーの決定 5.ポリシーにもとづく
iptables の設定 6.テストケースの設計と検証 7.運用テストと移行
1.要求仕様の定義
ファイアウォールに関する要求仕様を一覧にまとめる。システム設計の概念上、これは上流工程としてのシステム解析と考えてよい。普通、顧客からの注文をすべて受け入れることはむずかしいので、最低限次の点について明らかにしておく。
イ.予算
ロ.ネットワーク規模と構成(既存のネットワークか新規ネットワークかを含めて) ハ.動かしたいサービス(内部向け/外部向け) ニ.組織内で守るべき情報の優先度 ホ.実装・設置上の課題検討
また、現場の条件によっては検証環境の構築も必須となるため、あわせて検討しておくこと。
2.ネットワーク構成の検討と利用プロトコルの洗い出し
システム開発の概念からは概要設計に相当する。ネットワーク構成については基本的な形態を後述するが、要求仕様で定義した「予算」および「ネットワーク規模と構成」からブレイクダウンし、概念図とシステム構成表をまとめる。また、同様にして「動かしたいサービス」をブレイクダウンし、どのようなプロトコルが使われているかリストアップする。このときプロトコルがトラフィックに与える影響を留意点としてピックアップしておくとよい。たとえば
NetBIOS のようなブロードキャストを多用するプロトコルがある場合などがこれに当たる。また、TCP/IPの場合、パケットがTCPかUDPかをはじめ、該当プロトコルが使用する標準ポート(ウェルノウンポート)も同時に書き出しておく。
3.入出力パケットの検討
システム開発の概念からは基本設計に相当する。第二工程で作成したプロトコル一覧表をもとに入出力を解析し、具体的に止めるべきパケットと通すべきパケットを決定する。(DFDツールなどで入出力をまとめておくとよい。)また同時に、想定する外部アタックの種類(ポートスキャン・IPスプーフィング・SYNフラッド・DoSなどなど)を一覧表にまとめ、打つべき対策を検討しておく。
また、重要な項目として転送パケットの扱いがある。たとえばメールサーバを内部セグメントとDMZセグメントに置きDMZのMTAを中継サーバとするときなど、SPAM転送に悪用されないように十分留意する必要がある。これは他の種類のサーバでも同様な問題が起こりうるので、転送パケットについては細心の注意をすること。
同様にポートを標準ポートからユーザポートに変更する必要があるサービスについてもリストアップしておく。たとえばWEBサービスをユーザ権限で動かしたい場合など、しばしば80→8080のような変更が行われる。
4.ファイアウォールポリシーの決定
システム開発の概念からは詳細設計に相当する。工程1〜3までに決ったパケットの流れやアタック対策項目から実際に制御するルールを決定し、一覧表にまとめる。このルールがポリシーそのものであり、一覧表は
iptables を設定するための基本設定表になる。
この設定表はそのままテストケースの設計に使えるので、このあとの工程を分割して
iptables の設定記述とテストケースの設計を同時に進行させるとよい。
5.ポリシーにもとづく
iptables の設定
システム開発の概念からは製造(コーディング/デバッグ)工程に相当する。実際に
iptables コマンドを動作させるスクリプトを書き、デバッグを行う。iptables
コマンドはスクリプトからシステムにセーブし、再起動時も読み込むようにする。また、スクリプトは最初に検証機で動作させ、そのままテスト工程を待つ。
6.テストケースの設計と検証
パケット/プロトコルごとにテストケースを設計する。フィルタリングの基本機能としてフィルタが正しく働いているか、通すべきパケットまで止めていないか、要求項目ごとにチェックを行う。通常、外部ホストからのチェックには
nmap を使い、自ホストからのチェックには netstat を使ってポートをチェックする。
# nmap -P0 -p 1-65535 192.168.1.1 外部より192.168.1.1のサーバへ #
netstat -ant 自ホストのチェック
また、負荷検証ツールがあれば同時に負荷テストも設計しておく。ただし、システム負荷に関しては想定と現実との間に落差ができるのが普通であり、テストケースの設計自体がかなりむずかしい。たとえばWEBシステムへの過大負荷の発生などは多くの場合予測がつかず、必然的にリクエストがさばき切れない局面が発生する。これはフィルタリングでは対処できない(パケットの受け入れを毎秒いくつ、にすることはできるが…)ので、前もって
Apache WEBサーバの設定によって同時にオープンするセッション数やプロセス数を設定しておくこと。
※ この段階でのテストは検証機で実施し、要求項目が満足されれば運用テストへの準備を完了とする。
7.運用テストと移行
運用実機へのインストールとによる運用テストを行う。これは性能のテストというよりも、むしろ実装上の問題が発生しないかどうかのテストとなる。実装上の問題点が解消できたら、最終的にドキュメントをまとめ運用マニュアルを作成して作業が完了する。ただし、移行に関しては時系列でのチェックを続けなければならないので、別に運用管理とサポート体制を組織しておく必要があるのは言うまでもない。
■ チェインの設定
ここで問題を単純化するために、ブロードバンドルータに直結した1台だけのWEBサーバを考える。このサーバにおけるWEBサービスは通常のHTTPとSSL通信によるHTTPSをサポートする。さらにこのサーバではDNSが稼動し、外部のDNSと相互参照を行わせる。また、サーバのメンテナンスにはブロードバンドルータのハブポートから、必要なときだけSSHで専用ホストが入るものとする。
1.ネットワーク設定
サーバホスト
|
192.168.x.yyy
|
メンテナンスホスト
|
192.168.x.zzz
|
サブネットワークアドレス
|
192.168.x.0/24
|
2.稼動サービスと使用ポート
DNS
|
UDP
53
|
WEB
|
TCP 80
(HTTP)
|
TCP
443 (SSL)
|
SSH
|
TCP 22
|
3.パケットの入出力
プロトコル
|
対象
|
IN
|
OUT
|
ポリシー
|
DNS
|
インターネット
|
○
|
○
|
外部のDNSに対して相互に名前解決要求を許可
|
内部ネット
|
○
|
○
|
すべての内部ホストからの名前解決要求を許可
|
HTTP
|
インターネット
|
○
|
○
|
すべての外部ホストからWEBサービスへの接続許可
|
内部ネット
|
○
|
○
|
すべての内部ホストからWEBサービスへの接続許可
|
SSL
|
インターネット
|
○
|
○
|
すべての外部ホストからHTTPSサービスへの接続許可
|
内部ネット
|
○
|
○
|
すべての内部ホストからHTTPSサービスへの接続許可
|
ICMP
|
インターネット
|
-
|
-
|
すべて禁止
|
内部ネット
|
○
|
○
|
ローカルネットについてすべて相互に許可
|
SSH
|
インターネット
|
-
|
-
|
すべて禁止
|
内部ネット
|
○
|
-
|
メンテナンスホストからのみSSH接続を許可
|
4.チェインの基本的な設定例
以下はポリシーをもとに設定したチェインの例である。なお、設定を行うときはサーバ側にキーボードとモニタを用意してメインコンソールで行う。(他のホストから
telnet などの許可されないポートからログインして設定していると、iptables
実行スクリプトを動かした途端、通信できなくなるので念のため。起動時にスクリプトを動かしたい場合は
/etc/rc.local に登録しておけばよい。)また、作成したスクリプトは一般ユーザのアクセスを禁じたディレクトリに置き、念のためユーザ権限での読み・書き・実行も禁止しておく。
----
iptables_set.sh ----
#!/bin/bash
#-------------------------------------------------
変数定義
# iptables のコマンドを短縮して変数化
iptables="/sbin/iptables
-v"
# IPアドレス・ネットワークアドレスを変数化
server="192.168.x.yyy" localnet="192.168.x.0/24" maintenance="192.168.x.zzz" any="0.0.0.0/0"
#-------------------------------------------------
初期化
# すべてのルールをフラッシュ
$iptables
-F $iptables -F -t nat $iptables -X
# すべてのアクセスを禁止
$iptables
-P INPUT DROP $iptables
-P OUTPUT DROP $iptables -P FORWARD DROP
#-------------------------------------------------
loopback
# Loopbackにすべて許可
$iptables
-A INPUT -s 127.0.0.1 -d 127.0.0.1
-j ACCEPT $iptables -A OUTPUT -s 127.0.0.1 -d 127.0.0.1
-j ACCEPT
#-------------------------------------------------
localnet
# ローカルネットに対して ICMP 8/0 を相互許可
$iptables
-A INPUT -p icmp -s $server
--icmp-type 8 -d $localnet -j ACCEPT $iptables
-A OUTPUT -p icmp -s $localnet --icmp-type 0 -d $server
-j ACCEPT
$iptables -A INPUT -p
icmp -s $server --icmp-type 0 -d $localnet
-j ACCEPT $iptables -A OUTPUT -p icmp -s $localnet
--icmp-type 8 -d $server -j ACCEPT
#-------------------------------------------------
DNS
# 外部DNSに対して名前解決を許可
$iptables
-A INPUT -p udp -s $any -d
$server --source-port 53
-j ACCEPT $iptables -A OUTPUT -p udp -s $server -d
$any --destination-port
53 -j ACCEPT
# すべてのホストからの名前解決要求を許可
$iptables
-A INPUT -p udp -s $any -d
$server --destination-port 53 -j ACCEPT $iptables
-A OUTPUT -p udp -s $server -d $any --source-port
53 -j ACCEPT
#-------------------------------------------------
SSH
# メンテナンスホストからSSH接続を許可
$iptables
-A INPUT -p tcp -s $maintenance
-d $server --destination-port
22 -j ACCEPT $iptables -A OUTPUT -p tcp -s
$server -d
$maintenance --source-port 22
-j ACCEPT
#-------------------------------------------------
HTTP
# すべてのホストからHTTP接続を許可
$iptables
-A INPUT -p tcp -s $any -d
$server --destination-port 80 -j ACCEPT $iptables
-A OUTPUT -p udp -s $server -d $any --source-port
80 -j ACCEPT
#-------------------------------------------------
HTTPS
# すべてのホストからHTTPS接続を許可
$iptables
-A INPUT -p tcp -s $any -d
$server --destination-port 443 -j ACCEPT $iptables
-A OUTPUT -p udp -s $server -d $any
--source-port 443
-j ACCEPT
注意: この設定は基本的にパケットの入出力を制御するだけのものです。ファイアウォールに必須のアタック対策やIPスプーフィング対策は記述されていません。
|
5.ファイルの書き込み
以上の作業が終わったら
iptables
の設定を
/etc/sysconfig/iptables
ファイルにリダイレクトしておく。こうしておけばスクリプトファイルを
/etc/rc.local に登録しておかなくても、次回立ち上げ時に設定が有効になる。書き込みには
iptables-save コマンドを使う。書式は以下のとおり。(RedHat以外のディストリビューションの中にはこのツールが存在しないものもあるので注意。)
/sbin/iptables-save > /etc/sysconfig/iptables
|