OCIと自宅をIP-VPNで繋ぐ話

OCIのことを書きたいけど、AIには疎いので、今度はネットワークネタで。

(2025.06.12)IKEv1が使えなかった理由を追記。オラクル原田先生ありがとうございます。

# これを読むと何ができる？
* ローカル環境とOCIをネットワークで繋げられます
* 自宅PCからSSHで直接OCI上のサーバにログインできます（もちろん、逆も）

libreswanを使ってIPsecを繋ぐ方法は[ドキュメント](https://docs.oracle.com/ja-jp/iaas/Content/Network/Reference/libreswanCPE.htm)ありますが、それ以外も含めた説明があるところってあまりないんですよね。サーバやネットワークの知識が必要ですし。自分もよく忘れるんで、備忘録を兼ねて記載。

今回は接続元が自宅ですが、他クラウドから繋ぐとか、事務所から繋ぐとか、いろいろと使いどころはあると思います。OCIは10TBまで通信料無料だし。


# 何が必要？
* OCIアカウント（Free Tierで可）
* ローカル環境上のLinuxサーバ（今回はOracleLinux 9で構築）

高価なルータいりません。Linuxサーバがルータになります。BGP喋らせます。まあ別にLinuxサーバからログインできるようにするだけでも良いんですけど、PCから直接行けるほうが、ロマン、ありますよね。


# 先に大まかな流れ教えてくれない？
たぶん、長くなるので、先に流れ書いたほうが良いですよね。
* OCI側
  * VCN作る
  * DRG作る
  * ipsec tunnel作る
* 自宅側
  * サーバ建てる
  * 必要なパッケージ（libreswan、frr）をインストールする
  * ipsecで繋ぐ
  * frrでBGP喋らせる
  * PCからOCI上のサーバに接続する


# いざ作成開始
では、作っていきましょー！

## OCI側
### VCNとサブネットの作成
特筆すべきことはないので、さくっと。Redwoodまだ慣れない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/e1d4431a-eef4-4ab1-979e-271720b63bdd.png)


### DRGの作成
ここも特筆すべきことはないので、さくっと。VCNアタッチメントも作っておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/930d9303-f17f-47a4-b142-d7c6be2fd06a.png)


### サイト間VPNの作成
IPsec接続を作っていきましょう。VPNウィザードもありますが、普通に作っていきます。


まずは顧客構内機器(CPE)。
使うCPEはLinuxサーバ上にインストールしたLibreswan。
今回の構成では自宅内にCPEを置きます。なのでNATの中。
CPEとして設定するのは、自宅のルータのIPになります。フレッツとか引いてるとIPアドレスが半固定になるのでとてもありがたいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/3a924a2c-511d-4cd8-af10-c9845a3c3b9d.png)

これもさくっと作ります。ベンダーがLibreswan。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/b0e8e02f-4f6b-49ba-a8b1-7f6cc0614606.png)

IPsec接続も作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/75a0a5a7-6845-4159-a49f-e6cfb1cb99f0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/f6d727d6-e9ef-415f-b291-26a49a7a6c43.png)


トンネルの設定はこんな感じ。**IKEバージョンはv2**で。あんまり深く追ってないのですが、今回使ったLibreswanだと、v1が無効にされているみたいでした。

(2025.06.12)IKEv1を有効にするには以下で良いそうです。

https://x.com/oci_oujp/status/1933096266109776291

今回、あえて/31のリンクローカルアドレスで作ってます。個人的には/31は気持ち悪く感じるんですが、/31でもちゃんと動きます。もちろん/30でも大丈夫です。

トンネル名|IKEバージョン|ルーティング・タイプ|BGP ASN|IPv4-CPE|IPv4-Oracle
-|-|-|-|-|-
HOME-IPSEC-VPN-TUNNEL1|IKEv2|BGP動的ルーティング|65100|169.254.0.0/31|169.254.0.1/31
HOME-IPSEC-VPN-TUNNEL2|IKEv2|BGP動的ルーティング|65100|169.254.0.2/31|169.254.0.3/31

