CentOS 8とopenSUSE(Raspberry Pi)でIPsecゲートウェイVPN構築 - 2.StrongSwan VPN接続確認

# 前提と準備

## Linuxサーバー構築の記事
- [Sambaでファイルサーバー構築(CentOS 8.1・openSUSE 15.1・Ubuntu 20.04)](https://qiita.com/kazumi75kitty/items/4298795029ba9f67b9d2)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 1.Apache導入](https://qiita.com/kazumi75kitty/items/daaf8ff8feb50ad04f41) /[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/67686eccaaec73251458)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 2.PHP導入](https://qiita.com/kazumi75kitty/items/fca116b1b387fe56c93c) /[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/50f1a447f6ebc2ee2b61)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 3.MySQL導入](https://qiita.com/kazumi75kitty/items/76807c637c096618a0e1)/[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/4212dacc45944f27ca94)
- [LinuxでApache2.4＋PHP7.4 - 4.セキュリティ(chownとfirewalld)](https://qiita.com/kazumi75kitty/items/8ad51806ac50bd04b644)
- [LinuxでIPsecゲートウェイをVPN構築 - 1.StrongSwan導入](https://qiita.com/kazumi75kitty/items/60941f00ae91c4d9f555) /[【Ubuntu 20.04＋Raspberry Pi】](https://qiita.com/kazumi75kitty/items/08259681247a6c2ebd0d)
- LinuxでIPsecゲートウェイをVPN構築 - 2.VPNへの接続確認【この記事】 /[【Ubuntu 20.04＋Raspberry Pi】](https://qiita.com/kazumi75kitty/items/c83f920f052d83d62457)

[前回はStrongSwanのソースコンパイルによるIPsec-VPN環境の構築](https://qiita.com/kazumi75kitty/items/60941f00ae91c4d9f555)を行いましたが、今回はVPNに実際に接続できるか確認しましょう！(˶ ･ᴗ･ )੭⚐⚑

## 環境
- IPsecプログラム：StrongSwan 5.9.0(ソースコンパイル)
- IPsec交渉受信側：Raspberry Pi 3B+ / openSUSE 15.1 Leap(aarm64)
- IPsec交渉発信側：Hyper-V(第2世代)のx64仮想機 / CentOS 8.1(x86_64)
- VPNに接続するクライアントとサーバーを別途用意(私はここではUbuntuとCentOSのWebサーバーを用意しました)

## 前提
- OSは最小限のインストール。また、最新の状態でOSをアップデートしていること
- ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
- どのディストリビューションでも、ファイアウォールはfirewalldを使う(ディストリビューション方言のファイアウォールよりも、firewalldでディストリビューションで共通の操作をしたい)
- CentOSについては、セキュリティはファイルシステム組み込みのSELinuxは煩雑になるため使わず(/etc/selinux/config編集後は再起動も必要)、firewalldを使うこと。

```CentOS8.1
# vi /etc/selinux/config
```

```ini:/etc/selinux/config
SELINUX=disabled
```

```CentOS8.1
# reboot
```

## サーバー条件
### IPアドレスとネットワーク構築図
- IPsec交渉受信側ゲートウェイ(下の図の左、Raspberry Pi)：
 - インターネット側(eth0)：192.168.1.22
 - VPN領域側(eth1)：192.168.2.1

- IPsec交渉発信側ゲートウェイ(下の図の右、CentOS 8.1)：
 - インターネット側(eth0)：192.168.1.18
 - VPN領域側(eth1)：192.168.5.1

- ネットワークセグメント：
 - インターネット接続可能：192.168.1.0/24
 - Raspberry Pi(図の左の交渉受信側)セキュアセグメント：192.168.2.0/24
 - CentOS 8(図の右の交渉発信側)セキュアセグメント：192.168.5.0/24

- VPNに接続する端末：
 - クライアント(Ubuntu 20.04)：192.168.2.2(192.168.2.0/24に属する)
 - Linux Webサーバー(CentOS 8.1)：192.168.5.2(192.168.5.0/24に属する)

- IPsec領域関連：
 - トンネリング区間：192.168.1.22 ～ 192.168.1.18間
 - VPN連携：192.168.2.0/24 ～ 192.168.5.0/24をVPN接続
![IPsecゲートウェイ以内のVPNに接続する図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/ab00d528-1b8b-c477-8d33-b945fca95532.png)
ここでは、**192.168.2.2のUbuntuクライアントが、192.168.5.2のLinux WebサーバーにVPN接続できるかを試します**。なおVPNに接続しているサーバーとクライアントともに、VPNの範囲のみ接続して、インターネットには接続しないこととします。

### パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年9月時点)
- zlib-1.2.11.tar.gz
- strongswan-5.9.0.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

# 作業手順
## VPNにサーバーとクライアントを接続する
### VPN領域内のIPアドレス割り振り
前回ではeth1はあくまでもネットワークアダプタを追加しただけであって、まだIPアドレスは割り振られていません。openSUSE(Raspberry Pi)の場合はYaSTでeth1にIPアドレスを手動で割り振ることが簡単にできたのですが、CentOS 8.1(Hyper-Vの仮想マシン)の場合はNetworkManagerでやろうとしたら、うまくいかなかったんです( ´•̥̥̥ω•̥̥̥` )

```CentOS8.1(Hyper-V/x64)
# nmcli c modify eth1 ipv4.address 192.168.5.1/24
エラー: 不明な接続 'eth1'.
```

細かく調べるのは今回はあきらめて/etc/sysconfig/network-scripts/の設定ファイルを、eth0のものからコピーして編集することにしました。

```CentOS8.1(Hyper-V/x64)
# cd /etc/sysconfig/network-scripts/
# cp ifcfg-eth0 ifcfg-eth1
# vi ifcfg-eth1
```

```conf:/etc/sysconfig/network-scripts/ifcfg-eth1
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="none"
DEFROUTE="yes"			← "no"に変更
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="eth0"				← 増設したアダプタ。ここでは"eth1"に変更
UUID="daccf09e-f112-4817-8ade-016524d946d5"	← 行そのものを削除
DEVICE="eth0"			← 増設したアダプタ。ここでは"eth1"に変更
ONBOOT="yes"
IPADDR="192.168.1.18"	← 増設したアダプタ。ここでは"192.168.5.1"に変更
PREFIX="24"
GATEWAY="192.168.1.1"	← 行そのものを削除
DNS1="192.168.1.1"		← 行そのものを削除
IPV6_PRIVACY="no"

```

```CentOS8.1(Hyper-V/x64)
# systemctl restart NetworkManager
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether [最初からあるネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.18/24 brd 192.168.1.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 [最初からあるネットワークアダプタのIPv6アドレス] scope global dynamic noprefixroute
       valid_lft 14373sec preferred_lft 12573sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether [増設ネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.1/24 brd 192.168.5.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever
    inet6 [増設ネットワークアダプタのIPv6アドレス] scope link noprefixroute
       valid_lft forever preferred_lft forever

# ip route
default via 192.168.1.1 dev eth0 proto static metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.18 metric 100
192.168.5.0/24 dev eth1 proto kernel scope link src 192.168.5.1 metric 101
```

今回はこの地道な方法でNetworkManagerに読み込ませて、eth1にIPアドレスを設定しました。もちろんルーティングにも192.168.5.0/24も認識されました。

その一方で、ラズパイのopenSUSEはYaSTで新設のeth1に192.168.2.1を割り振るのが簡単でした！増設したアダプタにもしっかりわかりやすくついていますね！！

```openSUSE15.1(RaspberryPi)
# yast
「システム」→「ネットワークの設定」
IPアドレスは192.168.2.1を設定
```
![YaST・IPアドレス設定前](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/ad8210b1-99d5-43dc-2ca9-261051d98735.png)

↓私が使用した増設USBネットアダプタは「AX88772B」というデバイス名なので、そこにIPアドレスを設定します。↓

![YaST・IPアドレス設定後](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/d32d4e3e-7941-b326-c69c-5e9ac492a30c.png)

```openSUSE15.1(RaspberryPi)
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether [最初からあるネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.22/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 [最初からあるネットワークアダプタのIPv6アドレス] scope global dynamic
       valid_lft 14373sec preferred_lft 12573sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether [増設ネットワークアダプタのMACアドレス] brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.1/24 brd 192.168.5.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 [増設ネットワークアダプタのIPv6アドレス] scope link
       valid_lft forever preferred_lft forever

# ip route
default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.22
192.168.2.0/24 dev eth1 proto kernel scope link src 192.168.2.1
```

### firewalldのゾーンを割り振る
firewalldのデフォルトはゾーンが「public」なので、今まで追加編集してきたfirewall-cmdのルールは、全部publicゾーンに入っているので、publicゾーンはインターネット側のeth0に、VPN領域側のeth1はinternalゾーンを割り振ることにしました。これはHyper-V仮想マシンのCentOSと、ラズパイのopenSUSEとで同じです。

```
# firewall-cmd --zone=public --change-interface=eth0 --permanent
# firewall-cmd --zone=internal --change-interface=eth1 --permanent
# firewall-cmd --reload

# firewall-cmd --get-active-zones
internal
  interfaces: eth1
public
  interfaces: eth0
```

### VPN領域内のネットワークにサーバーとクライアントをLANケーブル接続する
これは言うまでもないですね。サーバーとクライアントをLANケーブルでつないで、IPアドレスを手動で設定します(DHCPサーバーがVPN領域内にないので、手動設定するしかないです)

「サーバー条件」を参照しての通り、下の図のようなLANケーブル接続でIPアドレスを割り振っていきます。もちろん仮想マシンの場合は仮想スイッチを割り当てるだけでOKです。

- Ubuntuクライアントをラズパイに接続(192.168.2.0/24)。IPアドレスを192.168.2.2に設定
- Linux WebサーバーをHyper-V仮想機に接続(192.168.5.0/24)。IPアドレスを192.168.5.2に設定
![IPsecゲートウェイ以内のVPNに接続する図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/ab00d528-1b8b-c477-8d33-b945fca95532.png)

## VPNのネットワーク接続動作確認
### Pingはこの時点で通っている

![IPアドレスが適切なだけでもPingは通る](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/330a6ca3-ef99-8527-9232-5526e25089d4.png)

VPNでのIPアドレスを適切に設定したので、まずはPingで、Ubuntuクライアント(192.168.2.2)から対向のVPN領域にあるWebサーバー(192.168.5.2)に通るか確認したら、あっさり通っていました( ´థ౪థ)

これは、Hyper-V仮想マシンのCentOS 8.1のfirewalldがnftablesを使用している関係で、nftablesの状態を調べたところだが、nftablesのフィルタルールがICMPの転送を常に許可しているようです(nftablesについてはここに詳しくは載せませんが。。。)。

だからといって、Webがその時点でVPN領域越しに見られるというわけじゃないみたいです。

![この時点ではIPsec-VPN越しサーバーのwgetは不可](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/4d6e6f46-bcd6-95c4-ced6-f1882423750e.png)
もちろんwgetでも「No route」となってしまっています。。。

### firewalldの転送許可をするが、CentOS 8.1のnftablesの連動にハマって断念

IPsecでトンネリングしたパケットも、IPsecゲートウェイのfirewalldでまた転送許可のルールを追加しなければならないので、VPNにあるサーバーとクライアントが通信するポートを開放した。ここでは、クライアントが192.168.2.2、サーバーが192.168.5.2なので、192.168.2.0/24 → 192.168.5.0/24宛ての転送許可をルールに加えるが、firewalldの場合は--directを指定する必要がある。

Webサーバーが使うポートは、Webである80・443・8080・8443なので、当然以下のコマンドを入力すればVPN越しにIPsecゲートウェイが転送してくれるはず。

```
[192.168.2.0/24 → 192.168.5.0/24 HTTP 許可]
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 80 -j ACCEPT
[192.168.2.0/24 → 192.168.5.0/24 HTTPS 許可]
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 443 -j ACCEPT
[192.168.2.0/24 → 192.168.5.0/24 ポート8080 許可]
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 8080 -j ACCEPT
[192.168.2.0/24 → 192.168.5.0/24 ポート8443 許可]
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 8443 -j ACCEPT

[確認するには]
# firewall-cmd --direct --get-all-rules
ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 80 -j ACCEPT
ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 443 -j ACCEPT
ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 8080 -j ACCEPT
ipv4 filter FORWARD_direct 1 -s 192.168.2.0/24 -p tcp -d 192.168.5.0/24 --dport 8443 -j ACCEPT
```

ところが、そこで問題発生( ´•̥̥̥ω•̥̥̥` )
ラズパイ(openSUSE)ではtcpdumpをeth0・eth1の両側でパケットが通過されているのを確認したが、**Hyper-V仮想マシンのCentOS 8.1では、eth0で受け取ったパケットが拒否(reject。admin prohibited filterとICMPメッセージがUbuntuクライアントに返ってしまう)**されてしまい、wgetでいまだに「No route」となってしまうのだ…

もちろんfirewalldには間違いなく--directでダイレクトフィルタルールを追加した。そこで、CentOS 8.1のfirewalldがバックベースとなっているnftablesを調査してみた。

#### nftables関連でいろいろ参考させていただきました！( ´ •̥  ̫ •̥ ` )- ̗̀ ♡  ̖́-
- [centOS8でDockerコンテナから名前解決ができない話をnftコマンドで解決する](https://qiita.com/DaichiSasak1/items/11687a3c613c8811350c)
- [netfilterとfirewalldとiptablesとnftablesの関係](https://qiita.com/bashaway/items/e405d59d92670fbc5341)
- [Linuxにおける新たなパケットフィルタリングツール「nftables」入門 - さくらのナレッジ](https://knowledge.sakura.ad.jp/22636/)

おそらくfirewalld用に使用されているnftablesのテーブルは「inet firewalld」のようですが、オリジナルのnftablesのフィルタルールは「ip filter」を使っているそうです。そこで、nftablesの操作コマンドである「nft」を使って、firewall-cmdで--directオプションにて追加したダイレクトルールがどこに入っているかを調べてみました。

```CentOS8.1(Hyper-V/x64)
[テーブル ip filter にある転送ルール]
# nft list chain ip filter FORWARD
table ip filter {
        chain FORWARD {
                type filter hook forward priority filter; policy accept;
                meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 80 counter packets 0 bytes 0 accept
                meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 443 counter packets 0 bytes 0 accept
                meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 8080 counter packets 0 bytes 0 accept
                meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 8443 counter packets 0 bytes 0 accept
        }
}
```

```CentOS8.1(Hyper-V/x64)
[テーブル inet firewalld にある転送ルール。jumpで何度か入れ子になっている]
# nft list chain inet firewalld filter_FORWARD
table inet firewalld {
        chain filter_FORWARD {
                type filter hook forward priority filter + 10; policy accept;
                ct state { established, related } accept
                ct status dnat accept
                iifname "lo" accept
                ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 type addr-unreachable
                jump filter_FORWARD_IN_ZONES_SOURCE
                jump filter_FORWARD_IN_ZONES
                jump filter_FORWARD_OUT_ZONES_SOURCE
                jump filter_FORWARD_OUT_ZONES
                ct state { invalid } drop
                reject with icmpx type admin-prohibited
        }
}
# nft list chain inet firewalld filter_FORWARD_IN_ZONES
table inet firewalld {
        chain filter_FORWARD_IN_ZONES {
                iifname "eth0" goto filter_FWDI_public
                iifname "eth1" goto filter_FWDI_internal
                goto filter_FWDI_public
        }
}
# nft list chain inet firewalld filter_FWDI_public
table inet firewalld {
        chain filter_FWDI_public {
                jump filter_FWDI_public_pre
                jump filter_FWDI_public_log
                jump filter_FWDI_public_deny
                jump filter_FWDI_public_allow
                jump filter_FWDI_public_post
                meta l4proto { icmp, ipv6-icmp } accept
        }
}
# nft list chain inet firewalld filter_FWDI_public_deny
table inet firewalld {
        chain filter_FWDI_public_deny {
        }
}
# nft list chain inet firewalld filter_FWDI_public_allow
table inet firewalld {
        chain filter_FWDI_public_allow {
        }
}
```

このコマンド結果から言えることというと、**firewall-cmdで--directでルールを追加したにも関わらず、inet firewalldテーブルには何もそのルールが適用されず、ip filterに入ってしまう。さらに、ip filterにある転送ルールが無視されてしまい、inet firewalldのルールだけが実行されてしまい、その結果inet firewalldの転送ルールをたどったところ「reject with icmpx type admin-prohibited」のrejectルールに入ってしまう**という動作をしてしまっているらしい。

優先順位は確かにip filter(0)のほうがinet firewalld(+10)より先に参照されるはずだが、なぜip filterが無視される原因がわからず、大本のルールを参照するconfigファイルすら見当たらなかった(モジュールをコンパイルしたものにあらかじめ組み込まれていて直接viで編集できない？？)。

おそらく、現時点ではnftablesのdirectインターフェースとfirewalldとは相性が悪いバグのようで、泣く泣くLinux起動時に手動でnftで、inet firewalldのテーブルに転送ルール(細かくいうと許可対象を記述するfilter_FWDI_public_allow)を追加するしかなかった。。。( ´•̥̥̥ω•̥̥̥` )

なお実行した2020/9/7時点では、nftablesのバージョンはv0.9.3、firewalldのバージョンはv0.8.0となっている。

```CentOS8.1(Hyper-V/x64)
# nft add rule inet firewalld filter_FWDI_public_allow meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 80 accept
# nft add rule inet firewalld filter_FWDI_public_allow meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 443 accept
# nft add rule inet firewalld filter_FWDI_public_allow meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 8080 accept
# nft add rule inet firewalld filter_FWDI_public_allow meta l4proto tcp ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 8443 accept

# nft list chain inet firewalld filter_FWDI_public_allow
table inet firewalld {
        chain filter_FWDI_public_allow {
                meta nfproto ipv4 ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 80 accept
                meta nfproto ipv4 ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 443 accept
                meta nfproto ipv4 ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 8080 accept
                meta nfproto ipv4 ip saddr 192.168.2.0/24 ip daddr 192.168.5.0/24 tcp dport 8443 accept
        }
}
```

### Webサーバーにアクセスできるか確認
firewalldとnftablesの相性の悪さが足を引っ張っていたが、今回のところはnftablesは手作業でファイアウォールを転送許可することにした(´-ε-｀) 無事IPsecゲートウェイの両方で転送を許可できたら、VPN越しにUbuntuクライアントからVPN内のサーバーにアクセスできるかやってみました。

![サーバーアクセス成功](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/3f69cc6a-7b78-8302-1f28-87847f212d8e.jpeg)

もう一度確認ですが、**Ubuntuクライアントは192.168.2.2で、そこからIPsecトンネリングで192.168.1.0/24のネットワークセグメントを越えた対向のVPNにあるサーバー(192.168.5.2)にアクセスしている画面**です。ついでにSSHで接続できるかも試しました(˶ ･ᴗ･ )੭⚐⚑

tcpdumpでも平文のパケットをESPでトンネル化している様子が見られます。

## セキュリティ確認
### IPsecゲートウェイをまたぐパケットは暗号化されている？？
ここがまずIPsec-VPNでのポイントだと思う。IPsecなんだから、インターネット側を通る192.168.1.0/24で暗号化されず平文でトンネリングされたら盗聴される危険性が増します；；

![パケットがIPsec暗号化されている！](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/a5cf3ca4-8191-9e9e-13aa-866416158e3b.png)

うんっ、暗号化されているね！！(˶ ･ᴗ･ )੭♡♡

わかりやすくHTTP(ポート80)で「QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ…」をHTTPSで暗号化させずにクライアントでサーバーからページをアクセスしてみたけど、IPsecゲートウェイ間のトンネリングでそれを拾ってみてみると、暗号化されていました！！


### VPN領域内から外側にアクセスできる？？
実際に、Ubuntuクライアント(192.168.2.2)から192.168.1.0/24の外側のセグメントにアクセスできるかもチェックしてみた。

![セキュア外部は接続不可](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/32ed0de0-dbec-1428-0aac-0c3fdd813326.png)
![セキュア外部は接続不可](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/496bddea-7185-a5ce-ce0a-a11ea0cd3883.png)

VPN領域内の端末は、192.168.1.0/24宛てはすべてVPNの入り口であるIPsecゲートウェイにパケットが送出されるので、それがIPsecゲートウェイでは許可していないからだ(192.168.2.0/24 → 192.168.5.0/24しか許可していない)。逆に許可しているとしても、192.168.2.2 → 192.168.1.0/24の端末は、Ubuntuクライアントもデフォルトゲートウェイとして、入口たるIPsecゲートウェイに送出させ、IPsecゲートウェイから目的の端末までの往路は届くが、復路は逆に受け取った192.168.1.0/24内の端末が192.168.2.0/24に返すためのルーティングを知らないため、VPN領域内のネットワークセグメントをルーティングテーブルに加えない限り、通信が成り立たないのだ。

### 外部からVPN領域にアクセスできてしまわないか？？
特にこれは一番気になるところだ…♆ (⃔ `꒳´\* )⃕↝
でも前述のとおり、実際は192.168.1.0/24の端末がVPNへの経路を知らなければ、ルーティング上は問題ないはず

![VPN外部からVPN内部にアクセスしようとすると…](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/712fe49e-6b3f-8733-ec91-320fbf6e4bcf.png)

192.168.1.0/24というVPN外部から、192.168.2.0/24と192.168.5.0/24の2つのVPN領域内のサーバーやクライアントに、PingやWebアクセスしようとしても、接続されることはないことを確認。

インターネットに直結する192.168.1.0/24内のフレッツ光集約などのモデムにそのようなVPN領域へのセグメントを教えなければ、基本的に外部からVPNにアクセスされることはまずない面では安全だと思う。でもVPN領域を区切るIPsecゲートウェイで、通過を許可すべきポート番号と宛先・送信元の両方をしっかりファイアウォールで制限すべきだと、私はそう思う。

# まとめ
StrongSwanでRaspberry Pi(openSUSE)とHyper-V仮想マシンのCentOS 8.1で、IPsecゲートウェイの構築を行い、IPsec-VPNとしての用途を満たせるかを検証してみたけど、外部での盗聴を防止するという面では有効性は高いが、VPN領域に適当にアクセス許可しているとあとで痛い目に合うところは要注意ではないかと感じた。

できればVPNにアクセスできる外部領域の端末はIPsecゲートウェイに限定して、VPNにあるSSHも公開鍵方式であるなど、ファイアウォールとIPsecに限らず、複合的なセキュリティを選択しなければやはり限界があるのかな…とも思う