Coderの構築により、どこにいてもどのPCでも同じ開発環境を利用することができるようになりました。
しかしながら、Dockerでマイクロサービスを作成して、立ち上げた後の動作確認はLAN内から実施する必要があります。
こんな時に便利なのが、VPNサーバです。
こういった用途で、筆者は、大昔にVPNサーバをラズパイ上に構築していましたが、少し前にAndroid12のスマホから接続できなくなっていて、そのまま放置していました。
今回、そろそろ直そうと思い立ち、ラズパイ上にVPNサーバを再構築しました。
ラズパイは、消費電力が少ないため、個人のVPNサーバの様な常設の基盤サービスを動作させるのに打ってつけです。
一方で、いつ壊れてもおかしくないリーズナブルなサーバなので、構築手順をここに残すことにしました。
目次
前提
- Raspberry Pi(Raspbian)にSSH接続できる状態である。
- インターネット側からアクセス可能なFQDNを持っていること。※以降の手順では[サーバのFQDN]と表記する
システム、ネットワーク構成と構築手順の流れ
再構築前のVPNサーバでは、SoftEtherという超簡単にVPNサーバを構築できるソフトウェアを利用していましたが、Android12のIKEv2というプロトコルに対応しておらず、仕方なくStrongSwanというソフトウェアに変更しました。結構手順が多くて大変です。
システム構成図です。
Raspberry PiにVPNソフトウェア「StrongSwan」を構築、設定します。
続いて、ネットワーク構成図です。
手順は下記流れになります。
①StrongSwan導入
何はともあれ、ソフトウェアをインストールします。
②認証用の自己証明書作成
パスワード認証も可能ですが、クライアント証明書認証にするため作成します。
③StrongSwanの設定
作成した証明書の紐付け、プロトコルの設定、VPNセグメントの設定などを行います。
④ルータのポートフォワード設定
ルータで外からのVPN接続をラズパイに転送する設定を行います。
⑤Raspberry Piのネットワーク設定
ラズパイをルータ化する設定です。VPNセグメントからの通信をLAN内にルーティングします。
⑥Androidからの接続確認
AndroidにStrongSwanアプリとクライアント証明書を導入し、LAN内のファイルサーバなどに接続してみます。
VPNサーバ構成手順
①StrongSwan導入
まずはインストールです。ラズパイにrootログインし、下記コマンドを流し込みます。
apt-get update
apt-get upgrade
apt install strongswan
apt install strongswan-pki
apt install libstrongswan-extra-plugins
②認証用の自己証明書作成
次に、自己証明書類を作成します。下記コマンドを流し込みますが、[サーバのFQDN]、[メールアドレス]は置き換えてください。なお、証明書の有効期限は10年とします。
cd /etc/ipsec.d/
ipsec pki --gen --type rsa --size 4096 \
--outform pem \
> private/strongswanKey.pem
chmod 600 private/strongswanKey.pem
ipsec pki --self --ca --lifetime 3650 \
--in private/strongswanKey.pem --type rsa \
--dn "C=CH, O=strongSwan, CN=strongSwan Root CA" \
--outform pem \
> cacerts/strongswanCert.pem
ipsec pki --print --in cacerts/strongswanCert.pem
ipsec pki --gen --type rsa --size 2048 --outform pem > private/vpnHostKey.pem
chmod 600 private/vpnHostKey.pem
ipsec pki --pub --in private/vpnHostKey.pem --type rsa | \
ipsec pki --issue --lifetime 3650 --outform pem \
--cacert cacerts/strongswanCert.pem \
--cakey private/strongswanKey.pem \
--dn "C=CH, O=strongSwan, CN=[サーバのFQDN]" \
--san [サーバのFQDN] \
--flag serverAuth --flag ikeIntermediate \
> certs/vpnHostCert.pem
ipsec pki --print --in certs/vpnHostCert.pem
ipsec pki --gen --type rsa --size 2048 --outform pem > private/ClientKey.pem
chmod 600 private/ClientKey.pem
ipsec pki --pub --in private/ClientKey.pem --type rsa | \
ipsec pki --issue --lifetime 3650 --outform pem \
--cacert cacerts/strongswanCert.pem \
--cakey private/strongswanKey.pem \
--dn "C=CH, O=strongSwan, CN=[メールアドレス]" \
--san [メールアドレス] \
> certs/ClientCert.pem
作成したクライアント証明書をPKCS#12形式に変換します。下記コマンドを流し込むと、パスワード設定を求められますので、任意のパスワードを設定してください。
openssl pkcs12 -export -name "My own VPN client certificate" \
-inkey private/ClientKey.pem \
-in certs/ClientCert.pem \
-certfile cacerts/strongswanCert.pem \
-caname "strongSwan Root CA" \
-out Client.p12
Android端末にクライアント証明書をインストールするときに、設定したパスワードを入力する必要があります。パスワードを知っている人だけが、クライアント端末へ証明書導入できるため、万が一ファイルが外部に漏れても安全ということです。
出力されたClient.p12をそのままAndroid端末に読み込めないので、base64に変換し、sswanファイルを作成します。
base64 Client.p12
→クライアント証明書が文字列で表示されます。
PCの適当な場所に「Client.sswan」というファイルを作成し、下記入力します。
※[base64文字列]を上記コマンドの結果に置き換えます。[サーバのFQDN]も置き換えてください。
{
"uuid": "a79d0628-cb3c-416a-814a-6f953603deb0",
"name": "My own VPN client certificate",
"type": "ikev2-cert",
"remote": {
"addr": "[サーバのFQDN]"
},
"local": {
"p12": "[base64文字列]"
}
}
③StrongSwanの設定
続いて、StrongSwanの設定ファイルを作成します。
任意のエディタで/etc/ipsec.confを開きます。
元々の文字列はすべて削除し、下記文字列を入力します。
VPNのセグメントは、rightsourceip=192.168.20.0/24で設定しています。LANのセグメントと重複していなければ、そのままでよいです。重複している場合は、第3オクテットの20を21などに変更しましょう。
/etc/ipsec.conf
config setup
charondebug="cfg 2, dmn 2, ike 2, net 2"
conn %default
keyexchange=ikev2
ike=aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024!
esp=aes128gcm16-ecp256,aes256gcm16-ecp384,aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128gcm16,aes256gcm16,aes128-sha256,aes128-sha1,aes256-sha384,aes256-sha256,aes256-sha1!
dpdaction=clear
dpddelay=300s
rekey=no
left=%any
leftsubnet=0.0.0.0/0
leftcert=vpnHostCert.pem
right=%any
rightdns=8.8.8.8,8.8.4.4
rightsourceip=192.168.20.0/24
conn IPSec-IKEv2
keyexchange=ikev2
auto=add
conn IPSec-IKEv2-EAP
also="IPSec-IKEv2"
rightauth=eap-mschapv2
rightsendcert=never
eap_identity=%any
conn CiscoIPSec
keyexchange=ikev1
# forceencaps=yes
rightauth=pubkey
rightauth2=xauth
auto=add
次に、/etc/ipsec.secretsを任意のエディタで開いて、元々の文字列を削除し、下記文字列に置き換えます。
/etc/ipsec.secrets
: RSA vpnHostKey.pem
設定ファイルを反映させます。
ipsec restart
ipsec status
現状、下記のように表示されるはずです。
Security Associations (0 up, 0 connecting):
none
まだ何もつながっていません。
VPNサーバの起動を確認しておきます。
ss -uapn
udp/500と4500が受付開始されていればオッケーです。
④ルータのポートフォワード設定
ルータの種類は、メーカー毎に多種多様のため、設定の抽象的な意味のみ記載します。
下記2設定を行います。
- インターネットからルータに届いたudp/500をラズパイ(VPNサーバ)のudp/500に転送
- インターネットからルータに届いたudp/4500をラズパイ(VPNサーバ)のudp/4500に転送
⑤Raspberry Piのネットワーク設定
最後に、VPNセグメントからの通信をLANにルーティングする設定です。
まずは、カーネル設定です。下記コマンドを流し込みます。
echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf
echo net.ipv6.conf.all.forwarding = 1 >> /etc/sysctl.conf
echo net.ipv4.conf.all.accept_redirects = 0 >> /etc/sysctl.conf
echo net.ipv4.conf.all.send_redirects = 0 >> /etc/sysctl.conf
sysctl -p
次に、ルーティング設定です。下記コマンドを流し込んで設定は完了です。
apt install iptables-persistent
iptables -t nat -A POSTROUTING -s 192.168.20.0/24 -j MASQUERADE
iptables-save > /etc/iptables/rules.v4
【参考】 実は、ラズパイで構築する前に、WindowsのWSLでVPNサーバを構築しようと企んでいましたが、このルーティングがどうしてもできず断念した経緯があります。 WSLの場合は、ホストのWindowsに来たUDP通信をWSLにフォワードする設定も必要となりますが、そちらについては、下記ソフトを使用することで実現できました。GitHub - matthid/UdpPortForwarder: Simple utility tool to forward udp ports, Supports multiple clients.Simple utility tool to forward udp ports, Supports multiple clients. - matthid/UdpPortForwarder
⑥Androidからの接続確認
Android端末にStrongSwanアプリを導入します。
作成した「Client.sswan」をAndroid端末に送り、StrongSwanアプリでClient.sswanを読み込んで、証明書をインストールします。
アプリを起動後、右上の「ADD VPN PROFILE」の横の3つの点をタップし、「Import VPN profile」をタップすると、ファイル選択画面が出ます。
そこで、「Client.sswan」を選択すると下記画面が出ます。
「IMPORT CERTIFICATE FROM VPN PROFILE」をタップすると、パスワード入力を求められます。
設定したパスワードを入力してOKをタップします。
下記画面が出ますので、そのままOKをタップします。
こちらもそのままOKをタップします。
下記画面が表示されます。「選択」をタップします。
最後に、右上の「IMPORT」をタップします。
これで設定は完了しました。
読み込んだプロファイルをタップし、VPN接続します。
下記のように「Status: Connected」となれば接続完了です。
あとは、LAN内の任意のサービス(ファイルサーバ等)に接続できることを確認します。
【追記】LinuxからのVPN接続
最近Linux Mint(Cinnamon)を使い始めました。
完成度が高くてWindowsのショートカットがそのまま使えたり、とても気に入っていますが、ラズパイのStrongSwanにVPN接続しようとして、VPNクライアントの設定に手こずったため、こちらに追記することにしました。
Ubuntuでも同じ手順で設定できると思います。
まず前提として、上記手順「②認証用の自己証明書作成」で作成しているクライアント証明書(p12ファイルやsswanファイル)は、Linuxではそのまま利用できません。
p12ファイルやsswanファイルには、サーバ証明書、クライアント証明書(秘密鍵、公開鍵)が含まれていて、クライアントへの導入が簡単にできるようになっています。
Linuxでは、p12ファイルにまとめる前の、それぞれの証明書をクライアントに導入する必要があります。
上記手順「②認証用の自己証明書作成」でラズパイに作成した下記ファイルを取得しておきます。
- /etc/ipsec.d/cacerts/strongswanCert.pem
- /etc/ipsec.d/certs/ClientCert.pem
- /etc/ipsec.d/private/ClientKey.pem
では早速、クライアントのLinuxで必要なモジュールを導入します。
sudo apt-get install strongswan libcharon-extra-plugins
導入完了後、/etc/ipsec.dディレクトリができますので、VPNサーバから取得した3つのファイルを同じディレクトリに置きます。
- /etc/ipsec.d/cacerts/strongswanCert.pem
- /etc/ipsec.d/certs/ClientCert.pem
- /etc/ipsec.d/private/ClientKey.pem
ファイルの所有者はすべてroot、権限は上2つの証明書が644、3つ目の秘密鍵が600です。
続いて、クライアント側のVPN設定ファイルを修正します。ファイルにデフォルト記載されている「#」から始まる行はコメント行のため、消してもそのままでも良いです。
/etc/ipsec.conf
config setup
conn ikev2-rw
right=[サーバのFQDN]
rightid=%any
rightsubnet=0.0.0.0/0
rightauth=pubkey
leftcert=ClientCert.pem
leftid="C=CH, O=strongSwan, CN=[メールアドレス]"
leftsourceip=%config
auto=add
/etc/ipsec.secrets
: RSA ClientKey.pem
最後に設定を再読込して設定完了です。
sudo ipsec restart
sudo ipsec reload
VPN接続コマンド
sudo ipsec up ikev2-rw
VPN切断コマンド
sudo ipsec down ikev2-rw
コメント
[…] 考になる記事がなくて断念してたのだが、以下の記事があった。Raspberry Pi(ラズパイ)上にVPNサーバ(StrongSwan)を導入する手順ここまでまとめられてるなら案外簡単そうだなって。中途半端に […]