ブログ:
組み込みLinuxシステムでのVPN使用
ネットワーク機能は、さまざまな組み込みアプリケーションの要件に含まれることがますます一般的となっており、これにともなってデータ通信におけるセキュリティーの課題が生まれます。VPNはこの課題に対応する効果的な方法の1つです。加えて、VPNを利用すればファイアウォールやNATを通したリモートネットワークの構築も可能なため、組み込みシステムがリモートネットワークにアクセスできるようになります。この記事では、Linuxを稼働しているApalis iMX8QM上で、人気の高い2つのVPNプロトコル、OpenVPNとWireGuardを使用する方法について詳述します。Torizonを使用している場合は簡単にVPNを利用できます。このページのガイドに従ってください。
OpenVPNは、広く利用されているVPNプロトコルで、複数のOpenSSLベースの暗号化スキームに対応します。トランスポートレイヤープロトコルにTCPまたはUDPを利用可能で、柔軟性に優れています。WireGuardは、高速でシンプルなVPNプトロコルで、OpenVPNよりも優れた効率を発揮します。もともとはLinuxカーネル内で直接実装されていたもので、最新の暗号化アルゴリズム、Curve25519、ChaCha20、Poly1305、BLAKE2などに対応しています。トランスポートレイヤーにはUDPプロトコルを使用します。Linux 5.6以降、WireGuardはカーネルに統合されています。現在は活発な開発コミュニティーが存在し、Windows、macOS、BSD、iOSとAndroidに対応しています。Toradexのモジュール用にToradexが管理しているBSPはYocto Projectで構築されており、Open VPNとWireGuardをYoctoデプロイメントに追加するのは簡単です。
まず、local.conf構成ファイルに次の行を追加します。(後でリモート接続のデモンストレーションにApacheウェブサーバーを利用します。)
IMAGE_INSTALL_append = " apache2 openvpn wireguard-module wireguard-tools"
次に、layers/meta-openembedded/meta-networking/recipes-kernel/wireguard/wireguard-module_1.0.20200401.bb and comment out PKG_${PN} = "kernel-module-${MODULE_NAME}"を以下のように編集します。
# Kernel module packages MUST begin with 'kernel-module-', otherwise
# multilib image generation can fail.
#
# The following line is only necessary if the recipe name does not begin
# with kernel-module-.
#PKG_${PN} = "kernel-module-${MODULE_NAME}"
WireGuardはLinuxカーネルに基づいて実装されています。コードをシンプルに保つためにカーネル内のネットワーク機能が多用されているので、Yoocto Projectのデフォルトのカーネル設定を変更する必要があります。OpenVPNを利用する場合は、この手順を飛ばしてそのままBSPをコンパイルできます。
$ MACHINE=apalis-imx8 bitbake -c menuconfig virtual/kernel
Networking support → Networking options
[*] IP: advanced router
[*] FIB TRIE statistics
[*] IP: policy routing
[*] IP: equal cost multipath
[*] IP: verbose route monitoring
Networking support → Networking options → Network packet filtering framework (Netfilter) → IP: Netfilter Configuration
<M> raw table support (required for NOTRACK/TRACE)
Networking support → Networking options → Network packet filtering framework (Netfilter) → Core Netfilter Configuration
<M> "CONNMARK" target support
<M> "MARK" target support
*** Xtables matches ***
<M> "comment" match support
<M> "mark" match support
<M> "connmark" connection mark match support
カーネルの再設定が終わったら、BSPをコンパイルします。
$ MACHINE=apalis-imx8 bitbake tdx-reference-minimal-image
VPNの設定方法を説明する前に、このテストで利用するネットワークのトポロジーを紹介します。次の図で示されるように、VPNサーバーとして公開IPを持つサーバーが必要です。Apalis iMX8QMは、通信事業者が提供するオプティカルモデムにイーサネットを介して接続します。現在、オプティカルモデムが取得できるのは、通信事業者のNATが変換したイントラネットのIpv4アドレスのみです。このテストで利用する携帯電話は、基地局を通じて公開ネットワークに接続されます。
VPNサーバーの設定
詳細なサーバー設定の手順は、OpenVPNとWireGuard双方の公式ウェブサイトで見ることができます。ここでは、PiVPNという別のツールを利用してサーバーを設定します。PiVPNは、もともとRasberry Pi用のシンプルなサーバー管理ツールでしたが、UbuntuなどのDebianベースのディストリビューションでも利用可能です。次のコマンドを実行し、PiVPNをインストールします。
curl -L $ https://install.pivpn.io | bash
その後、pivpnを2回実行してApalis iMX8と携帯電話のOpenVPNとWireGuardアカウントを追加します。
$ pivpn ovpn add
$ pivpn wg add
次に、サーバーのネットワーク設定を変更します。
$ sudo iptables -A FORWARD -i wg0 -o wg0 -j ACCEPT
$ vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
$ sysctl -p /etc/sysctl.conf
携帯電話の設定
OpenVPNとWireGuardクライアントを携帯電話にインストールします。次に、上記でPiVPNが生成したovpnまたはconfファイルをインポートするか、QRコードをスキャンします。PiVPNは、とても使いやすい機能を提供します。
Apalis iMX8QMの設定
ネットワークマネージャーにはsystem-networkdを使用します。
root@apalis-imx8:~# systemctl disable connman
root@apalis-imx8:~# ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
Set the network interface to dynamically obtain an IP address.
root@apalis-imx8:~# vi /etc/systemd/network/wired.network
[Match]
Name=eth0
[Network]
DHCP=ipv4
Apacheウェブサーバーのデフォルトで表示されるコンテンツを変更します。ほかのクライアントはHTTPを利用してウェブページにアクセスできます。
/usr/share/apache2/default-site/htdocs/index.html
<html><body><h1>It works! Apalis iMX8.</h1></body></html>
OpenVPN
OpenVPN構成ファイルをopenvpnで開きます。
root@apalis-imx8:~# openvpn apalis-imx8.ovpn
成功すると、次の情報が表示されます。
Thu Jan 28 03:16:44 2021 OpenVPN 2.4.9 aarch64-tdx-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD] built on Apr 16 2020
Thu Jan 28 03:16:44 2021 library versions: OpenSSL 1.1.1i 8 Dec 2020, LZO 2.10
Enter Private Key Password:
Thu Jan 28 03:16:52 2021 /sbin/ip link set dev tun0 up mtu 1500
Thu Jan 28 03:16:52 2021 /sbin/ip addr add dev tun0 10.8.0.5/24 broadcast 10.8.0.255
Thu Jan 28 03:16:52 2021 /sbin/ip route add 125.107.107.37/32 via 192.168.123.1
Thu Jan 28 03:16:52 2021 /sbin/ip route add 0.0.0.0/1 via 10.8.0.1
Thu Jan 28 03:16:52 2021 /sbin/ip route add 128.0.0.0/1 via 10.8.0.1
Thu Jan 28 03:16:52 2021 Initialization Sequence Completed
VPNが有効なことを確認するには、ifconfigの出力でtun0インターフェースを探します。割り当てられたIPは10.8.0.5です。ほかのVPNに接続されたクライアントは、このIPを利用してApalis iMX8QMにアクセスできます。
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.8.0.5 P-t-P:10.8.0.5 Mask:255.255.255.0
inet6 addr: fe80::cd6f:13cd:62e9:4d1e/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:190 (190.0 B) TX bytes:1006 (1006.0 B)
携帯電話でOpenVPNを接続し、割り当てられたIPが10.8.0.3であることを確認します。携帯電話のブラウザーでhttp://10.8.0.5に移動すると、Apalis iMX8QMで稼働しているApacheサーバーに接続されます。
WireGuard
PiVPNが生成したapalis-imx8.confという構成ファイルを/etc/wireguard/wg0.confにコピーして、wg-quickを使って読み込みます。
root@apalis-imx8:~# wg-quick up wg0
ifconfigの出力で、wg0インターフェースを探します。割り当てられたIPは10.6.0.5です。
wg0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.6.0.5 P-t-P:10.6.0.5 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MTU:1420 Metric:1
RX packets:63 errors:0 dropped:0 overruns:0 frame:0
TX packets:127 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:6540 (6.3 KiB) TX bytes:15988 (15.6 KiB)
OpenVPNの例と同様、WireGuardモバイルアプリから接続を確立した後、携帯電話のブラウザーでhttp://10.6.0.5に移動するとApalis iMX8QM上のApacheサーバーに接続できます。
まとめ
VPNを利用すると、異なるネットワークにあるデバイスに接続できるため、リモート管理が便利になります。しかし、認証情報や接続されたデバイスのそのほかの情報に攻撃者がアクセスするのを防ぐため、サーバーでは十分なセキュリティー対策を講じる必要があります。