NTTPCの激安VPS「Indigo」と自宅をIPSec-VPNでつなぐ

# はじめに
自宅内で遊びに使っているサーバ（と言う名のノートPC）がそろそろ限界に近づいているので、NTTPCコミュニケーションズのVPS「[Indigo](https://web.arena.ne.jp/indigo/)」に移行してみようと思います。自宅と同じような感覚で使うためも、VPN張りたいよね！ということで、自宅とVPS上のインスタンスをSite to Site IPSec-VPNで接続することにしました。

#前提条件
##自宅側
- FortiGate 60C（v5.2.13,build762）
    - 古っ。。
- 普通のプロバイダ契約で、DDNS使用

##VPS側
- NTT PC コミュニケーションズ「Indigo」上の、KVM Instance 1 CPU 1 GB - Ubuntu 18.04
- strongSwan U5.6.2/K4.15.0-106-generic

##ネットワーク環境

|ネットワーク|自宅側|VPS側|
|:--|:--|:--|
|グローバルIPアドレス|x.x.x.x(可変)/xxxx.fortiddns.com|y.y.y.y(固定)|
|IPSec接続用IPアドレス|172.16.1.1|172.16.1.2|
|ローカルアドレス|192.168.100.0/24|-|

![ipsec-summary.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/8d7ecaa6-bfd4-64e9-886c-8a4b10e9b544.png)



# 自宅側FortiGateの設定
## IPSecウィザード
FortiGateのIPSecウィザード「Site to Site - Cisco」をベースに作成します。
カスタムで作ってもよいのですが、一旦ウィザードで作ると、インタフェイスの設定とか、ルーティングの設定とか必要なものを自動的に作ってくれるので楽ちんです。

##トンネルの設定
ウィザードで作成したトンネルを以下のように設定します。ポイントになる設定だけ表に抜き出しているので参考にしてください。

###ネットワーク

![ipsec-tunnnel-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/30d6ff15-906a-0c68-53c9-9b621a4b20f9.png)

|項目|設定|
|:--|:--|
|リモートゲートウェイ|固定IPアドレス|
|IPアドレス|VPSのインスタンスのグローバルIPアドレス|
|インターフェイス|自宅のインターネットの出口|
|NATトラバーサル|有効（Indigoのファイアウォールを抜けるため）|

###認証
![ipsec-tunnnel-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/baed9fe1-7206-8e2e-2fc7-504e80f0961c.png)

|項目|設定|
|:--|:--|
|方式|事前共有鍵|
|事前共有鍵|適当なパスワード|
|IKEバージョン|2|


###Phase1プロポーザル
![ipsec-tunnnel-3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/e83d15c8-1fee-6bc7-6f9f-6f96153c5d1a.png)

|項目|設定|
|:--|:--|
|暗号化|AES256|
|認証|SHA256|
|Diffie-Hellman Group|21|
|ローカルID|自宅側DDNSのFQDN（例：xxxx.fortiddns.com）|

###Phase2セレクタ
![ipsec-tunnnel-4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/cd7e5b8c-9866-32bf-e6ce-ed770ba08c33.png)

|項目|設定|
|:--|:--|
|暗号化|AES256|
|認証|SHA256|
|Diffie-Hellman Group|21|


##インタフェイス
ウィザードで作成したインタフェイスを以下のように設定をします。
![ipsec-interface.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/ae7615eb-cc68-c74e-bde0-10abe8530402.png)

|項目|設定|
|:--|:--|
|IP|IPSecで使用する自宅側のIP、ここでは`172.16.1.1`にしています。|
|リモートIP|同じくVPS側のIP、ここでは`172.16.1.2`にしています。|
|管理者アクセス|疎通確認のため、PINGだけ許可しています。|

##ルーティング
ウィザードで作成したスタティックルートを以下のように設定をします。
![ipsec-routing.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580974/5e262ef4-f700-ba8b-83aa-74f29125409e.png)

|項目|設定|
|:--|:--|
|宛先IP/マスク|インタフェイスで指定したリモートIPに設定します。|

# VPS側の設定
##必要なコンポーネントのインストール
IPSec-VPNの接続には、[strongSwan](https://www.strongswan.org/)を使用します。

```
# apt install strongswan
```

##strongSwanの設定

### ipsec.conf
strongSwanの設定ファイルです。
`right`と`left`というのがVPNのどっちがどっちかよくわからなくなりますが、先に書いた絵と同じように、`left`がVPS側、`right`が自宅側ということにしています。

```/etc/ipsec.conf:
# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
	charondebug="ike 1, knl 1, cfg 0"
	# strictcrlpolicy=yes
	# uniqueids = no

# Add connections here.

conn home
	left=y.y.y.y
	leftsubnet=0.0.0.0/0
	right=xxxx.fortiddns.com
	rightid=%any
	rightsubnet=0.0.0.0/0
	leftfirewall=no
	leftupdown=/etc/strongswan.d/updown.sh
	keyexchange=ikev2
	ike=aes256-sha256-ecp521
	esp=aes256-sha256-ecp521
	type=tunnel
	authby=secret
	auto=route
	compress=no
	mark=42
	forceencaps=yes
```

###ipsec.secrets
FortiGateに仕込んだ事前共有鍵を指定します。

```/etc/ipsec.secrets:
# This file holds shared secrets or RSA private keys for authentication.

# RSA private key for this host, authenticating it to any other host
# which knows the public part.
#
y.y.y.y xxxx.fortiddns.com : PSK "asdfasdfasdfasdfadsf"
```

###updown.sh
IPSecで無事に接続された際に実行されるスクリプトを作成します。
ここで、自宅側のネットワークをVTI経由で通信するようにルーティングの設定等を行っています。

```/etc/strongswan.d/updown.sh:
#!/bin/bash

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

echo ${PLUTO_VERB}
echo ${PLUTO_CONNECTION}

VTI_INTERFACE="vti"${PLUTO_MARK_IN_ARR}

case "${PLUTO_VERB}" in
    up-client)
        ip tunnel add ${VTI_INTERFACE} mode vti local ${PLUTO_ME} remote ${PLUTO_PEER} key 42
        ip link set ${VTI_INTERFACE} up
        ip link set ${VTI_INTERFACE} up mtu 1350
        ip addr add 172.16.1.2/32 dev ${VTI_INTERFACE}

        ip route add 172.16.1.1/32 dev ${VTI_INTERFACE}
        ip route add 192.168.100.0/24 dev ${VTI_INTERFACE}
        ;;

    down-client)
        $IP link del ${VTI_INTERFACE}
        ;;
esac
```

### ファイアウォールの設定
VPS側のファイアウォールに穴あけが必要です。[Indigoのコントロールパネル](https://indigo.arena.ne.jp/)から、ファイアウォールで以下の設定を入れます。

|方向|プロトコル|ポート|IPアドレス|
|:--|:--|:--|:--|
|IN|UDP|500(IKE)|x.x.x.x|
|IN|UDP|4500(NAT-T)|x.x.x.x|

## IPSec VPNの接続
準備ができたので早速接続してみましょう。

```
# ipsec start
Starting strongSwan 5.6.2 IPsec [starter]...

# ipsec statusall
Status of IKE charon daemon (strongSwan 5.6.2, Linux 4.15.0-106-generic, x86_64):
  uptime: 19 seconds, since Jun 21 07:41:20 2020
  malloc: sbrk 1617920, mmap 0, used 568000, free 1049920
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 3
  loaded plugins: charon aesni aes rc2 sha2 sha1 md4 md5 mgf1 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf gmp agent xcbc hmac gcm attr kernel-netlink resolve socket-default connmark stroke updown eap-mschapv2 xauth-generic counters
Listening IP addresses:
  y.y.y.y
  172.16.1.2
Connections:
        home:  y.y.y.y...xxxx.fortiddns.com  IKEv2
        home:   local:  [y.y.y.y] uses pre-shared key authentication
        home:   remote: uses pre-shared key authentication
        home:   child:  0.0.0.0/0 === 0.0.0.0/0 TUNNEL
(以下省略)
```

このように表示されてたらおそらく大丈夫かと。。
VTIと、ルーティングが設定されているかも確認しておきます。

```
# ifconfig
ens10: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet y.y.y.y  netmask 255.255.255.0  broadcast y.y.y.255
        ether XX:XX:XX:XX:XX:XX  txqueuelen 1000  (Ethernet)
        RX packets 549464753  bytes 108213055144 (108.2 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1350377  bytes 262993102 (262.9 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
vti42: flags=209<UP,POINTOPOINT,RUNNING,NOARP>  mtu 1350
        inet 172.16.1.2  netmask 255.255.255.255  destination 172.16.1.2
        tunnel   txqueuelen 1000  (IPIP Tunnel)
        RX packets 1292489  bytes 185606148 (185.6 MB)
        RX errors 93  dropped 93  overruns 0  frame 0
        TX packets 1229046  bytes 148444508 (148.4 MB)
        TX errors 424  dropped 0 overruns 0  carrier 424  collisions 0

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    0      0        0 ens10
y.y.y.y         0.0.0.0         255.255.255.0   U     0      0        0 ens10
172.16.1.1      0.0.0.0         255.255.255.255 UH    0      0        0 vti42
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 vti42
```

大丈夫そうなので、試しに、VPS側から自宅側に`ping`で疎通確認してみます。

```
# ping 172.16.1.1 -c 5
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=255 time=10.7 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=255 time=11.3 ms
64 bytes from 172.16.1.1: icmp_seq=3 ttl=255 time=10.6 ms
64 bytes from 172.16.1.1: icmp_seq=4 ttl=255 time=11.1 ms
64 bytes from 172.16.1.1: icmp_seq=5 ttl=255 time=11.0 ms

# ping 192.168.100.1 -c 5
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=255 time=11.7 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=255 time=10.3 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=255 time=11.2 ms
64 bytes from 192.168.100.1: icmp_seq=4 ttl=255 time=13.8 ms
64 bytes from 192.168.100.1: icmp_seq=5 ttl=255 time=10.5 ms
```

大丈夫ですね。

## 自動起動の設定
OS起動時に自動的に接続されるように設定しておきます。

```
# systemctl enable strongswan
```

#うまくいかなかった場合の確認ポイント
## ログを確認する。
strongSwanとかがエラーを吐いていないか、`/var/log/syslog`を確認しましょう。

## ファイアウォールを疑う
設定に間違いがないのに、うまく行かない場合はファイアウォールを疑うべきですね。

- VPS側のファイアウォール（`ufw`とか`iptables`とか）の設定を確認する。
- 自宅側のファイアウォールのポリシーを確認する。特にIPSec用に作成したインタフェイスからinternalへの通信はポリシーの設定が必要です。

## それでもだめな場合は
tcpdumpとかでパケットキャプチャをとってみましょう。

```
# tcpdump -i ens10 -f "host x.x.x.x" -w /tmp/vpn.pcap
```

私の場合は、`/etc/ipsec.conf`の`forceencaps=yes`が抜けていたせいで、NAT-Traversalが効いてなくて、ESPのパケットがVPSから自宅には飛ぶのに、自宅からVPSに飛んでこないという状況が見えていました。。


# おわりに
ちゃんとしたVPNをサービスがついているVPSであれば、こんなことしなくてもよいのかもしれませんが、strongSwanを使うことで安価なVPSと自宅をIPSec VPNで接続することができました。これでVPSの用途が広がります。
あと、VPS側のファイアウォールの設定で、自宅のグローバルIPアドレスを指定したのですが、自宅のグローバルIPアドレスは可変でDDNS運用ですので、プロバイダの都合で変わってしまいます。そうなったときでも大丈夫なように[別記事](https://qiita.com/mmmmmmmmmmmmm/items/da008ce37bd820ef264d)でDDNS運用でも大丈夫な仕組みを作っていますので、興味があればそちらも参照してください。

#参考資料

- [FortiGateとStrongSwanでSite-Site IPsec VPNを張る](https://qiita.com/tatsuya_info/items/4632f086a789732dcb6f)
    - こちら、大いに参考にさせてもらいました。感謝です。