Akamai's cloud computing servicesとAWSをSite-to-Site VPNで接続をする（単体構成編）

# 本構成について

Akamai's cloud computing services上に構築したインスタンスとAWSのインスタンス間の通信を行う際にはインターネット経由で通信を行う必要があります。
今回はLinodeインスタンスにstrongSwanとFRRoutingを構築して、AWSのSite-to-Site VPNに接続し、安全な通信経路とBGPによる動的ルーティングを構築します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/f22e8f5a-c1dd-d927-78a3-61cde6fa8049.png)


本構成では単一のインスタンス構成となりますが、冗長化する場合のブログは以下となります。

https://qiita.com/isss802/items/58176dba5aa688843e2a

https://qiita.com/isss802/items/08b1e5538d1af714be95

## strongSwan とは

strongSwanはLinuxカーネル上で動作するオープンソースのIPsecを実装することができるVPNソリューションです。
また、strongSwanはIKEv1とIKEv2をサポートしており、エンドツーエンドのセキュアな通信を提供することができます。

https://www.strongswan.org/

## FRRouting とは

Free Range Routing(FRR)は、Quaggaから派生したUNIX/Linuxプラットフォーム上で動作するオープンソースのルーティングプロトコルを管理するソリューションです。
BGP/OSPF/RIP/MPLSなどのさまざまなルーティングプロトコルを実装しており、Cisco独自のEIGRPもサポートしています。

https://frrouting.org/

## Akamai's cloud computing servicesでインスタンスを作成する

今回は、Linode 4GBのインスタンスをVLANに対応しているシンガポールリージョンに作成します。

OSはUbuntu 22.04 LTSを利用しています。

Public IP Addressを控えておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/65709238-4f33-1722-360a-db0ae71ed3ae.png)

同一リージョン内にあるインスタンスからの疎通を実現するため、VLANインターフェイスを追加します。

https://qiita.com/110hideki/items/aead6f2bc9ff1563641c

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/3a1700f5-2b57-e2cb-1b42-a1777fe62492.png)


## AWS Site-to-Site VPNを設定する

AWS Site-to-Site VPNを設定します。

設定に関しては以下のドキュメントを参考にして構築します。

https://docs.aws.amazon.com/ja_jp/vpn/latest/s2svpn/SetUpVPNConnections.html

設定が完了したら、Site-to-Site VPNの設定をダウンロードします。

設定値のみの確認に利用するためどのConfigでも問題はないのですが、今回はCisco IOS を参考にします。

## Linode にstrongSwanを構築する

strongSwanをインストールします。

```
sudo apt update
sudo apt install strongswan
```

IPsecの設定ファイルを作成します。

```
vim /etc/ipsec.conf

config setup
        charondebug="all"
        uniqueids=yes
        strictcrlpolicy=no
conn %default
        leftauth=psk
        rightauth=psk
        ike=aes128-sha1-modp1024!
        ikelifetime=28800s
        aggressive=no
        esp=aes128-sha1-modp1024!
        lifetime=3600s
        type=tunnel
        dpddelay=10s
        dpdtimeout=30s
        keyexchange=ikev1
        rekey=yes
        reauth=no
        dpdaction=restart
        closeaction=restart
        leftsubnet=0.0.0.0/0,::/0
        rightsubnet=0.0.0.0/0,::/0
        leftupdown=/etc/ipsec-vti.sh
        installpolicy=yes
        compress=no
        mobike=no
conn AWS-VPC-GW1
        # Customer Gateway IP:
        left=<Linode Public IP Address>
        # Virtual Private Gateway IP:
        right=<AWS Tunnel IP Address 1>
        auto=start
        mark=100
        #reqid=1
conn AWS-VPC-GW2
        # Customer Gateway: :
        left=<Linode Public IP Address>
        # Virtual Private Gateway :
        right=<AWS Tunnel IP Address 2>
        auto=start
        mark=200
```

鍵の情報を設定ファイルに追記します。
シークレットの情報はダウンロードした設定ファイル内に記載されています。

```
vim /etc/ipsec.secrets

<Linode Public IP Address> <AWS Tunnel 1 Outside IP address> : PSK "<AWS Tunnel 1 Pre-shared key>"
<Linode Public IP Address> <AWS Tunnel 2 Outside IP address> : PSK "<AWS Tunnel 2 Pre-shared key>"
```

トンネルインターフェイスが起動もしくは停止した際に動作するスクリプトを配置します。

```shell
vim /etc/ipsec-vti.sh

#!/bin/bash

#
# /etc/ipsec-vti.sh
#

IP=$(which ip)
IPTABLES=$(which iptables)

PLUTO_MARK_OUT_ARR=(${PLUTO_MARK_OUT//// })
PLUTO_MARK_IN_ARR=(${PLUTO_MARK_IN//// })

case "$PLUTO_CONNECTION" in
    AWS-VPC-GW1)
        VTI_INTERFACE=vti1
        VTI_LOCALADDR=169.254.173.126/30
        VTI_REMOTEADDR=169.254.173.125/30
    ;;
    AWS-VPC-GW2)
        VTI_INTERFACE=vti2
        VTI_LOCALADDR=169.254.139.82/30
        VTI_REMOTEADDR=169.254.139.81/30
    ;;
esac

case "${PLUTO_VERB}" in
    up-client)
        $IP link add ${VTI_INTERFACE} type vti local ${PLUTO_ME} remote ${PLUTO_PEER} okey ${PLUTO_MARK_OUT_ARR[0]} ikey ${PLUTO_MARK_IN_ARR[0]}
        sysctl -w net.ipv4.conf.${VTI_INTERFACE}.disable_policy=1
        sysctl -w net.ipv4.conf.${VTI_INTERFACE}.rp_filter=2 || sysctl -w net.ipv4.conf.${VTI_INTERFACE}.rp_filter=0
        $IP addr add ${VTI_LOCALADDR} remote ${VTI_REMOTEADDR} dev ${VTI_INTERFACE}
        $IP link set ${VTI_INTERFACE} up mtu 1436
        $IPTABLES -t mangle -I FORWARD -o ${VTI_INTERFACE} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
        $IPTABLES -t mangle -I INPUT -p esp -s ${PLUTO_PEER} -d ${PLUTO_ME} -j MARK --set-xmark ${PLUTO_MARK_IN}
        $IP route flush table 220
    ;;
    down-client)
        $IP link del ${VTI_INTERFACE}
        $IPTABLES -t mangle -D FORWARD -o ${VTI_INTERFACE} -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
        $IPTABLES -t mangle -D INPUT -p esp -s ${PLUTO_PEER} -d ${PLUTO_ME} -j MARK --set-xmark ${PLUTO_MARK_IN}
    ;;
esac

# Enable IPv4 forwarding
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.eth0.disable_xfrm=1
sysctl -w net.ipv4.conf.eth0.disable_policy=1
sysctl -w net.ipv4.conf.eth1.disable_xfrm=1
sysctl -w net.ipv4.conf.eth1.disable_policy=1
```

実行権限を付与します。

```
chmod +x /etc/ipsec-vti.sh
```

strongSwanのサービスを再起動します。

```
sudo systemctl restart strongswan-starter.service
sudo systemctl enable strongswan-starter.service
```

ステータスが問題なく、IPsecの接続が問題なくされていることを確認します。

```
sudo systemctl status strongswan-starter.service
sudo ipsec status
sudo ipsec statusall
```

IPsecの接続先であるインターフェイスに接続可能であることを確認します。

```
root@localhost:~# ping 169.254.139.81
PING 169.254.139.81 (169.254.139.81) 56(84) bytes of data.
64 bytes from 169.254.139.81: icmp_seq=1 ttl=254 time=69.8 ms
64 bytes from 169.254.139.81: icmp_seq=2 ttl=254 time=70.0 ms
```

## LinodeにFRRoutingを構築する

FRRoutingをインストールし、BGPによる動的ルーティングを構築します。

```
sudo apt install frr
```

BGPを有効化します。

```
sudo sed -i.org 's/bgpd=no/bgpd=yes/' /etc/frr/daemons
```

サービスを再起動します。

```
sudo systemctl restart frr
sudo systemctl enable frr
```

コンソールにログインし、BGPの設定を行います。