### 必要な情報の保存
Libreswan用に以下の情報を保存します。
* 各トンネルのOracle VPN IPアドレス
* 各トンネルの共有シークレット

Oracle VPN IPアドレスはこれ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/f55a03a4-5de0-4268-ae74-98869c7cdba5.png)

共有シークレットは各トンネルの詳細画面のこれ。右の「…」をクリックして、表示を選択すればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/3e20ee2a-ff04-468c-a689-994c7731ed66.png)

OCI側はこれでOK。


## 自宅側
### サーバ構築
Oracle Linux 9.6で作ってみました。rootなのは気にしないでください。
```shell-session
[root@ipvpn-ol9 ~]# cat /etc/oracle-release
Oracle Linux Server release 9.6
[root@ipvpn-ol9 ~]#
```

### libreswan,frrのインストール
依存関係でいっぱいパッケージが入るのは割愛。
```shell-session
[root@ipvpn-ol9 ~]# dnf install libreswan frr
メタデータの期限切れの最終確認: 0:16:07 前の 2025年06月01日 16時59分41秒 に実施 しました。
依存関係が解決しました。
================================================================================
 パッケージ                   Arch   バージョン         リポジトリー      サイズ
================================================================================
インストール:
 frr                          x86_64 8.5.3-7.el9        ol9_appstream     4.9 M
 libreswan                    x86_64 4.15-8.0.1.el9     ol9_appstream     1.4 M
依存関係のインストール:

（中略）

トランザクションの概要
================================================================================
インストール  88 パッケージ

ダウンロードサイズの合計: 25 M
インストール後のサイズ: 82 M
これでよろしいですか? [y/N]: y
```


