ドキュメントから学ぶiptables

以前に何度かiptablesを理解しようと試みて挫折しました。言葉がいつもわかりません。

- テーブルって何ですか？
- チェインって何ですか？
- ターゲットって何ですか？

インターネットにはたくさんの説明がありますが、どうも腑に落ちませんでした。
なので、今回は本腰入れてiptablesのドキュメントを読んで理解したいと思います。

2019.12.25 追記
iptablesを理解するために情報収集をする中で、素晴らしいリファレンスの日本語訳サイトを見つけました。
正確な知識をつけるために以下を参照することをおすすめします。
[Iptablesチュートリアル 日本語訳](https://www.asahi-net.or.jp/~aa4t-nngk/ipttut/)
テーブルとチェインの概要をつかむのであれば、[Chapter 6](https://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/ipttut_all.html#TRAVERSINGGENERAL)を見るのがよいと思います。

# アウトライン

1. まずiptableのマニュアルのDESCRIPTION, TAGETS, TABLESを読み、基礎知識を学び整理します。
2. その後、@suinさんの「[俺史上最強のiptablesをさらす](https://qiita.com/suin/items/5c4e21fa284497782f71)」を読み解きます。

~~~ bash
$ man iptables
~~~

以下、iptables 1.6.1のマニュアルを抜粋して読みます。

# DESCRIPTION

DESCRIPTIONを読むことで以下が分かります。

- iptablesが何をするものか
- テーブルとチェインとターゲットの概念

> Iptables  and  ip6tables are used to set up, maintain, and inspect the tables of IPv4 and IPv6 packet filter rules in the Linux kernel.  Several different tables may be defined.  Each table contains a number of built-in chains and may also contain user-defined chains.

- Linux kernelには、IPv4, IPv6 のパケットフィルターのルールのテーブルがある。
- iptablesはそのset upとmaintainとinspectをするために使用される。
- いくつかの異なるテーブルが定義されているだろう。
- 各テーブルはビルトインのチェインやユーザ定義のチェインがあればそれを含む。
 
> Each  chain  is  a  list  of  rules which can match a set of packets.  Each rule specifies what to do with a packet that matches.  This is called a `target', which may be a jump to a user-defined chain in the same table.

- 各チェインはパケットの集合にマッチするルールのリストである。
- 各ルールはマッチしたパケットに何をするか指定する。
- この「何をするか」をターゲットと呼ぶ。  
  （同じテーブル内のユーザ定義のチェインへのジャンプということもある。

## まとめ

1. **テーブル**はLinux kernelに存在するパケットフィルターのテーブルを指す  
   テーブルは複数存在し、各テーブルがチェインを含む
1. **チェイン**はパケットをマッチさせるルールのリスト
1. **ターゲット**はマッチしたパケットに何をするか。

# TARGETS

TARGETSを読むことで以下が分かります。

- パケットマッチしなかったらどう処理されるか、マッチしたらどう処理されるか
- ACCEPT, DROP, RETURNというターゲットについて

> A  firewall  rule specifies criteria for a packet and a target.  If the packet does not match, the next rule in the chain is examined; if it does match, then the next rule is specified by  the  value  of  the  target, which  can  be  the name of a user-defined chain, one of the targets described in iptables-extensions(8), or one of the special values ACCEPT, DROP or RETURN.

- パケットがマッチしなかったら、次のルールを試す。
- パケットがマッチしたら、次のルールはターゲットの値によって指定される。
- そのターゲットの値はユーザ定義のチェインか、特別な値である、ACCEPT, DROP, RETURNである。

> ACCEPT means to let the packet through.  DROP means to drop the packet on  the  floor.   RETURN  means  stop traversing this chain and resume at the next rule in the previous (calling) chain.  If the end of a built-in chain is reached or a rule in a built-in chain with target RETURN is matched, the target  specified  by  the chain policy determines the fate of the packet.

- ACCEPTはパケットを通過させる
- DROPはパケットを床に落とす、つまり棄てる
- RETURNはチェインの走査を停止し、呼び出し元のチェーンの次のルールから再開する
- ビルトインのチェインの終わりに達するか、ビルトインチェインでRETURNにマッチした場合、そのパケットの運命は、そのチェインのポリシーによって指定される

## まとめ

- ターゲットにはACCEPT, DROP, RETURNがある
- ビルトインチェインのルールに一つもマッチしなかった、パケットの扱いはポリシーによって指定される

※REJECTはman iptables-extensionsを参照ください。

# TABLES

TABLESを読むことで以下が分かります。

- 複数存在するテーブルには何があるか
- filterテーブルに存在するビルトインのチェインとは

> There are currently five independent tables (which tables are present at any time depends on the kernel configuration options and which modules are present).
> The tables are as follows

- カーネルのコンフィグによるが、現在5つの独立したテーブルがある
- それはfilter, nat, mangle, raw, securityである

ここではfilterテーブルとnatテーブルのみ意訳します。

> filter:
> This is the default table (if no -t option is passed). It contains the built-in chains INPUT (for packets  destined to local sockets), FORWARD (for packets being routed through the box), and OUTPUT (for locally-generated packets).

- filterテーブルは-tオプションを使わなかった場合のデフォルトのテーブルである
- このテーブルはビルトインの以下のチェインをもつ  
  - INPUT（ローカルソケット宛のパケット用）
  - FORWARD（通過するようにルーティングされるパケット用）
  - OUTPUT（ローカルで生成されるパケット用）

> nat:
> This table is consulted when a packet that creates a new connection is encountered.  It  consists of four built-ins: PREROUTING (for altering packets as soon as they come in), INPUT (for altering packets destined for local sockets), OUTPUT (for altering locally-generated packets before  routing),  and  POSTROUTING  (for altering packets as they are about to go out).  IPv6 NAT support is available since kernel 3.7.

- natテーブルは新規コネクションを作成するパケットを検出すると参照される
- このテーブルはビルトインの以下の4つのチェインをもつ
  - PREROUTING（入って来るパケットの改変用）
  - INPUT（ローカルソケット宛のパケットの改変用）
  - OUTPUT（ローカルで生成されるパケットのルーティング前の改変用）
  - POSTROUTING（出て行くパケットの改変用）

# filterテーブルの図解

ここまでの理解を図にしてみます。

![Screenshot from 2019-12-24 11-16-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/9d69b880-226f-dc2c-8879-7a2989529509.png)

- filterテーブルがあり、その中にはビルトインの３つのチェインとユーザ定義のチェインがある
- ローカルソケット宛のパケットはINPUTチェインで、通過するようルーティングされるパケットはFORWARDチェインで、ローカルで生成されるパケットはOUTPUTチェインで、ルールにマッチするか調べられる
- 各チェインにはルールがありマッチすれば、ACCEPT, DROP, RETURNされるかユーザ定義のチェインにジャンプする
- マッチしない場合はチェインのポリシーでACCEPTかDROPに処理が決まる

# 「[俺史上最強のiptablesをさらす](https://qiita.com/suin/items/5c4e21fa284497782f71)」を読み解く

ここまでの得た知識で抜粋して読んでみます。

## ポリシーの決定

~~~ bash
iptables -P INPUT   DROP # すべてDROP。すべての穴をふさいでから必要なポートを空けていくのが良い。
iptables -P OUTPUT  ACCEPT
iptables -P FORWARD DROP
~~~

> -P, --policy chain target

ビルトインのチェインにポリシーを設定しています。
パケットがチェインのルールリストにマッチしなかった場合の最終的な扱いを決めています。

INPUTとFORWARDチェイン（に含まれるルールリスト）の対象となるパケットが、いずれのルールにもマッチしなかった場合にはDROPするとしています。

まず、このポリシーを設定し、これ以降でACCEPTターゲットを持つルールを追加することで許可するパケットを決めていきます。
これがホワイトリスト言われる理由だと思います。

## 信頼可能なホストは許可

``` bash
# lo はローカルループバックのことで自分自身のホストを指す
iptables -A INPUT -i lo -j ACCEPT # SELF -> SELF
```

> -A, --append chain rule-specification
> -i, --in-interface name
> -j, --jump target

INPUTチェインにルールを追加しています。
loに来たパケットにマッチし、ACCEPTしています。

## 攻撃対策: Stealth Scan

``` bash
iptables -N STEALTH_SCAN # "STEALTH_SCAN" という名前でチェーンを作る
iptables -A STEALTH_SCAN -j LOG --log-prefix "stealth_scan_attack: "
iptables -A STEALTH_SCAN -j DROP
```

> -N, --new-chain chain

STEALTH_SCANというユーザ定義のチェインを作成し、そのチェインに、LOG, DROPへjumpするルールをappendしています。

LOGターゲットは処理を行った後に終了せず、次のルールを処理します。
※man iptables-extentionsのLOGを参照
> This  is  a "non-terminating target", i.e. rule traversal continues at the next rule.

上記設定は、STELALTH_SCANチェインにログを残すルールとパケットを破棄するルールを登録しています。
このチェインにjumpしたら順にログを残し、パケットが破棄されます。

そしてこのチェインへのジャンプのするための設定が以下です。

```
# ステルススキャンらしきパケットは "STEALTH_SCAN" チェーンへジャンプする
iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j STEALTH_SCAN
...# 続きは省略
```

ステルススキャンと思しきパケットをマッチしSTELALTH_SCANチェインにジャンプするルールをINPUTに追加しています。
※ -p tcp --tcp-flags, -m state --state NEWはステルススキャンと思しきパケットをマッチさせる設定だと思います。  
  ここではステルススキャンについては扱わないので深入りしません。

-j ACCEPT等がjumpであるのに最初は違和感がありましたが、
ACCEPT, DROP, RETURNを特殊なチェインと捉えることで違和感はなくなりました。

# まとめ

ここまでで大筋が読めるようになりました。
パケットをマッチさせるオプションを学習すればとりあえず、「[俺史上最強のiptablesをさらす](https://qiita.com/suin/items/5c4e21fa284497782f71)」は理解できそうです。

ただし、「[俺史上最強のiptablesをさらす](https://qiita.com/suin/items/5c4e21fa284497782f71)」はINPUTチェインへのルール登録のみのため、
FORWARDやOUTPUTに関して理解ができていません。
次回はこの辺をもう少し掘ってみたいと思います。←以下を書きました。

- [試して学ぶiptables、ウェブ閲覧できるまで](https://qiita.com/pojiro/items/dcd6149c48cde6a0843d)
- [試して学ぶiptablse、ポートフォワード](https://qiita.com/pojiro/items/c9a57c73f0bdf13b2843)

2019.12.25 追記
iptablesを理解するために情報収集をする中で、素晴らしいリファレンスの日本語訳サイトを見つけました。
正確な知識をつけるために以下を参照することをおすすめします。
[Iptablesチュートリアル 日本語訳](https://www.asahi-net.or.jp/~aa4t-nngk/ipttut/)
テーブルとチェインの概要をつかむのであれば、[Chapter 6](https://www.asahi-net.or.jp/~aa4t-nngk/ipttut/output/ipttut_all.html#TRAVERSINGGENERAL)を見るのがよいと思います。

この記事がもしあなたの理解の助けになったら幸いです。
**「いいね」よろしくお願いします。**:wink: