iptablesを使ってポートフォワードをする

- 環境
    - 設定するところ : CentOS release 6.9 (Final)
        - iptables v1.4.7
    - 転送先 : AWS上の他のLinuxインスタンス

# 何？iptablesって？
[iptablesはファイアウォールとパケット転送ができる](http://ponsuke-tarou.hatenablog.com/entry/2019/07/17/233526)
[NATはプライベートIPアドレスとパブリックIPアドレスを組合せで変換してくれる](http://ponsuke-tarou.hatenablog.com/entry/2019/07/17/003304)

## CentOS7からはiptablesではなくてfirewalldになった
[iptablesからfirewalldへ | CentOS7ではじめるサーバー構築入門](http://cos7.it-mem.info/2019/01/19/iptables%E3%81%8B%E3%82%89firewalld%E3%81%B8/)

### とはいえ今回はCentOS6なのでiptablesに設定する

# 準備
## iptablesが有効になっていることを確認する
参考 : [しがないプログラマーの備忘録: iptablesサービスの起動状態を確認する方法](http://foolprogrammer.blogspot.com/2012/08/iptables.html)

```bash
# こんな感じに表示されると起動されているらしい
$ sudo /etc/rc.d/init.d/iptables status
Table: nat
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
```

## 転送先が見えることを確認する

```bash
# Connectedになるか確認する
$ curl -v telnet://10.0.1.2:80
* About to connect() to 10.0.1.2 port 80 (#0)
*   Trying 10.0.1.2... connected
* Connected to 10.0.1.2 (10.0.1.2) port 80 (#0)

# ポート80は、Webサーバー経由でもアクセスしてみる
$ curl http://10.0.1.2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
#省略

# Webサーバー経由の場合は、転送先のaccess_logを見ることでも、アクセスが到達したことを確認出来る
$ sudo less +F /var/log/httpd/access_log
```

# 設定ファイルを書く
設定ファイル : `/etc/sysconfig/iptables`

```conf:iptables
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 10080 -j DNAT --to-destination 10.0.1.2:80
-A POSTROUTING -d 10.0.1.2/32 -p tcp -m tcp --dport 80 -j SNAT --to-source 10.0.1.3
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
```

## natテーブルのざっくり設定の意味
参考 : [コピペから脱出！iptablesの仕組みを理解して環境に合わせた設定をしよう | OXY NOTES](https://oxynotes.com/?p=6361)

|設定項目|意味|
|:--:|:--:|
|-A（--append）|指定チェインに1つ以上の新しいルールを追加|
|PREROUTING|受信時にアドレスを変換するチェイン|
|POSTROUTING|送信時にアドレスを変換するチェイン|
|-p (--protocol)|チェックされるパケットのプロトコル|
|-m|他の拡張を有効にする|
|--dport|受信側のポート番号を指定|
|-j (--jump)|ターゲットを指定|
|DNAT|送信先のパブリックIPアドレスをプライベートIPアドレスに変換してくれる|
|SNAT|送信元のプライベートIPアドレスをパブリックIPアドレスに変換してくれる|
|--to-destination|IPアドレスとポートの範囲を指定|

`-A PREROUTING -p tcp -m tcp --dport 54321 -j DNAT --to-destination 10.0.1.1:1521`
-> 「自分(10.0.1.3)のポート54321」へ来たら「10.0.1.1:1521」へ変換する

`-A POSTROUTING -d 10.0.1.1/32 -p tcp -m tcp --dport 1521 -j SNAT --to-source 10.0.1.3`
-> 「10.0.1.1:1521」宛は「10.0.1.3(自分)」に変換する

# 設定ファイルを反映する
参考 : [iptablesをいじってた - わすれっぽいきみえ](https://kimikimi714.hatenablog.com/entry/2015/07/07/200000)

```bash
# 設定ファイルを反映する
$ sudo service iptables restart
iptables: Setting chains to policy ACCEPT: nat             [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]
iptables: Applying firewall rules:                         [  OK  ]

# natテーブルのチェインルールを順序番号付きで一覧表示する
$ sudo iptables -t nat -L --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    DNAT       tcp  --  anywhere             anywhere            tcp dpt:54321 to:10.0.1.1:1521
2    DNAT       tcp  --  anywhere             anywhere            tcp dpt:10080 to:10.0.1.2:80

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    SNAT       tcp  --  anywhere             ip-10-0-1-1.ap-northeast-1.compute.internal tcp dpt:ncube-lm to:10.0.1.3
2    SNAT       tcp  --  anywhere             ip-10-0-1-2.ap-northeast-1.compute.internal tcp dpt:http to:10.0.1.3

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
```

|iptablesコマンドのオプション|意味|
|:--:|:--:|
|-t|テーブルを指定する|
|-L, --list [CHAIN]|チェイン（省略した場合はすべて）のルールを一覧表示する|
|--line-numbers|各チェーンの規則の横にチェーン内の順序番号を出力する|

|項目|意味|
|:--:|:--:|
|num|チェーン内の順序番号|
|target|パケットをどう処理するか|
|prop|プロトコルの種類|
|opt|オプション|
|source|どこから来たのか|
|destination|目的地、行き先、送り先|

## なんかエラーになったら
[iptablesの書き方を間違えて怒られた時の原因集 - Qiita](https://qiita.com/ponsuke0531/items/56a3eb7b5228bd7f53e3)