### ipsecで繋ぐ
基本的に[ドキュメント](https://docs.oracle.com/ja-jp/iaas/Content/Network/Reference/libreswanCPE.htm)どおりです。

まずはカーネルパラメータの変更。libreswanをインストールすると、/etc/sysctl.d/50-libreswan.confというファイルが作られます。ただ、/usr/lib/sysctl.d/50-redhat.confで、net.ipv4.conf.*.rp_filter=1がセットされてしまうので、それを上書きするために、/etc/sysctl.d/90-ipsec.confというのを作成して読み込みます。
ついでに、ip_forward=1にします。

```/etc/sysctl.d/90-ipsec.conf
net.ipv4.ip_forward=1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.*.rp_filter = 0
```

```shell-session
[root@ipvpn-ol9 ~]# sysctl --system
(中略)
* Applying /etc/sysctl.d/50-libreswan.conf ...
(中略)
* Applying /etc/sysctl.d/90-ipsec.conf ...
(中略)
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.enp1s0.rp_filter = 0
net.ipv4.conf.ip_vti0.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
[root@ipvpn-ol9 ~]#
```

次に、/etc/ipsec.d/oci-ipsec.confの作成。ドキュメント通りで問題なし。

```/etc/ipsec.d/oci-ipsec.conf
conn home-ipsec-vpn-tunnel1
     left=192.168.1.61        # LinuxサーバのIP
     leftid=aaa.aaa.aaa.aaa   # CPE作成時に指定したIP(ルータのグローバルIP)
     right=bbb.bbb.bbb.bbb    # Oracle VPN IPアドレス(TUNNEL1側)
     authby=secret
     leftsubnet=0.0.0.0/0
     rightsubnet=0.0.0.0/0
     auto=start
     mark=5/0xffffffff # Needs to be unique across all tunnels
     vti-interface=vti-t1     # インターフェース名は好きに
     vti-routing=no
     ikev2=insist             # IKEv2にしたのでここも忘れず
     ike=aes_cbc256-sha2_384;modp1536
     phase2alg=aes_gcm256;modp1536
     encapsulation=yes
     ikelifetime=28800s
     salifetime=3600s
conn home-ipsec-vpn-tunnel2
     left=192.168.1.61        # LinuxサーバのIP
     leftid=aaa.aaa.aaa.aaa   # CPE作成時に指定したIP(ルータのグローバルIP)
     right=ccc.ccc.ccc.ccc    # Oracle VPN IPアドレス(TUNNEL2側)
     authby=secret
     leftsubnet=0.0.0.0/0
     rightsubnet=0.0.0.0/0
     auto=start
     mark=6/0xffffffff # Needs to be unique across all tunnels
     vti-interface=vti-t2     # インターフェース名は好きに
     vti-routing=no
     ikev2=insist             # IKEv2にしたのでここも忘れず
     ike=aes_cbc256-sha2_384;modp1536
     phase2alg=aes_gcm256;modp1536
     encapsulation=yes
     ikelifetime=28800s
     salifetime=3600s
```

そして、シークレットファイル。これもドキュメント通りで問題なし。
aaa.aaa.aaa.aaa～ccc.ccc.ccc.cccの部分は、oci-ipsec.confで記載したものと同じ。
```/etc/ipsec.d/oci-ipsec.secrets
aaa.aaa.aaa.aaa bbb.bbb.bbb.bbb: PSK "secret-key-string_tunnel1"
aaa.aaa.aaa.aaa ccc.ccc.ccc.ccc: PSK "secret-key-string_tunnel2"
```

ファイルを作ったら検証。まだサービス起動していないので、そこだけFAILEDになります。
```shell-session
[root@ipvpn-ol9 ~]# ipsec verify
Verifying installed system and configuration files

Version check and ipsec on-path                         [OK]
Libreswan 4.15
Checking for IPsec support in kernel                    [OK]
 NETKEY: Testing XFRM related proc values
         ICMP default/send_redirects                    [OK]
         ICMP default/accept_redirects                  [OK]
         XFRM larval drop                               [OK]
Pluto ipsec.conf syntax                                 [OK]
Checking rp_filter                                      [OK]
Checking that pluto is running                          [FAILED]
Checking 'ip' command                                   [OK]
Checking 'iptables' command                             [OK]
Checking 'prelink' command does not interfere with FIPS [OK]
Checking for obsolete ipsec.conf options                [OK]

ipsec verify: encountered 2 errors - see 'man ipsec_verify' for help
[root@ipvpn-ol9 ~]#
```

問題ないことを確認したら、サービスを起動させます。

```shell-session
[root@ipvpn-ol9 ~]# systemctl start ipsec
[root@ipvpn-ol9 ~]# ipsec status | grep active
000 Total IPsec connections: loaded 2, active 2
[root@ipvpn-ol9 ~]# ipsec status | grep established
000 #1: "home-ipsec-vpn-tunnel1":4500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); REKEY in 27798s; REPLACE in 28780s; newest; idle;
000 #3: "home-ipsec-vpn-tunnel1":4500 STATE_V2_ESTABLISHED_CHILD_SA (establishe  Child SA); REKEY in 2533s; REPLACE in 3580s; newest; eroute owner; IKE SA #1; idle;
000 #2: "home-ipsec-vpn-tunnel2":4500 STATE_V2_ESTABLISHED_IKE_SA (established IKE SA); REKEY in 28149s; REPLACE in 28780s; newest; idle;
000 #4: "home-ipsec-vpn-tunnel2":4500 STATE_V2_ESTABLISHED_CHILD_SA (establishe  Child SA); REKEY in 2749s; REPLACE in 3580s; newest; eroute owner; IKE SA #2; idle;
[root@ipvpn-ol9 ~]#
```

繋がりましたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/8a41009a-27fc-4ad6-8905-bd704de2cc4c.png)

忘れずに、自動起動するようにしておきましょう。
```shell-session
[root@ipvpn-ol9 ~]# systemctl enable ipsec
Created symlink /etc/systemd/system/multi-user.target.wants/ipsec.service → /usr/lib/systemd/system/ipsec.service.
[root@ipvpn-ol9 ~]#
```


### frrとBGPの設定
frrはオープンソースのルーティングプロトコルスイートです。BGPの検証したいときに便利です。まあ、ネットワークエンジニア以外にはあまり馴染みはなさそうですが。

