リモートネットワークに設置した踏み台ホストPC、 Ubuntu 22.04 デスクトップに OpenConnect VPN クライアントをセットアップ。さらに自身のネットワークへの 自動接続 することで、リモートネットワーク管理が便利になりました。
VPNサーバはOpenWRTのOCServ
VPNの接続先は、自宅に設置しているOpenWrt仮想マシンに構築した、OpenConnect VPNサーバです(製作記事はこちら)。
今回新たに設定するクライアント用に、VPNユーザアカウントをサーバ側で作成しました(作成後、パスワードはエンコードされるので後からの参照は不可)。
セキュリティ的には鍵を交わしての認証が望ましいとろですが、今回も単純な作業で済むパスワード認証とします。
クライアントは非GUI版
このVPNサーバへは、Ubuntu22.04デスクトップ機から、Network ManagerのOpenConnectプラグインを使って、必要時にその都度人手により、接続するようにしています。
今回設定するクライアントは無人でも自動接続するのが目標なので、GUIは不要。システムはKubuntu 22.04デスクトップです。
1 2 3 4 5 6 7 8 |
$ uname -a Linux NUC8Kubu 6.2.0-32-generic #32~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 18 10:40:13 UTC 2 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy |
パッケージマネージャから、必要なOpenConnectパッケージをインストールします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$sudo apt update $ apt list openconnect -a openconnect/jammy 8.20-1 amd64 $ sudo apt install openconnect The following additional packages will be installed: libjs-sphinxdoc python3-asn1crypto python3-html5lib python3-mechanize python3-webencodings vpnc-scripts Suggested packages: python3-genshi python3-lxml dnsmasq resolvconf The following NEW packages will be installed: libjs-sphinxdoc openconnect python3-asn1crypto python3-html5lib python3-mechanize python3-webencodings vpnc-scripts 0 upgraded, 7 newly installed, 0 to remove and 0 not upgraded. Need to get 1,202 kB of archives. After this operation, 6,501 kB of additional disk space will be used. Do you want to continue? [Y/n] y $ openconnect --version OpenConnect version v8.20-1 Using GnuTLS 3.7.3. Features present: TPMv2, PKCS#11, RSA software token, HOTP software token, TOTP software token, Yubikey OATH, System keys, DTLS, ESP Supported protocols: anyconnect (default), nc, gp, pulse, f5, fortinet, array Default vpnc-script (override with --script): /usr/share/vpnc-scripts/vpnc-script |
コマンドラインからOpenConnectクライアントを試してみます。
( VPNSERVER_URL , USERNAME , PASSWORD を適宜編集のこと)
1 2 3 4 5 6 7 8 9 10 11 12 |
$ echo "PASSWORD" | sudo openconnect VPNSERVER_URL -u USERNAME --passwd-on-stdin POST https://VPNSERVER_URL/ Attempting to connect to server VPNSERVER_URL Connected to VPNSERVER_URL SSL negotiation with VPNSERVER_URL Server certificate verify failed: signer not found Certificate from VPN server "VPNSERVER_URL" failed verification. Reason: signer not found To trust this server in future, perhaps add this to your command line: --servercert pin-sha256:bfbBKt4q........................................ Enter 'yes' to accept, 'no' to abort; anything else to view: fgets (stdin): Operation now in progress |
接続を確立する前の小言は接続先サーバの信頼性に関することで、以降このプロンプトを避けるには、表示されている --servercert オプションを併記するようにします。
スプリットトンネリング設定
このままでは接続中、全てのトラフィックがVPNトンネルへ向かってしまいます。今回はトンネル利用を互いのローカルネットワークの疎通にとどめたいので、スプリットトンネリングを設定します。
Network Managerの設定GUIウィンドウであれば、「この接続はネットワーク上のリソースのためだけに使用」にチェックを入れれば済む話が、CLIベースではなかなか面倒です。
そんな標準では煩雑な手順をスプリットトンネリングに特化して単純にしてくれるのが、このvpn-sliceというPythonスクリプトです。
導入はpipから。pipがまだ入っていないので、パッケージマネージャで先にインストールします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ python --version Python 3.10.12 $ pip Command 'pip' not found, but can be installed with: sudo apt install python3-pip $ sudo apt install python3-pip 0 upgraded, 48 newly installed, 0 to remove and 0 not upgraded. Need to get 61.3 MB of archives. After this operation, 217 MB of additional disk space will be used. Do you want to continue? [Y/n] y $ pip --version<br>pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ sudo pip3 install "vpn-slice[dnspython,setproctitle]" Collecting vpn-slice[dnspython,setproctitle] Downloading vpn_slice-0.16.1-py3-none-any.whl (34 kB) Collecting dnspython Downloading dnspython-2.4.2-py3-none-any.whl (300 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 300.4/300.4 KB 8.2 MB/s eta 0:00:00 Collecting setproctitle Downloading setproctitle-1.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (30 kB) Installing collected packages: setproctitle, dnspython, vpn-slice Successfully installed dnspython-2.4.2 setproctitle-1.3.2 vpn-slice-0.16.1 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv user@NUC8Kubu:~$ sudo vpn-slice --self-test *************************************************************************** *** Self-test passed. Try using vpn-slice with openconnect or vpnc now. *** *************************************************************************** |
セルフテストも問題無くクリアしたので、早速使ってみます。使い方は、OpenConnectのコマンドラインオプション -sを使って記述するのだそう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ echo "PASSWORD" | sudo openconnect VPNSERVER_URL -u USERNAME --passwd-on-stdin \ --servercert pin-sha256:bfbBKt4q.................. --no-dtls \ -s 'vpn-slice -i 192.168.61.0/24 192.168.201.0/24 192.168.202.0/24' $ route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default _gateway 0.0.0.0 UG 100 0 0 eno1 ############### _gateway 255.255.255.255 UGH 0 0 0 eno1 link-local 0.0.0.0 255.255.0.0 U 1000 0 0 eno1 192.168.12.0 0.0.0.0 255.255.255.0 U 100 0 0 eno1 192.168.61.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0 dns0.tun1 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 192.168.201.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0 192.168.202.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0 |
vpn-sliceには接続先サブネット( 192.168.61.0/24 )の他、トンネル内の別のクライアントとの疎通も確保したいので、トンネル内のサブネット( 192.168.201.0/24 , 192.168.202.0/24 )も列記しておきました。
サービス化して自動接続
OpenConnectコマンドラインの仕様がかたまったら、自動接続のためにサービスファイルへ仕上げます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ cat /etc/systemd/system/autovpn_openconnect.service [Unit] Description=Auto Connect to OpenConnect VPN After=network.target [Service] Type=simple User=root RestartSec=10 Environment=password=correcthorsebatterystaple ExecStart=/bin/sh -c 'echo PASSWORD | openconnect VPNSERVER_URL \ -u USERNAME --passwd-on-stdin \ --servercert pin-sha256:bfbBKt4q.................. \ --no-dtls -s "vpn-slice -i 192.168.61.0/24 192.168.201.0/24 192.168.202.0/24"' Restart=always [Install] WantedBy=multi-user.target |
サービスを有効にして開始します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ sudo systemctl daemon-reload $ sudo systemctl enable autovpn_openconnect Created symlink /etc/systemd/system/multi-user.target.wants/autovpn_openconnect.service → /etc/systemd/system/autovpn_openconnect.service. $ sudo systemctl status autovpn_openconnect $ systemctl status autovpn_openconnect ● autovpn_openconnect.service - Auto Connect to OpenConnect VPN Loaded: loaded (/etc/systemd/system/autovpn_openconnect.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2023-09-11 14:03:38 HKT; 2s ago Main PID: 8643 (sh) Tasks: 2 (limit: 18866) Memory: 2.1M CPU: 229ms |
これで例えばVPNサーバ側から切断しても、数秒で再接続されるようになりました。
尚、上述のサービスファイル内の RestartSec=10 で高頻度の実行を抑制しているのは、システムコールドスタート時に自動接続ず、システムログに次の文言を見つけたため。
1 |
Start request repeated too quickly. |
systemdのサービスユニットの起動回数制限に触れてしまうのを避けるために、10秒のアイドル時間を設けたというわけです。