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


はじめに

自宅内で遊びに使っているサーバ(と言う名のノートPC)がそろそろ限界に近づいているので、NTTPCコミュニケーションズのVPS「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 -

自宅側FortiGateの設定

IPSecウィザード

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

トンネルの設定

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

ネットワーク

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

認証

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

Phase1プロポーザル

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

Phase2セレクタ

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

インタフェイス

ウィザードで作成したインタフェイスを以下のように設定をします。

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

ルーティング

ウィザードで作成したスタティックルートを以下のように設定をします。

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

VPS側の設定

必要なコンポーネントのインストール

IPSec-VPNの接続には、strongSwanを使用します。

# apt install strongswan

strongSwanの設定

ipsec.conf

strongSwanの設定ファイルです。
rightleftというのが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のコントロールパネルから、ファイアウォールで以下の設定を入れます。

方向 プロトコル ポート 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.confforceencaps=yesが抜けていたせいで、NAT-Traversalが効いてなくて、ESPのパケットがVPSから自宅には飛ぶのに、自宅からVPSに飛んでこないという状況が見えていました。。

おわりに

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

参考資料