まずはBGPを有効化して、起動します。
```shell-session
[root@ipvpn-ol9 ~]# grep bgp /etc/frr/daemons
bgpd=no
bgpd_options="   -A 127.0.0.1"
# bgpd_wrap="/usr/bin/daemonize /usr/bin/mywrapper"
[root@ipvpn-ol9 ~]# sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons
[root@ipvpn-ol9 ~]# grep bgp /etc/frr/daemons
bgpd=yes
bgpd_options="   -A 127.0.0.1"
# bgpd_wrap="/usr/bin/daemonize /usr/bin/mywrapper"
[root@ipvpn-ol9 ~]# systemctl start frr
[root@ipvpn-ol9 ~]#
```

次にconfig流し込みます。vtyshという対話型シェルがあります。ネットワークエンジニアにはお馴染みのインターフェースです。良き良き。

```shell-session
[root@ipvpn-ol9 ~]# vtysh

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

ipvpn-ol9# show run
Building configuration...

Current configuration:
!
frr version 8.5.3
frr defaults traditional
hostname ipvpn-ol9
no ipv6 forwarding
!
end
ipvpn-ol9# conf t
ipvpn-ol9(config)# ip forwarding
ipvpn-ol9(config)#
ipvpn-ol9(config)# interface vti-t1
ipvpn-ol9(config-if)#  ip address 169.254.0.0/31
ipvpn-ol9(config-if)# !
ipvpn-ol9(config-if)# interface vti-t2
ipvpn-ol9(config-if)#  ip address 169.254.0.2/31
ipvpn-ol9(config-if)# !
ipvpn-ol9(config-if)#
ipvpn-ol9(config-if)# router bgp 65100
ipvpn-ol9(config-router)#  bgp router-id 192.168.1.61
ipvpn-ol9(config-router)#  no bgp ebgp-requires-policy
ipvpn-ol9(config-router)#  neighbor 169.254.0.1 remote-as 31898
ipvpn-ol9(config-router)#  neighbor 169.254.0.1 ebgp-multihop 255
ipvpn-ol9(config-router)#  neighbor 169.254.0.3 remote-as 31898
ipvpn-ol9(config-router)#  neighbor 169.254.0.3 ebgp-multihop 255
ipvpn-ol9(config-router)#
ipvpn-ol9(config-router)#  address-family ipv4 unicast
ipvpn-ol9(config-router-af)#   network 192.168.1.0/24
ipvpn-ol9(config-router-af)#   neighbor 169.254.0.1 next-hop-self
ipvpn-ol9(config-router-af)#   neighbor 169.254.0.1 soft-reconfiguration inbound
ipvpn-ol9(config-router-af)#   neighbor 169.254.0.3 next-hop-self
ipvpn-ol9(config-router-af)#   neighbor 169.254.0.3 soft-reconfiguration inbound
ipvpn-ol9(config-router-af)#
ipvpn-ol9(config-router-af)# end
ipvpn-ol9# show run
Building configuration...

Current configuration:
!
frr version 8.5.3
frr defaults traditional
hostname ipvpn-ol9
no ipv6 forwarding
!
interface vti-t1
 ip address 169.254.0.0/31
exit
!
interface vti-t2
 ip address 169.254.0.2/31
exit
!
router bgp 65100
 bgp router-id 192.168.1.61
 no bgp ebgp-requires-policy
 neighbor 169.254.0.1 remote-as 31898
 neighbor 169.254.0.1 ebgp-multihop
 neighbor 169.254.0.3 remote-as 31898
 neighbor 169.254.0.3 ebgp-multihop
 !
 address-family ipv4 unicast
  network 192.168.1.0/24
  neighbor 169.254.0.1 next-hop-self
  neighbor 169.254.0.1 soft-reconfiguration inbound
  neighbor 169.254.0.3 next-hop-self
  neighbor 169.254.0.3 soft-reconfiguration inbound
 exit-address-family
exit
!
end
ipvpn-ol9#
```

network 192.168.1.0/24のところは自宅のネットワークアドレスです。必要に応じて書き換えてください。
さて、繋がったかどうか、確認。