```
vtysh

Hello, this is FRRouting (version 8.1).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

localhost# conf t
localhost(config)#
router bgp <Linode BGP AS>
 bgp log-neighbor-changes
 no bgp ebgp-requires-policy
 bgp graceful-restart
 timers bgp 3 9
 neighbor <AWS Tunnel 1 Inside IPv4 Address> remote-as <AWS BGP AS>
 neighbor <AWS Tunnel 2 Inside IPv4 Address> remote-as <AWS BGP AS>
 !
 address-family ipv4 unicast
  network 10.0.1.0/24
  neighbor <AWS Tunnel 1 Inside IPv4 Address> soft-reconfiguration inbound
  neighbor <AWS Tunnel 2 Inside IPv4 Address> soft-reconfiguration inbound
 exit-address-family
exit
!
```

BGPのStateが問題ないことを確認します。

```
localhost# show ip bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier , local AS number 65000 vrf-id 0
BGP table version 9
RIB entries 3, using 552 bytes of memory
Peers 2, using 1446 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
169.254.139.81  4      64512     33101     33114        0    0    0 20:23:24            1        2 N/A
169.254.173.125 4      64512     33102     33116        0    0    0 20:23:31            1        2 N/A
```

BGPで経路を受け取っていることを確認します。

```
localhost# show ip route bgp
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

B>* 10.0.0.0/24 [20/100] via 169.254.139.81, vti2, weight 1, 20:24:53
```

設定を保存します。

```
localhost# write memory
Note: this version of vtysh never writes vtysh.conf
Building Configuration...
Integrated configuration saved to /etc/frr/frr.conf
[OK]
```

## AWSの設定を確認

AWSのBGPステータスがUpしていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/4a0c0dc7-bbd9-078b-dd31-9d48bf98b153.png)

経路がRouteTableに自動的に伝播されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/63ced59a-32d4-445f-18b3-97a5da5a8efb.png)

## Linode インスタンスからの疎通確認

VLANの設定を行ったLinodeインスタンスを構築し、疎通確認をします。

AWSのVPCのネットワークへの経路を構築したVPNインスタンスを経由するように設定します。

Network設定の書き換えを行うため、上書きされないようにAuto-configure networkingを無効にします。

https://www.linode.com/docs/products/compute/compute-instances/guides/network-helper

無効にした後に設定を追記します。


```
vim /etc/systemd/network/05-eth1.network

[Route]
Destination=10.0.0.0/24
Gateway=10.0.1.2
```

尚、一時的に経路確認したい場合にはコマンドでも追加可能です。

```
sudo ip route add 10.0.0.0/24 via 10.0.1.2
```

設定を反映させます。

```
netplan apply
```

経路が追加されたことを確認します。

```
root@localhost:~# ip route
default via 172.104.40.1 dev eth0 proto static
10.0.0.0/24 via 10.0.1.2 dev eth1 proto static
10.0.1.0/24 dev eth1 proto kernel scope link src 10.0.1.1
172.104.40.0/24 dev eth0 proto kernel scope link src 
```

AWSに構築したインスタンスに疎通が取れ、VPNインスタンス経由であることを確認します。

```
root@localhost:~# ping 10.0.0.24
PING 10.0.0.24 (10.0.0.24) 56(84) bytes of data.
64 bytes from 10.0.0.24: icmp_seq=1 ttl=126 time=72.8 ms
64 bytes from 10.0.0.24: icmp_seq=2 ttl=126 time=72.6 ms

root@localhost:~# tracepath 10.0.0.24
 1?: [LOCALHOST]                      pmtu 1422
 1:  10.0.1.2                                              0.667ms
 1:  10.0.1.2                                              0.495ms
 2:  10.0.0.24                                            72.936ms reached
     Resume: pmtu 1422 hops 2 back 3
```

# まとめ

strongSwanとFRRoutingを利用することで、AWSのインスタンスとインターネット経由での安全な通信経路を構築することができ、経路も冗長化することができました。
ぜひ、マルチクラウドでの通信に活用していただければと思います。

# 参考サイト

今回のブログ記載ではいくつかのサイトの手順を参考にさせていただいております。

https://www.edge-cloud.net/2019/07/18/aws-site-2-site-vpn-with-strongswan-frrouting/

http://letslearntogether.info/posts/aws-linux-libreswan-p3/

https://geekdudes.wordpress.com/2019/02/01/creating-site-to-site-vpn-between-strongswan-and-amazon-aws-virtual-private-gateway-using-bgp-routing-protocol/

# 関連記事

アカマイ・テクノロジーズ合同会社はQiitaでAkamai's cloud computing services関連など開発者向けの記事を掲載しております。

https://qiita.com/xenbase/items/52e2956a64cedc772bd9