Region 間接続を VPC の VPN 機能と VyOS でやってみた

# はじめに
AWS VPC にある [VPN 接続機能](http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_VPN.html)を設定してみましたので、その内容についてシェアします。VPC と VPN 接続をするルータとしては VyOS というソフトウェアルータを使用しました。VyOS の AMI はAWS Marketplace、Community AMIs にありますので、ハードウェアルータを用意できない人でも VPN 接続を簡単に試せてオススメです。

# 前提
EC2、VPC についてはある程度の知識がある前提で話を進めます。たとえば、Network ACL、 Route Table というワードを聞いて全然ピンとこない場合はひと通り、[ドキュメント](http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Introduction.html)を読んでみることをオススメします。また、Subnet 等の VPC に限らない概念についても最低限、知っておく必要はあります。と、偉そうに書きましたが、筆者も元々はアプリケーションエンジニア出身でネットワークについては素人同然なので、適宜、勉強すればなんとかなると思います。

また、VyOS のバージョンは 1.0.5 を利用しました。はじめ、1.1.0 を利用していたのですが、うまくいかず、ネットを彷徨っていたら、以下の記事をみつけました。ご注意ください。
http://www.lockon.co.jp/officialblog/engineer/10042/ 
> ※注意 VyOSのver 1.1.0, 1.1.1では、VPN経由のパケットを正しくルーティングできないという致命的なバグがありました。最新のVyOSでは確認できていませんが、もしVPN経由のパケットがルーティングできない場合には、ver.1.0.5をお使いください。

# 構成
今回、試してみた構成図は以下のようなものです。

