Murayama blog.

プログラミングと、その次の話

iptablesの設定 入門編

Linux勉強中です。
今日はiptablesを試してみます。
参考書籍はこちら。

Ubuntuで作るLinuxサーバー (日経BPパソコンベストムック)

Ubuntuで作るLinuxサーバー (日経BPパソコンベストムック)


そうそう、この本オススメです。
タイトルにもあるとおり、サーバ構築がメインでして、
内容も浅すぎず、深すぎずちょうどいいです。
暇な人は本屋さんへGO。


で、勉強した内容をまとめます。

iptablesとは

iptablesはパケットフィルタリング機能をもつソフトウェアです。
ファイアウォールやNATとして利用できます。
CentOSの場合は、デフォルトでインストールされており、
ファイアウォールの設定もデフォルトで有効になっています。

iptablesの設定確認

iptables --listで確認します。

[root@localhost ~]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
RH-Firewall-1-INPUT  all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
RH-Firewall-1-INPUT  all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain RH-Firewall-1-INPUT (2 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     icmp --  anywhere             anywhere            icmp any 
ACCEPT     esp  --  anywhere             anywhere            
ACCEPT     ah   --  anywhere             anywhere            
ACCEPT     udp  --  anywhere             224.0.0.251         udp dpt:mdns 
ACCEPT     udp  --  anywhere             anywhere            udp dpt:ipp 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ipp 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh 
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

ちょっと考察してみます。Let's考察。
Chainで始まる4つのブロックがあります。

  • Chain INPUT (policy ACCEPT)
  • Chain FORWARD (policy ACCEPT)
  • Chain OUTPUT (policy ACCEPT)
  • Chain RH-Firewall-1-INPUT (2 references)

INPUT、OUTPUT、FORWARD、RH-Firewall-1-INPUTの4つが見てとれます。


1つ目のChain INPUT (policy ACCEPT)の続きを見ると

target     prot opt source               destination         
RH-Firewall-1-INPUT  all  --  anywhere             anywhere            

ヘッダ(target prot optなど)とその指定だと見てとれます。
また、その他のChainブロックも同様に出力されています。


さらによく見ると、
先頭2つのChain(INPUT、OUTPUT)ブロックは、
4つ目のChain(RH-Firewall-1-INPUT)を参照しているように見えます。
3つ目のChain(OUTPUT)は、ヘッダの表示だけで何も設定されていないようです。


とりあえずの考察は以上で、
iptablesの基本的な部分からまとめていきます。

3つのテーブル

iptablesには3つの機能があります。
その3つをテーブルという概念で定義します。

テーブル名 機能
filter パケットフィルタリング
nat IPアドレスの変換
mangle IPヘッダの書き換え

各テーブルはチェインの集合を持ちます。
チェインとは後述するルールを束ねたもののことです。
#話がそれますが、JavaなんかでもFilterChainとか出てきますがあのノリになります。


チェインは5つの組み込みチェインとユーザ定義チェインに分類できます。
組み込みチェインの一覧は以下のとおりです。*1

チェイン 実行条件
INPUT パケットがNICに取り込まれたとき(送信先が自身である)
OUTPUT パケットがNICから出ていくとき(送信元が自身である)
FORWARD パケットがNICから出ていくとき(ルーティング後)
PREROUTING パケットがNICに取り込まれたとき(ルーティング前)
POSTROUTING パケットがNICから出ていくとき(ルーティング後、FORWARDの後)

イメージ図

ルールとは特定のIPアドレスやプロトコルを条件に、
パケットを受け取るのか破棄するのかといった処理を定義するものです。
これらの処理はターゲットして分類されています。主要なターゲットを以下にまとめます。

ターゲット 処理
ACCEPT パケットを受け取る
DROP パケットを破棄する
REJECT パケットを破棄し、エラーパケットを返す
DNAT 送信先IPアドレスを変更する
MASQUERADE 複数の送信元IPアドレスを変更(マスカレード)する
SNAT 送信元IPアドレスを変更する
LOG ログを出力する


つづいて、
既存の設定を初期化しポリシーに従ってフィルタリングの設定をしてみます。

iptablesの初期化

iptables --flushコマンドを実行します。

[root@localhost ~]# iptables --flush

iptables --listの実行結果から設定情報が初期化されたのがわかります。

[root@localhost ~]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain RH-Firewall-1-INPUT (0 references)
target     prot opt source               destination         
[root@localhost ~]# 

iptablesの設定

以下のポリシーを満たすよう設定してみます。

  1. ローカルマシンからの全ての送信を許可する
  2. ローカルマシンへの全ての受信を拒否する
  3. ローカルマシンへから送信時の応答受信は許可する
ローカルマシンから全ての送信を許可する

ローカルマシンからの送信ということなので、OUTPUTチェインを設定します。
iptables --flush直後の状態は、

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

となっています。
設定が何もされていない状態です。
この場合 (policy ACCEPT)の部分が適用されます。
つまり、デフォルトでACCEPTする(許可する)という意味になり、
現状のままでもポリシーを満たせます。
よって追加設定は不要です。

ローカルマシンへの全ての受信を拒否する

ローカルマシンへの受信ということなので、INPUTチェインを設定します。

iptables --flush直後の状態は、

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

となっています。
OUTPUTチェインの場合と同様にすべてをACCEPT(許可)してしまいます。
そこでポリシーを満たすためには以下のコマンドを実行します。

iptables --table filter --append INPUT --in-interface eth0 --jump DROP

iptables --listで確認すると

[root@localhost ~]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain RH-Firewall-1-INPUT (0 references)
target     prot opt source               destination   

となり、INPUTチェインにルール(DROP処理)が追加されているのがわかります。
ただし、この設定のままだと次の3つ目のポリシーを実現できていないため調整が必要になります。

ローカルマシンへから送信時の応答受信は許可する

送信時の応答受信を許可するためにはiptablesのモジュールを利用します。*2

iptables --table filter --append INPUT --in-interface eth0 --match state --state ESTABLISHED,RELATED --jump ACCEPT

上記のコマンドを実行すると送信時の応答受信を許可することができます。


ここで、2つ目のポリシーと3つ目のポリシーを優先順位を検討します。
今回のように実行順序を以下のようにしてしまうと

iptables --table filter --append INPUT --in-interface eth0 --jump DROP
iptables --table filter --append INPUT --in-interface eth0 --match state --state ESTABLISHED,RELATED --jump ACCEPT

iptables --listの実行結果は以下のようになってしまいます。

[root@localhost ~]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain RH-Firewall-1-INPUT (0 references)
target     prot opt source               destination         

INPUT時には、DROPが先に実行されるためすべてのパケットが破棄されてしまいます。
よって3つ目のポリシーは満たされません。


正しくポリシーを満たすためには、コマンドの実行順序を変更します。

iptables --table filter --append INPUT --in-interface eth0 --match state --state ESTABLISHED,RELATED --jump ACCEPT
iptables --table filter --append INPUT --in-interface eth0 --jump DROP

そうすると、iptables --listの実行結果は以下のようになります。

[root@localhost ~]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
DROP       all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain RH-Firewall-1-INPUT (0 references)
target     prot opt source               destination         

上記であれば3つのポリシーを満たすことができます。

iptables設定の保存

iptablesの設定情報はマシンを再起動すると初期化されてしまいます。
設定を残すにはserviceコマンドによって保存できます。

service iptables save

上記のコマンドを実行すると、
/etc/sysconfig/iptablesファイルに設定が保存されます。

オチ

もっと勉強します。

*1:動作確認までしてないので間違ってたらすみません。

*2:このまま設定を追加すると、先ほど設定した2つ目のポリシーが優先されるので、いったんiptables --flushにて初期化しておきます