AWSでのリージョン間接続 その3 BGP冗長構成(VPN/VyOS)

#AWSリージョン間接続 BGP

VyOSでリージョン間のVPNを構築する。
冗長構成をBGPとSerfで実装する。

##構成図

![vyos_vpn_bgp.jpg](https://qiita-image-store.s3.amazonaws.com/0/49877/3d029f1a-9ce4-62ea-6672-e9ecf7b9d59b.jpeg)

##ルーティング

- 拠点間をeBGPにてピア接続を行う。
- 同一拠点間をiBGPにてピア接続を行う。
- Front SubnetのネットワークはStatic経路をBGPに再配布することによって経路公告を行う
- VyOS SubnetのネットワークはConnect経路をBGPに再配布することによって経路公告を行う
- BGPTimerは[Hello:4秒][Dead:12秒]とし検知12秒 切替1秒
- MTUは1414
- IPSec/GREでトンネルを構築
- AWSのルーティング切り替えはSerfを利用する

##AWS設定

・AmazonLinux 最新版のAMI
→RoutingTableに「対向のネットワークアドレス：VyOSのENI(Active)」を設定する

・VyOS コミュニティAMIの最新版(Version 1.1.0)
→source dest checkを無効にする
→EIPを付与する

・セキュリティグループ
→対向のEIP宛の通信を許可しておく

##Config

```
set system host-name [hostname]

set vpn ipsec ipsec-interfaces interface [if:eth0]

set vpn ipsec ike-group ike lifetime 3600
set vpn ipsec ike-group ike proposal 1 encryption aes128
set vpn ipsec ike-group ike proposal 1 hash sha1

set vpn ipsec esp-group esp lifetime 1800
set vpn ipsec esp-group esp proposal 1 encryption aes128
set vpn ipsec esp-group esp proposal 1 hash sha1

set vpn ipsec site-to-site peer [EIP] authentication mode pre-shared-secret 
set vpn ipsec site-to-site peer [EIP] authentication pre-shared-secret [パスワード]
		
set vpn ipsec site-to-site peer [EIP] authentication id [ID]
set vpn ipsec site-to-site peer [EIP] authentication remote-id [ID]

set vpn ipsec site-to-site peer [EIP] default-esp-group esp
set vpn ipsec site-to-site peer [EIP] ike-group ike
set vpn ipsec site-to-site peer [EIP] local-address [IP]
set vpn ipsec site-to-site peer [EIP] tunnel 1 local prefix [LoopbackIP]
set vpn ipsec site-to-site peer [EIP] tunnel 1 remote prefix [LoopbackIP]

set interfaces loopback lo address [LoopbackIP]
set interfaces tunnel tun0 address [VPN用アドレス]
set interfaces tunnel tun0 local-ip [LoopbackIP]
set interfaces tunnel tun0 remote-ip [対向LoopbackIP]
set interfaces tunnel tun0 mtu 1414
set interfaces tunnel tun0 encapsulation gre

#別リージョンのeBGPピア
set protocols bgp [自AS番号] neighbor [VPN用アドレス] remote-as [AS]
set protocols bgp [自AS番号] neighbor [VPN用アドレス] soft-reconfiguration inbound
set protocols bgp [自AS番号] network [VPN用ネットワークアドレス]
set protocols bgp [自AS番号] network [LoopbackIP]
set protocols bgp [自AS番号] timers holdtime 12
set protocols bgp [自AS番号] timers keepalive 4
set protocols bgp [自AS番号] parameters log-neighbor-changes

#同一AS内のiBGPピア
set protocols bgp [自AS番号] neighbor [Standby側アドレス] remote-as [AS]
set protocols bgp [自AS番号] neighbor [Standby側アドレス] soft-reconfiguration inbound
set protocols bgp [自AS番号] neighbor [Standby側アドレス] nexthop-self

#Connectルートの再配布設定
set policy prefix-list prefix-connect-to-bgp rule 10 action permit
set policy prefix-list prefix-connect-to-bgp rule 10 prefix [VyOS Subnet]
set policy route-map routemap-connect-to-bgp rule 1 action permit
set policy route-map routemap-connect-to-bgp rule 1 match ip address prefix-list prefix-connect-to-bgp
set protocols bgp [自AS番号] network [VyOS Subnet] route-map routemap-connect-to-bgp


#Staticルートの再配布設定
set policy prefix-list prefix-static-to-bgp rule 10 action permit
set policy prefix-list prefix-static-to-bgp rule 10 prefix [Front Subnet]
set policy route-map routemap-static-to-bgp rule 1 action permit
set policy route-map routemap-static-to-bgp rule 1 match ip address prefix-list prefix-static-to-bgp
set protocols bgp [自AS番号] redistribute static route-map routemap-static-to-bgp
set protocols static route [Front Subnet] next-hop [DefaultGW]

set policy route-map routemap-connect-to-bgp rule 1 set metric 100
set policy route-map routemap-static-to-bgp rule 1 set metric 100

```


##Serf

・インストール
こちらからバイナリをダウンロードして、お好きなところに配置。
https://www.serfdom.io/downloads.html


・起動用スクリプトを記載

```/opt/vyatta/etc/config/scripts/vyatta-postconfig-bootup.script
/usr/local/bin/serf agent -bind=[PrivateIP] -config-dir=/etc/serf.conf
```

・Serf Conf

/etc/serf.conf

```
{
  "node_name": "[hostname]",
  "tags": {
    "role": "[rolename]"
  },
#BGPタイマーと同じになるように設定
  "reconnect_interval": "4s", 
  "reconnect_timeout": "12s",
  "tombstone_timeout": "12s",
#メンバーから外れたらシェルを起動(Standby側のみ)
  "event_handlers": [
    "member-failed,member-leave=bash /opt/serf/ssh.sh >> /var/log/ssh.log 2>&1"
  ]
}
```


・フェールオーバー用のスクリプト作成(Standby側)

VyOSのスタンバイ側のみに設定
VyOSにパッケージの追加等を極力行いたくないためAWS-SDKが実行可能なホストのshellを起動する。

```ssh.sh
#!/bin/bash

ssh ${NAME} /opt/serf/change_eni.sh -h ${NAME}
result=$?
if [ ! $result -eq 0 ] ; then
  exit 1
fi
```


SSH先に仕込んでおく。

```change_eni.sh
#!/bin/bash

aws ec2 delete-route --route-table-id ${ROUTETABLE} --destination-cidr-block ${NETWORK} --region ${REGION}
result=$?
if [ ! $result -eq 0 ] ; then
  exit 1
fi

aws ec2 create-route --route-table-id ${ROUTETABLE} --destination-cidr-block ${NETWORK} --instance-id ${INSTANCE} --region ${REGION}
result=$?
if [ ! $result -eq 0 ] ; then
  exit 1
fi


```

##起動

起動時は自分でjoinを行う。

```
serf join [同一AS内PrivateIP]
```

##障害時

・Active側のインスタンスに障害が発生した場合、Serfが検知しAWSのルーティングを操作しStandby側へ。(検知12秒)

・Active側のインターネットに障害が発生した場合、BGPが検知しルーティングを切り替える。(検知12秒)

切り戻しのタイミングは運用に合わせるので、手動にした。

#etc...

できればVRRPを実装したかったのだが、AWSではマルチキャスト通信が行えないため実装ができない。
以下等を実装したかったのだが、技術力が足りないせいもあり実装ができなかった。
http://www.slideshare.net/kentayasukawa/multicastunicast
http://www.slideshare.net/winebarrel/ec2keepalivedlvsdsr

KeepAlivedの最新版はUnicastに対応している模様で、VyOSに組み込む方法がVPN構成の一番綺麗だと思う。

以上