AWS NATインスタンスを作成したメモ


AWSでEC2とWorkspacesを1つのVPCに入れて NATを構成しました。
昔とった杵柄でちょろいと思いきや、色んなところにハマりまくったので、記録しておきます。

# 要件

* VPC内にEC2数台と、Workspaces数台を構築
* VPC内でEC2とWorkspacesは相互に通信する
* EC2とWorkspacesからVPC外（インターネット）にアクセス可能
* VPC外から一部のEC2 Webサーバーにアクセスできる（ポート転送）


# 完成形

以下、アドレスやポート番号、IDなどはダミーです。
また、設定する順番通りには記載していないので、手順については以下のサイトの通りです。

http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html


## 構成図

![Qiita.png](https://qiita-image-store.s3.amazonaws.com/0/45711/ba77c14d-05d7-5918-9db6-5705d553bbd5.png "Qiita.png")


## NAT instanceの設定

### インスタンスの作成

今回は、「amzn-ami-vpc-nat-hvm-2015.03.0.x86_64-gp2」というAMIから作成しました。
コミュニティAMIで「amzn-ami-vpc-nat」で検索して一番上にあったのを素直に選択しました。

### 送信元/送信先チェックを無効にする

EC2 コンソールで NATインスタンスを選択して、「ネットワーキング」→「送信元/送信先の変更チェック」で無効にしておく。

### ポート転送

デフォルトだと無効になってます。

```
$ sysctl net.ipv4.conf.all.forwarding
net.ipv4.conf.all.forwarding = 0
```

有効にします。

```
$ sudo sysctl net.ipv4.conf.all.forwarding=1
net.ipv4.conf.all.forwarding = 1 
```

### NATの設定

iptablesを書きます。

```/etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.0.0/16 -o eth0 -j MASQUERADE
-A PREROUTING  -i eth0 -d 192.168.10.100 -p tcp -m tcp --dport 80   -j DNAT --to 192.168.32.101
-A PREROUTING  -i eth0 -d 192.168.10.100 -p tcp -m tcp --dport 8080 -j DNAT --to 192.168.32.102:8080
-A POSTROUTING -o eth0 -d 192.168.32.101  -p tcp -m tcp --dport 8080 -j SNAT --to-source 192.168.10.100
-A POSTROUTING -o eth0 -d 192.168.32.102  -p tcp -m tcp --dport 80   -j SNAT --to-source 192.168.10.100
COMMIT
```

サービス再起動すると反映されます。

```
$ sudo service iptables restart
```


## VPCの設定


IPv4 CIDRブロック 192.168.0.0/16

### サブネット

| 名前 | CIDR |
|:---------|:---------------|
| Public   | 192.168.0.0/20 |
| Private1 | 192.168.32.0/21 |
| Private2 | 192.168.48.0/21 |

### ルートテーブル

| サブネット | 送信先 | ターゲット |
|:---------|:------|:----------|
| Public   | 192.168.0.0/16 | local |
|          | 0.0.0.0/0 | igw-xxxxxxxx(*1) |
| Private1 | 192.168.0.0/16 | local |
|          | 0.0.0.0/0 | eni-xxxxxxxx(*2) |
| Private2 | 192.168.0.0/16 | local |
|          | 0.0.0.0/0 | eni-xxxxxxxx(*2) |

(*1) ゲートウェイを指定する
(*2) NAT Instanceを指定する

## セキュリティグループの設定

AWSの推奨を参考にしつつこんな感じ。

| ポート範囲 | ソース |
|:---------|:------|
| すべてのTCP   | 192.168.0.0/16 |
| すべてのICMP - IPv4   | 192.168.0.0/16 |
| 80       | (参照元Global IP) |
| 8080     | (参照元Global IP) |
| 22       | (管理者のGlobal IP) |


# ハマったこと

## 起動済のEC2のVPCを変更できない

オンプレだと、ネットワークケーブル引っこ抜いて挿し直せば良いだけなので、意外と罠。
一度、AMIを作成し、設定しておいたVPCでイメージからインスタンスを起動すればOKです。

## EC2を作り直したらSSH接続できなくなった

NAT関係ないですが。
AMIからEC2インスタンスを作り直すと finger printが変わるため、sshするとエラーになります。

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
(後略)
```

すいません、NASTYなことしたのは、私です。
ローカルの .ssh/known_hostsを開いて、IPアドレスで接続先を特定し、その行を削除すればOKです。

## Workspacesには、subnetが3つ必要

Public 1つと、Private 2つが必要でした。
NAT Instanceのドキュメントを見て Subnet 2つで進めてたら、Workspaces立てるところでドボンしました。
ちなみに、Workspacesのドキュメントには明記されていましたので、計画性のある向きはハマらないと思う。

## DockerホストもIP転送を有効にする必要あり

これも単に再起動したから発生した問題ですが、ちょっとハマった。
EC2上でDockerコンテナを立てていたインスタンスで、IP転送が無効になっていたため、コンテナから通信できなくなっていました。


## NAT instanceにはVPC内のローカルIPで入ってくる

当初iptablesでこんな風に書いていたのですが、ポート転送されずに???となりました。

```
-A PREROUTING  -i eth0 -d 118.123.123.123 -p tcp -m tcp --dport 80   -j DNAT --to 192.168.32.101
```

tcpdumpで見てみて、NAT instanceに入ってきた時点で、VPC内のローカルIPになっていることが判りました。
結果として、前記の設定でポート転送に成功しました。

# 感想

AWSが良きに計らってくれるところと、自分でケアしなければいけないところの境界線がハマりポイントでした。