![Inter Region Connection for qiit (1).png](https://qiita-image-store.s3.amazonaws.com/0/19376/fda51995-9696-3690-5a56-4bf1eff58ce9.png)


左側に Oregon Region、右側に Tokyo Region があり、Oregon Region の Virtual Private Gateway (以下、VGW[^1]) と Tokyo Region の Customer Gateway(以下、CGW) を VPN 接続します。CGW はここでは VyOS のことを指します。あなたが準備する必要があるルータのことです。ここでは便宜上、CGW も AWS 上にいますが、一般的には、オンプレだったりオフィスのネットワーク内にいるルータになるかと思います[^2]。下部にある図は CGW と VGW 内のルータが Link-local address を利用して VPN コネクションを張っている図になります。

それでは、各コンポーネントについて説明します。

## Customer Gateway
一言でいうなら、VGW に接続する IPSec トンネルのエンドポイントが CGW です。設定ファイル等は AWS マネジメントコンソールから落とせるので便利だが、今回の例では一部修正が必要なので、後ほどその点については触れます。詳細は[こちら](http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/NetworkAdminGuide/Introduction.html)を参照ください。

## Virtual Private Gateway
AWS 側にある VPN のエンドポイントになります。こちらはユーザ側は特に意識することなく、AWS 側がよしなに管理してくれます。画面からは Name Tag を入力して Create するだけです。このとき生成される vgw ID を Route Table で指定することで VPN 接続先に適切にルーティングされます。

## VPN Connection
### Tunnel が２つある
マネジメントコンソールから VPN 接続を Create すると VPN Tunnel が2つ生成されます。また、VGW 内の各ルータの IP Address、Status なども確認できます。CGW の設定をしていなければ、Status は DOWN のままのはずです。

### Link-local address
VGW 内には2つのルータがあり、CGW は1つのルータのみです。CGW 側の設定ファイルをみると VTI (Virtual Tunnel Interface) として vti0 の address が 169.254.249.58/30、vti1 の address が 169.254.249.62/30 となっています。Link-local address を利用して CGW には仮想的にインターフェースが2つあり、その仮想インターフェースを通じて2つのトンネルをつくって VPN の通信を実現しているようです。

```
interfaces {
...
    vti vti0 {
        address 169.254.249.58/30
        description "VPC tunnel 1"
        mtu 1436
    }
    vti vti1 {
        address 169.254.249.62/30
        description "VPC tunnel 2"
        mtu 1436
    }
}
```

### UDP 500 と IP protocol 50
VPN over IPSec では 秘密鍵の交換を安全に行うためのプロトコルとして IKE を利用し、これが UDP の500番ポートを利用します。また、パケットの認証、暗号化として ESP を利用し、これが IP プロトコル番号 50 で通信をします。IKE には Phase 1 と Phase 2があるようで、細かい話は別途参照ください。とりあえず、UDP 500 と IP protocol 50 を使うことだけを押さえておけばなんとかなると思います。下記は juniper のサイトですが、一般的な話だと思うので参考になると思います。
http://kb.juniper.net/InfoCenter/index?page=content&id=KB5671
> [ScreenOS] What ports are used for a Virtual Private Network (VPN)?
> ...
> Internet Protocol Security (IPSec) uses IP protocol 50 for Encapsulated Security Protocol (ESP), IP protocol 51 for Authentication Header (AH), and UDP port 500 for IKE Phase 1 negotiation and Phase 2 negotiations. UDP ports 500 and 4500 are used, if NAT-T is used for IKE Phase 1 negotiation and Phase 2 negotiations

ちなみに、AWS で Security Group をつくると、デフォルトでは Outbound がすべて許可されています。この状態で、VyOS の Security Group を設定すると、特に、Inbound の設定で UDP 500、Ip Protocol 50 を明示的に許可しなくても、VPN の STATUS は UP になります。はじめ、Inbound を許可してないのに、なんで VPN 接続に成功したのか不思議だったのですが、察するに、CGW 側から IKE の negotiation を開始したからだと納得しました。つまり、CGW 側から negotiation が開始する場合は、当然、Outbound はすべて許可されているので通信ができ、AWS の Security Group は Stateful なため、Outbound で出て行った通信に対する戻りの Inbound に対しては明示的に許可していなくても通信ができるようです。ためしに、Outbound の設定もすべて許可するのではなく、1つずつ明示的に許可するようにして、わざと UDP 500 を許可しないようにすれば（もしくは Network ACL で明示的に Deny する）、VPN の STATUS が DOWN のままになるはずです。

また、VPC では NAT トラバーサルはサポート外のようですので、CGW は Global IP が必須ということでしょうか。
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/NetworkAdminGuide/Introduction.html
> カスタマーゲートウェイの外部インターフェイスのアドレスは、静的アドレスである必要があります。カスタマー ゲートウェイは、ネットワークアドレス変換（NAT）を実行するデバイスの背後に存在する可能性があります。ただし、NAT トラバーサル（NAT-T）はサポートされていません。VPN 接続の要件の詳細については、『Amazon VPC ユーザーガイド』の「VPN 接続に必要なもの」を参照してください。

# 作業内容
それでは、ざっと作業手順を紹介します。
 1. [Tokyo/Oregon] VPC をつくる
 2. [Tokyo/Oregon] Subnet をつくる
 3. [Tokyo/Oregon] Internet Gateway をつくって、Route Table に設定する
 4. [Oregon] EC2 インスタンスを1つ起動する
 5. [Tokyo] VyOS インスタンスと EC2 インスタンスを起動する。 VyOS は EC2 の設定で Source/Dest Check をオフる。
 6. [Oregon] CGW をつくる。Routing は Static で IP Address は VyOS の Global IPを。
 7. [Oregon] VGW をつくる
 8. [Oregon] VPN をつくる。CGW, VGWは上でつくったものを指定、Routing Options は Dynamic でOKです。
 9. [Oregon/Tokyo] VPN の config をマネジメントコンソールから落として、その内容を VyOS に反映させる。
    ただし、以下の項目を修正する。デフォルトでは local-address が VyOS の Global IP になっているので、Private IP に修正する。
```
set vpn ipsec site-to-site peer 205.251.233.120 local-address '52.69.xx.xx'
set vpn ipsec site-to-site peer 205.251.233.122 local-address '52.69.xx.xx'
↓
set vpn ipsec site-to-site peer 205.251.233.120 local-address '172.100.0.200'
set vpn ipsec site-to-site peer 205.251.233.122 local-address '172.100.0.200'
```
10. [Oregon] Route Table で、Tokyo リージョンへの Destination の Target が VGW になっていることを確認。
11. [Tokyo] Route Table で、Oregon リージョンへの Destination の Target が VyOS になっていることを確認。
以上で VPN 接続されるはずです。各インスタンスにログインして ping を打って疎通確認しましょう。VyOS から Oregon のインスタンスに ping を打つときは以下の様に interface を指定して試しましょう。ping をうける側のインスタンスで tcpdump で icmp を watch するとわかりやすいです。

```
$ ping 10.10.0.39 interface 172.100.0.27

$ sudo tcpdump icmp
```


# 最後に
以上、Region 間接続を VPC の VPN 機能と VyOS でやってみるための手順でした。いかかでしょうか？ネットワーク系は Subnet だったり、VGW、CGW と作業することが多いので、図を書いて整理しながら進めるとトラブルシューティングもはかどると思います。


[^1]: Virtual Private Gateway なんだから VPG じゃないのかよ！と突っ込みたくなりますが、マネージメントコンソールで Virtual Private Gateway を作成すると、その ID として vgw-xxxxx といったID が振られます。 おそらく Customer Gateway を CGW としてるのでそっちと統一感をもたせてるためでしょう。
[^2]: "一般的"と書きましたが、[VPC Peering](http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-peering.html) は同一 Region である必要があり、VPC では Region 間接続をサポートする機能はないので(2015/6/18現在)、今回のユースケースも十分一般的かもしれません。