【SSLVPN】OPNsense on Azure

クラウドへリモートアクセス環境を準備する場合,クラウドネイティブな方法もあるがVPN仮想アプライアンスをたててオンプレライクにSSLVPNで乗り込みたいシーンがよくある。(私の案件では)
クラウドにアカウントを作りたくない,プロトコルが対応していない等いくつか理由があるが,一番の理由は「クラウド構築担当している人がVPNとか全然分からんからNW部隊に丸投げしてくる。そんでもってユーザ管理や運用はそっちでやってね。」というもの。(

ぼやいても仕方ないので毎度VPN対応のFW仮想マシンをたてて構築するのだけれど,まぁ高いのなんの。そこで丁度よさそうなのがOPNsenseだったので構築手順を残しておく。

公式ドキュメントがあるので基本それに従って進めていく。
https://docs.opnsense.org/manual/how-tos/installazure.html

構成イメージ

バージョンは以下の通り。

サーバ側
OPNsense 24.1.1-amd64
FreeBSD 13.2-RELEASE-p9
OpenSSL 3.0.13

クライアント側
OpenVPN GUI v11.47.0.0

仮想マシン作成

ユーザ設定で認証を証明書にするとデプロイ失敗するのでパスワードを設定する。
パブリックIPとネットワークセキュリティグループを適切に設定してデプロイ完了したらHTTPSでログイン。

続いてSSLVPNの設定へ。

OPNsense設定

まずは認証関連の設定。今回は自己証明書で構成を組む。

CA作成

System: Trust: Authorities
※ 中身は省略

サーバ証明書作成

System: Trust: Certificates
※ 中身は省略

2FA用のGoogleAuth登録

System: Access: Servers
サーバ名を入れて,TypeでLocal+OTP。それ以外はそのまま。

SSLVPN Server作成

Serverを作成して~という流れはLegacyとあるのでインスタンスの作成。その前にTLS Keyを作成する。

認証用なのでAuthオンリーで。

入力したパラメータ一覧は以下の通り。それ以外は空欄ないしはデフォルトのまま。

GeneralSetting

  • Role: Server
  • Description: 適宜
  • Server(IPv4):172.16.1.0/24

Trust

  • Certificate: SSLVPN CRT(作成したサーバ証明書)
  • Certificate Authority: SSLVPN CA(作成したローカルCA)
  • Verify Client Certificate: none
  • Certificate Depth:One(Client+Server)
  • TLS static key: TSL-Key(作成したもの)
  • Auth:SHA256
  • Data Ciphers: AES-256-GCM

Authentication

  • Authentication: Google Auth(先ほど作成したもの)
  • Renegotiate time: 0 ※ OTP認証のため再接続になるとTokenが切れているため認証エラーとなってしまう。そのため,ここは「0」に設定する必要がある。OTPでなければ不要。

Routing

  • Local Network: 10.0.0.0/16 (VNetにアクセスできれば良いのでVNetに割り当てたセグメント指定)

SNAT設定

VPNのトラフィックをインタフェースでSNATする。
Modeをマニュアルへ変更。

Interface,Source addressをそれぞれ設定。

結果。

リモートアクセスユーザ作成

ユーザ名,パスワードを入力し,OTP用の設定を入力する。

ここでSaveをするとユーザ証明書作成ページに跳ぶ。自己証明書作成を選択し、その他項目も適宜入力して作成する。

その後,GoogleAuthenticatorへ登録するためのQRコードが生成されるのでスマホアプリで登録する。

OpenVPNClient設定エクスポート

TypeはFileonly。Windowsの証明書ストアのオプションは外す。

一番下にあるユーザ用の構成ファイルをダウンロードして完了。

FW設定

今回,Azure上で構築しているので通信制御はNetworkSecurityGroupで対応することとして,OPNsenseのルールは全許可とした。よってここは省略。(LANとOpenVPNのIFにIN全許可ルールを1行入れたのみ)

接続試験(Windows11)

サーバ側でも設定した再認証させない設定をダウンロードしたファイルにも追記する必要がある。

dev tun
persist-tun
persist-key
auth SHA256
client
verb 5  # デバッグ用
ping-restart 0  # これ0に指定する必要がある
resolv-retry infinite

保存した設定ファイルをOpenVPNクライアントにインポートし,接続すると認証画面が出るので「 Token + Password 」の並びで入力する。これが分からなくてサーバ設定見直したりキャプチャ眺めたり,VM作り直したりとかなり迷走した orz。

無事に成功するとIPアドレスが割り当てられAzure内に通信できるようになる。

疎通確認

無事Pingも通った。

ping 172.16.1.1  # Tunnel対向

172.16.1.1 に ping を送信しています 32 バイトのデータ:
172.16.1.1 からの応答: バイト数 =32 時間 =187ms TTL=64
172.16.1.1 からの応答: バイト数 =32 時間 =186ms TTL=64

172.16.1.1 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 186ms、最大 = 187ms、平均 = 186ms
Ctrl+C
^C

>ping 10.0.0.5 -t # VPNサーバAzure内部IP

10.0.0.5 に ping を送信しています 32 バイトのデータ:
10.0.0.5 からの応答: バイト数 =32 時間 =187ms TTL=64
10.0.0.5 からの応答: バイト数 =32 時間 =187ms TTL=64

10.0.0.5 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 187ms、最大 = 187ms、平均 = 187ms
Ctrl+C
^C

>ping 10.0.0.4 -t # Azure内同一Subnet別インスタンス

10.0.0.4 に ping を送信しています 32 バイトのデータ:
10.0.0.4 からの応答: バイト数 =32 時間 =189ms TTL=63
10.0.0.4 からの応答: バイト数 =32 時間 =189ms TTL=63

10.0.0.4 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 189ms、最大 = 189ms、平均 = 189ms
Ctrl+C
^C

以上で完了。おつかれさまでした。

GCPとVPN接続する~その2~

GCPとのVPN接続で, ポリシーベースではなくルーティングベースでやってみる。

構成は前回とほぼ変わらず。
クラウドルータとの間のセグメントが増えた感じ。

GCP側にBGPルータができ, それとのルーティング設定が追加となる

前提条件(ポリシーベースの前提を大体引き継ぐ)

  • GCPのアカウント設定済み
  • (VPC作成済み, VPC作成後のインスタンスも作成済み)
  • 家側のNAT設定済み
  • ルーティングベースなので, VTIを採用

流れ

1. クラウドルータ設定
2. VPN設定(Cisco)

1. クラウドルータ設定

ネットワーキングから「ハイブリッド接続」を選択

「ルーターを作成」をクリック

必要事項を記入する。
今回, BGPのAS NoはGCP側は64512とした。

ルーター作成後, 「VPNトンネルを追加」する。

各項目を記入し, BGPセッションの編集ボタンをクリック。

ここでは家側のAS Noを65000とし, トンネル間のセグメント情報を記入する。

設定の結果を確認。

これでGCP側は完了。

2. VPN設定(Cisco)

VTIに準じた設定を入れていく。
関連Config抜粋

crypto ikev2 proposal GCP_proposal
encryption aes-cbc-256 aes-cbc-192 aes-cbc-128
integrity sha256
group 16
!
crypto ikev2 policy GCP_policy
proposal GCP_proposal
!
crypto ikev2 keyring GCP_Key
peer GCP
address <GCPのIPアドレス>
pre-shared-key <共有キー>
!
!
!
crypto ikev2 profile IKEv2_Profile
match identity remote address <GCPのIPアドレス> 255.255.255.255
identity local address <家のGlobal IP>
authentication remote pre-share
authentication local pre-share
keyring local GCP_Key
lifetime 3600
!
!
crypto ipsec transform-set TS esp-aes 256 esp-sha256-hmac
mode tunnel
!
crypto ipsec profile GCP_Profile
set transform-set TS
set pfs group16
set ikev2-profile IKEv2_Profile
!
crypto ipsec profile VTI
set transform-set TS
set pfs group16
!
interface Tunnel1
ip address 169.254.1.2 255.255.255.252
tunnel source Vlan100
tunnel mode ipsec ipv4
tunnel destination <GCPのIPアドレス>
tunnel protection ipsec profile GCP_Profile
!
!
router bgp 65000
bgp log-neighbor-changes
network 192.168.1.0
network 192.168.10.0
neighbor 169.254.1.1 remote-as 64512
!

通信確認

#ping 10.10.10.10 source 192.168.1.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.10.10.10, timeout is 2 seconds:
Packet sent with a source address of 192.168.1.2
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 160/160/160 ms

IPSecステータス

#show crypto session
Crypto session current status

Interface: Tunnel1
Profile: IKEv2_Profile
Session status: UP-ACTIVE
Peer: 35.231.219.234 port 4500
Session ID: 2209
IKEv2 SA: local 192.168.1.2/4500 remote 35.231.219.234/4500 Active
IPSEC FLOW: permit ip 0.0.0.0/0.0.0.0 0.0.0.0/0.0.0.0
Active SAs: 2, origin: crypto map

無事接続確認完了。

GCPとVPN接続する

GCPの$300クレジット(1年)があるのでAWSだけでなくGCPも触ってみる。

例によって自宅とVPN張って見る。構成はこんな感じ。

概略構成

前提条件

  • GCPのアカウント設定済み
  • (VPC作成後)インスタンスは作成済み
  • 家側のNAT等の転送ルールは設定済み
  • 今回はポリシーベースVPNとするので GRE over IPSec (訂正:GRE使いません)

流れ

1. VPC作成
2. サブネット作成
3. FW設定
4. インスタンス作成(ここでは省略)
5. VPN設定(GCP & Cisco)

Google Cloud Consoleにログインして, VPCネットワークを作成する。

1. VPC作成

「VPCネットワーク」から「VPCネットワーク」を選択

「VPCネットワークを作成」を選択

2.  サブネット作成

必要事項記入して「作成」

この後, 作成したサブネット上にインスタンスを作成する。(手順は省略)

3. FW設定

サブネットに対する通信許可設定を入れる。
VPCから作成したVPC「vpc01」を選択
ファイアウォールルールを選択し, ルールの追加をクリック
※画像は既に作成済み
ルールを記入していく
ここでは自宅の環境からサブネット全体に対して全て通信許可としている
完了

4. VPN作成

「VPCネットワーク」から「VPN」選択

「VPN接続を作成」をクリック

必要事項を記入する。IPアドレスはプルダウンをクリックして新規作成する。

名前を適当につけて「予約」

するとGlobal IP Addressが割当たる

内容確認して「完了」をクリック

GCP側はこれで準備完了

5. Ciscoルータの設定

GCPでサポートしている暗号化セットはここに記載されている。
Supported IKE Ciphers

関連Config抜粋

!
crypto ikev2 proposal GCP_proposal
encryption aes-cbc-256 aes-cbc-192 aes-cbc-128
integrity sha256
group 16
!
crypto ikev2 policy GCP_policy
proposal GCP_proposal
!
crypto ikev2 keyring GCP_Key
peer GCP
address <GCPのIPアドレス>
pre-shared-key <設定した共有キー>
!
!
!
crypto ikev2 profile IKEv2_Profile
match identity remote address <GCPのIPアドレス> 255.255.255.255
identity local address <家のGlobal IP>
authentication remote pre-share
authentication local pre-share
keyring local GCP_Key
lifetime 3600
!

crypto ipsec transform-set TS esp-aes 256 esp-sha256-hmac
mode tunnel
!
crypto ipsec profile GCP_Profile
set transform-set TS
set pfs group16
set ikev2-profile IKEv2_Profile
!
!
crypto map GCP_map 5 ipsec-isakmp
set peer <GCPのIPアドレス>
set transform-set TS
set pfs group16
set ikev2-profile IKEv2_Profile
match address GCP_ACL
!
!
interface Vlan100
description to 192.168.1.0/24
ip address 192.168.1.2 255.255.255.0
crypto map GCP_map
!
ip access-list extended GCP_ACL
permit ip 192.168.0.0 0.0.255.255 10.10.10.0 0.0.0.255
!
!

通信確認

Ping確認

#ping 10.10.10.10 source 192.168.1.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.10.10.10, timeout is 2 seconds:
Packet sent with a source address of 192.168.1.2
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 160/162/164 ms

IP-Secステータス

#show crypto session
Crypto session current status

Interface: Vlan100
Profile: IKEv2_Profile
Session status: UP-ACTIVE
Peer: 35.231.219.234 port 4500
Session ID: 2208
IKEv2 SA: local 192.168.1.2/4500 remote <GCPのIPアドレス>/4500 Active
IPSEC FLOW: permit ip 192.168.0.0/255.255.0.0 10.10.10.0/255.255.255.0
Active SAs: 2, origin: crypto map

以上。
次はルートベースのVPN設定を試す。

ちなみに, MTUサイズを確認してみるとトンネルのオーバーヘッド含めて1422だった。

$ ping 10.10.10.10  -s 1394 -M do
PING 10.10.10.10 (10.10.10.10) 1394(1422) bytes of data.
1402 bytes from 10.10.10.10: icmp_seq=1 ttl=63 time=162 ms
1402 bytes from 10.10.10.10: icmp_seq=2 ttl=63 time=161 ms
1402 bytes from 10.10.10.10: icmp_seq=3 ttl=63 time=160 ms
^C
--- 10.10.10.10 ping statistics ---
4 packets transmitted, 3 received, 25% packet loss, time 3001ms
rtt min/avg/max/mdev = 160.511/161.357/162.479/0.947 ms
$ ping 10.10.10.10 -s 1395 -M do
PING 10.10.10.10 (10.10.10.10) 1395(1423) bytes of data.
ping: sendmsg: Message too long
ping: sendmsg: Message too long
ping: sendmsg: Message too long
^C
--- 10.10.10.10 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2004ms