Linuxサーバ構築初学者のための頻出iptables

Linuxサーバを構築、公開するにあたって避けられないのがファイアウォールであるiptablesの構築ですね。
でもブログとかで公開されているiptablesの設定を見てもどういう設定内容になっているのかよくわからない、とか公式のドキュメントを見てみたけど高機能すぎて意味が分からん、とかで適当になっている人ももしかしたらいるのではないでしょうか。

と、いうわけで自分へのチートシートも兼ねてiptablesで頻出する書式を例を挙げながら解説してみようと思います。

#まずはiptablesの仕組みを知る
iptablesは複数のチェックポイント(チェインと呼ぶ)ごとにパケットの通過を許可、拒否、破棄する条件を設定できます。
各チェインはfilter、nat、mangleという3つのカテゴリ(テーブルと呼ぶ)に分類されますが、ここではLinuxサーバにおけるファイアウォールを扱うことが目的なのでfilterテーブルにのみ言及します。

##filterテーブルに属するチェイン
filterテーブルにはINPUT、OUTPUT、FORWARDという3種類のチェインがあり、それぞれ次のような役割を持ちます。

- INPUT
受信したパケットのうち、宛先IPアドレスが自分であるものを対象とするチェイン
- OUTPUT
自分の内側、すなわち自分の上で動作しているプログラムのプロセスから送信されるパケットを対象とするチェイン
- FORWARD
受信したパケットのうち、宛先IPアドレスが自分ではないために転送されるパケットを対象とするチェイン

##filterテーブルによるフィルタリングの流れ
###FORWARDチェイン
宛先IPアドレスが自分ではないパケットはFORWARDチェインへ行きます。
それらはFORWARDチェインに記述されている条件に照会され、許可されたり、拒否されたり、破棄されます。
FORWARDチェインにおいて許可されたパケットはそのまま自分の外へ出ていきます。
ので、サーバにおけるiptablesを扱う本稿ではあんまり関係なかったりします。

###INPUTチェイン
宛先IPアドレスが自分であるパケットはINPUTチェインへ行きます。
それらもやはりINPUTチェインの条件に照会され、許可されたもののみがPCの内側、すなわちLinux上で動作しているサーバプログラムのプロセスへ到達します。

###OUTPUTチェイン
自身の内側から外側へ送信されるパケットは必ずOUTPUTチェインへ行きます。
OUTPUTチェインも当然各パケットを設定されている条件に照会するわけですが、その対象となるパケットの範囲については注意する必要があります。

####FORWARDチェインを通過したパケットはOUTPUTチェインには到着しない
OUTPUTチェインはiptablesの内側から送信されるパケットに対してフィルタリングを行うチェインです。
FORWARDチェインを通過したパケットは外側から外側へ転送されるのみでiptablesの内側には入っていないのでOUTPUTチェインの対象ではありません。

####ループバック接続はOUTPUTチェインを通過した後、INPUTチェインに到着する
Linux上で動作するプログラムには、同じコンピュータ上で動作していてもループバック接続によって接続を行うプログラムが少なからず存在します。
具体的にはMySQLなどでして、UNIX/Linuxではネットワーク越しに複数のコンピュータが連携することが当たり前ですから同じコンピュータ上で動作しているかどうかを区別せず全てIP通信で行ってしまうことが当然なのでしょう。

というわけで、同じコンピュータ上で動作するプロセスにIP通信を用いて接続する際には127.0.0.1を宛先としたパケットが送信されます。127.0.0.1は自分自身を意味するIPアドレスです。
iptablesはIPv4を対象とするファイヤーウォールなので直接は関係ありませんが、IPv6では[::1]です。
内側で動作するプロセスからiptablesの外側であるネットワーク層まで出ていくのですから当然OUTPUTチェインを通過しますし、自分自身が宛先でiptablesの内側へ到着しようとするのですから当然、INPUTチェインを通過します。

##iptablesにおける許可、拒否、破棄
前節では許可、拒否、破棄という単語を用いましたが、設定ファイルに記述する場合は当然英語で、それぞれACCEPT、REJECT、DROPという語を用います。

- ACCEPT 許可
読んで字のごとく、該当するパケットにチェインの通過を許可します。
- REJECT 拒否
該当するバケットの送信元に対して、接続を拒否する旨のicmpパケットを送信します。
- DROP 破棄
該当するパケットを捨てます。送信元に対しては何もしません。


#iptablesの設定ファイルを読んでみる
さて、前節の知識をベースに下のファイルを上から順に読んでみましょう。

```:iptables
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

-A INPUT -m state --state NEW -s 127.0.0.1 -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
COMMIT
```

##`*filter`
filterテーブルについての設定を始めるという宣言です。

`:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]`
各チェインのデフォルト動作とパケットカウンタの初期値を設定しています。
INPUTはデフォルト動作がDROP、FORWARDとOUTPUTはACCEPTになっています。

##`-A INPUT -m state --state NEW -s 127.0.0.1 -j ACCEPT`

- -A INPUT
INPUTチェインにルールを追加(Append)する
- -m state --state NEW
フローの状態がNEW、すなわち新しい接続を確立するために送信されてきた最初のパケット(SYN)を対象とする
- -s 127.0.0.1
送信元IPアドレスが127.0.0.1である
- -j ACCEPT
パケットを許可する

##`-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT`

- -A INPUT
INPUTチェインにルールを追加(Append)する
- -m state --state ESTABLISHED,RELATED
パケットの状態がESTABLISHEDかRELATEDである
 - ESTABLISHED
既に確立済みである接続
 - RELATED
確立済みの接続に関係する接続
ex.FTPのデータ送信コネクションなど
- -j ACCEPT
パケットを許可する

##`-A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT`

- -A INPUT
INPUTチェインにルールを追加(Append)する
- -p tcp --dport 22
パケットの宛先ポートが22番である
- -m state --state NEW
フローの状態がNEW、すなわち新しい接続を確立するために送信されてきた最初のパケット(SYN)を対象とする
- -j ACCEPT
パケットを許可する

##`COMMIT`
設定を適用するキーワードです。

と、概ねこのような感じになっています。

原則的にはこのようにINPUTチェインをホワイトリスト方式(許可するものだけを明示)で書いていけばいいと思います。
つまり-A [INPUT/OUTPUT/FORWARD]を使ってルールを設定する対象のチェインを書き、-s [0.0.0.0-255.255.255.255]/[1-30]と-m state --state [NEW/ESTABLISHED/RELATED]と-p [tcp/udp] --dport [1-65535]を使って条件を指定し、-j [ACCEPT/REJECT/DROP]を使ってその条件に合致するパケットをどうするかを記述すれば良いのです。

それ以外の事をしようとしている人はもはや初学者ではないと思われるので扱いません！

では皆さん、良いiptablesライフを(？)。