```shell-session
ipvpn-ol9# show ip bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 192.168.1.61, local AS number 65100 vrf-id 0
BGP table version 3
RIB entries 5, using 960 bytes of memory
Peers 2, using 1449 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
169.254.0.1     4      31898        11        12        0    0    0 00:04:10            2        3 N/A
169.254.0.3     4      31898        12        13        0    0    0 00:04:10            2        3 N/A

Total number of neighbors 2
ipvpn-ol9# show ip route
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, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

K>* 0.0.0.0/0 [0/100] via 192.168.1.1, enp1s0, 00:08:51
C>* 169.254.0.0/31 is directly connected, vti-t1, 00:04:25
C>* 169.254.0.2/31 is directly connected, vti-t2, 00:04:25
B>* 172.16.0.0/24 [20/0] via 169.254.0.1, vti-t1, weight 1, 00:04:24
  *                      via 169.254.0.3, vti-t2, weight 1, 00:04:24
B>* 172.16.1.0/24 [20/0] via 169.254.0.1, vti-t1, weight 1, 00:04:24
  *                      via 169.254.0.3, vti-t2, weight 1, 00:04:24
C>* 192.168.1.0/24 is directly connected, enp1s0, 00:08:51
ipvpn-ol9# 
```

繋がってますねえ。OCIコンソール側も確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/e638069b-624b-41bf-b0da-4831c09ae47f.png)


ここまでできれば、あとはAS_PATHプリペンドやDRGルート表周りの検証も簡単です。

設定保存して、こちらも自動起動するようにしておきましょう。
```shell-session
ipvpn-ol9# wr mem
Note: this version of vtysh never writes vtysh.conf
Building Configuration...
Integrated configuration saved to /etc/frr/frr.conf
[OK]
ipvpn-ol9# exit
[root@ipvpn-ol9 ~]# systemctl enable frr
Created symlink /etc/systemd/system/multi-user.target.wants/frr.service → /usr/lib/systemd/system/frr.service.
[root@ipvpn-ol9 ~]#
```

### PCからOCI上のサーバに接続
そもそも接続先のサーバ作ってなかったですね。簡単に作ります。DRG向けのルートルールも忘れずに。
（あ、スペルミスしてる、、、恥ずかしい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/04511fea-53e0-4999-a3d8-39c28733839c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/f02a675b-70b7-43b8-bfe6-f236cbaae41c.png)


まずはlibreswan,frrを動かしているLinuxサーバからログイン。-Bで送信元インターフェースを指定する(もしくは-bで送信元IPを指定する)をしないと、IPsec用のインターフェースから送信する（＝送信元がリンクローカルIPになる）ことに通信が成立しなくなります。注意。
```shell-session
[root@ipvpn-ol9 ~]# ssh -i ssh-key-2025-06-01.key -B enp1s0 opc@172.16.0.2
The authenticity of host '172.16.0.2 (172.16.0.2)' can't be established.
ED25519 key fingerprint is SHA256:pOYHQ6FVsrmtF6TfSl8ZWfafZg1xOMenBJJdAI6dvjg.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.16.0.2' (ED25519) to the list of known hosts.
[opc@ipsev-vpn-test ~]$
```


ここまで来たら、あと少しですね。
まずは、Linuxサーバのfirewalldの設定変更。今回は繋ぐことが目的なので、無効化します。ちゃんと運用する人は、firewall-cmd使ってごにょごにょするのが良いのかなと思います。
```shell-session
[root@ipvpn-ol9 ~]# systemctl stop firewalld
[root@ipvpn-ol9 ~]# systemctl disable firewalld
Removed "/etc/systemd/system/multi-user.target.wants/firewalld.service".
Removed "/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service".
[root@ipvpn-ol9 ~]#
```

最後にPCからLinuxサーバあてのルーティング。これは自宅環境によって異なるので割愛しますが、PCに直接ルーティング追加しても良いですし、デフォルトゲートウェイ上に静的ルート追加するのも良いと思います。私の場合は、後者でさくっと終わらせました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/afafd7d8-6c56-4d81-878d-edcb9c859a72.png)


ここまでできれば、繋がるようになります。ちゃんとPCから直接つながってることになってますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3781934/3e416e6c-94e6-496b-9610-5f67e3dd5f81.png)


これで、OCIのネットワークもばっちり★