Docker 内に VPN サーバを導入してスマホから接続する
背景
海外旅行先で、日本国外のIPアドレスだと利用できない日本のサービスがいくつかあります。
私は NordVPN を使用した経験があります。しかし、「日本」と表示されているノード(サーバ番号)に接続しても、日本からの接続では無い、とエラーが表示され 利用できないサービス ( dアニメストア ) がありました。ノードはランダムで選択されます。全部の「日本」ノードがダメという訳ではありませんが、試した限り、体感8割ぐらいの「日本」ノードからは利用できなかったです。
ちなみに NotdVPN 自体は、回線速度や接続可能な国の数の観点から総合的に良いサービスであり、インターネットのセキュリティ保護の目的で利用を続けています。
しかしながら、確実に接続可能な日本のVPNサーバ、の目的は達成されていません。無料の VPN はセキュリティ的に怪しいので、それならば自前で作ってしまおう、というのが今回の記事の動機になります。
構成図
全体構成図
Docker がインストールされた Ubuntu サーバに、VPN サービスをインストールしたコンテナを用意し、スマホからコンテナ内 VPN に接続します。Docker を利用しているのは、基本的にホスト環境での様々な検証や変更を避けたいからです。
VPN ライブラリ - strongSwan -
あまり VPN の技術的なところは詳しくないのですが、ひとえに VPN といっても様々なプロトコルが存在します。やりたい事はスマホからの VPN 接続ですが、手持ちの Android 12 では IKEv2 プロトコルしかデフォルトで対応していませんでした。
Android 12 の VPN接続画面
オープンソースで有名な VPN プロジェクトとして、OpenVPN や SoftEther VPN が挙げられますが、2022年10月時点ではどちらも IKEv2 プロトコルに対応していなかったため、strongSwan を利用して VPN 接続を試みます。
参考サイト
特に参考にしたサイトはここ(紹介元の日本語サイトはここ)。ほぼ丸パクリと言っても良いです。今回の構成において、微妙に分かりにくかった設定について補足するものとします。
事前準備
Ubuntu
確実な日本のIPアドレスを用意するには、自宅に設置したサーバを使うのが良いです。自宅の適当なパソコンに Ubuntu 22.04 をインストールします。
Docker
公式HP を参考にインストールします。
作成手順
VPN コンテナ作成
Image pull
Ubuntu 20.04 image を Docker Hub から pull します。
sudo docker pull ubuntu:20.04
Create docker network
独立した docker network にコンテナを置きたいので、次のようにネットワークを作成します。ここではサブネットを 172.18.1.XXX としています。
sudo docker network create --subnet=172.18.1.0/24 vpnnw
Container run
IKEv2 では UDP の 500, 4500 port を使用するので、-p オプションでポートを開けます。セキュリティ上、これらのポート番号は変えた方が良いと思われますが、ポート番号の設定箇所が分からなかったので断念します。
ちなみに、後の作業で一部証明書の取得が必要なので、-v オプションで共有ディレクトリを設定した方が便利です。
sudo docker run -itd --privileged --name vpn --net=vpnnw --ip=172.18.1.2 -p 4500:4500/udp -p 500:500/udp ubuntu:20.04 /bin/bash --login
sudo docker exec -it vpn /bin/bash
Module install
必要なモジュールをインストールします。
apt-get update
apt install -y strongswan strongswan-pki libcharon-extra-plugins libcharon-extauth-plugins libstrongswan-extra-plugins tzdata libtss2-tcti-tabrmd0 vim systemctl ufw
tzdata での日時設定は日本/東京を選択します。
tzdata の config. 赤アンダーライン箇所で、各数字を入力してEnterを押す
証明書の作成
VPN 接続で使用する各証明書の準備です。"VPN root CA" はCA証明書の名前なので、適宜変更してください。
mkdir -p ~/pki/{cacerts,certs,private}
chmod 700 ~/pki
ipsec pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/ca-key.pem
ipsec pki --self --ca --lifetime 3650 --in ~/pki/private/ca-key.pem --type rsa --dn "CN=VPN root CA" --outform pem > ~/pki/cacerts/ca-cert.pem
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/server-key.pem
次のコード内で、PUBLIC IPアドレスを入力する必要があります。
“111.111.111.111" をインターネット側で見えている IPアドレスに置き換えて入力してください。
pki --pub --in ~/pki/private/server-key.pem --type rsa | pki --issue --lifetime 1825 \
--cacert ~/pki/cacerts/ca-cert.pem \
--cakey ~/pki/private/ca-key.pem \
--dn "CN=111.111.111.111" --san @111.111.111.111 --san 111.111.111.111 \
--flag serverAuth --flag ikeIntermediate --outform pem \
> ~/pki/certs/server-cert.pem
IPアドレスの調べ方は、例えばこのサイトです。82.102.28.37 がPUBLIC IPアドレスです。
PUBLIC IPアドレス
作成した証明書ファイルを、所定の場所にコピーします。
cp -r ~/pki/* /etc/ipsec.d/
VPN 設定ファイルの編集
設定ファイルを編集します。バックアップを取ってから編集します。
※vi コマンドで編集しますが、他ツールで編集しても問題ありません。
cp /etc/ipsec.conf /etc/ipsec.conf.original
vi /etc/ipsec.conf
線を引いた箇所を削除し、以降の設定を貼り付けします。"111.111.111.111″ は先ほどの PUBLIC IPアドレスに変更してください。
“10.10.10.0/24" は、VPN で割り当てられるIPアドレスです。変更しても問題ありませんが、以降で設定するIPルーティングの設定は、この割り当てを基準に記述します。
- config setup
- # strictcrlpolicy=yes
- # uniqueids = no
config setup
charondebug="ike 1, knl 1, cfg 0"
uniqueids=no
conn ikev2-vpn
auto=add
compress=no
type=tunnel
keyexchange=ikev2
fragmentation=yes
forceencaps=yes
dpdaction=clear
dpddelay=300s
rekey=no
left=%any
leftid=111.111.111.111
leftcert=server-cert.pem
leftsendcert=always
leftsubnet=0.0.0.0/0
right=%any
rightid=%any
rightauth=eap-mschapv2
rightsourceip=10.10.10.0/24
rightdns=8.8.8.8,8.8.4.4
rightsendcert=never
eap_identity=%identity
ike=chacha20poly1305-sha512-curve25519-prfsha512,aes256gcm16-sha384-prfsha384-ecp384,aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024!
esp=chacha20poly1305-sha512,aes256gcm16-ecp384,aes256-sha256,aes256-sha1,3des-sha1!
接続ユーザの作成
パスワード認証でVPN接続するためのユーザ/パスワードの設定を行います。
※上記以外の接続方法については分かりません。
まずは設定ファイルを開きます。
vi /etc/ipsec.secrets
次のように追記します。user_id に使用したいユーザ名を、"password" にパスワードを適宜入力してください。
※このままでも、セキュリティ的には問題ありますが、接続は可能です。
: RSA "server-key.pem"
user_id : EAP "password"
編集が終わったら、次のように権限を変更しておきます。
chmod 600 /etc/ipsec.secrets
UFW
これまでの設定で、VPN 接続自体は可能です。※サービスの起動が必要です(/etc/init.d/ipsec restart)
しかし、これだけでは 10.10.10.0/24 のネットワークから外に出られず、つまり肝心のインターネットに接続できません。インターネットに接続するためのIPフォワードの設定を行います。
まず、ufw を有効化して、使用するUDPポートへのアクセスを許可します。
ufw enable
ufw allow 500,4500/udp
次に、NATの設定と、IPフォワードの設定をします。
※ここの設定ファイルの内容はよく分かりません。
vi /etc/ufw/before.rules
次の箇所を追記してください。
+ *nat
+ -A POSTROUTING -s 10.10.10.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
+ -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
+ COMMIT
+ *mangle
+ -A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.0/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
+ COMMIT
# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines
+ -A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 10.10.10.0/24 -j ACCEPT
+ -A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 10.10.10.0/24 -j ACCEPT
ufw を再起動して設定を反映します。
ufw disable
ufw enable
strongSwan のサービス起動
/etc/init.d/ipsec restart
ルーターの設定
今回の構成ではルーターがあるので、インターネット側からのUDPポートへの接続を許可してあげる必要があります。
こちらの設定はルーターのメーカーに依存するのでそれぞれで設定してください。
設定ページは、ほとんどの場合、ルーターのLAN側のゲートウェイアドレスにブラウザから接続すれば開くと思います。(今回の構成では、http://192.168.1.1)
Android 12 からのVPN接続
クライアントとなるスマホ側での設定です。
CA証明書のインストール
VPN接続するために、CA証明書のインポートが必要になります。
コンテナ内にある、/etc/ipsec.d/cacerts/ca-cert.pem ファイルをどうにかしてスマホに持ってきます。※Google Drive内でも良いです。
Android 12 CA証明書インストール手順
VPN接続設定
次のように設定します。「名前」は何でも良いです。
Android 12 VPNプロファイル設定画面
VPN接続し、インターネットに接続できる事を確認してください。
また、IPアドレスが PUBLIC IPアドレスと同じになっていることを確認してください。
Windows 11 からのVPN接続
CA証明書のインポート
VPN接続するために、CA証明書のインポートが必要になります。
コンテナ内にある、/etc/ipsec.d/cacerts/ca-cert.pem ファイルをローカルに置き、次のようにファイル名を変更します。
ca-cert.pem ⇒ ca-cert.cer
ファイルをダブルクリックし、次のようにファイルを設置します。
Windows11 CA証明書インストール手順
VPN接続
「設定」⇒「ネットワークとインターネット」⇒「VPN」⇒「VPNを追加」から、次のように設定します。接続名は何でもかまいません。「サーバ名またはアドレス」に関しては、WAN側のアドレスに設定してください。
最後に
以上が、DockerコンテナにVPNサービスを構築し、スマホやWindows PCから接続する手順になります。
Discussion