私のWireguardを利用したVPNのセットアップ
背景
グローバルIPが割り当てられない環境(マンション, 職場, 研究室)に機械学習サーバーを設置したい。でも、グローバルIPがないとLAN外から接続できませんね。そこで、クラウドサービスでVPNサーバーを建てて、出先のラップトップからVMのグローバルIPを踏み台として、機械学習サーバーに接続できるようにしたいと思います。
ネットで調べるとVPNのフレームワークとして、主にopenvpn, wireguard, softetherの3つが主流のようです。今回は特にモダンでシンプルと評判のwireguardを使用したVPN環境構築を行います。
ネットワーク図
以下のようなネットワーク構成になります。今回は接続先がWSL(Windows Subsystem for Linux), 接続元がChromebookと仮定し、VPNサーバーとしてGCPのGCE(Ubuntu)を利用した手順を紹介します。
下準備
- GCP, AWS等でVMのインスタンスを建てる
私はGCP派なので、例えばGCEを建てる際は以下のとおりに設定するとよいです。- UDPの51820を開く
- イメージはUbuntuで作成
- エフェメラルIPではなく固定IPを使用
- SSH keyを登録
- デスクトップPCにWSLを入れる
VPNサーバーのセットアップ
-
Wireguardのインストール
sudo apt update -y sudo apt upgrade -y sudo apt autoremove -y sudo apt install wireguard -y
-
サーバー鍵の生成
sudo -i <<EOF cd /etc/wireguard/ wg genkey | tee server_private_key | wg pubkey > server_public_key chmod 400 server_private_key server_public_key exit EOF
-
サーバーの設定
sudo tee /etc/wireguard/wg0.conf > /dev/null <<EOF [Interface] PrivateKey = $(sudo cat /etc/wireguard/server_private_key) Address = 10.10.10.1/24 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ListenPort = 51820 EOF
-
ポートフォワーディング設定
sudo tee /etc/sysctl.conf> /dev/null <<EOF net.ipv4.ip_forward = 1 EOF sudo sysctl -p
-
クライアントの追加
以下のコードを実行し、クライアントIDを入力すればクライアントの追加ができます。今回は、クライアントを2台追加するため、2度実行してください。read -p "Enter client ID (2-254): " client_id if ! [[ $client_id =~ ^[2-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]$ ]]; then echo "Error: Client ID must be between 2 and 254" exit 1 fi # Check if client configuration file already exists client_conf="/etc/wireguard/client${client_id}.conf" if [ -f "$client_conf" ]; then echo "Configuration file for client ${client_id} already exists: $client_conf" read -p "Do you want to overwrite it? (y/n) " overwrite if [[ $overwrite != "y" ]]; then echo "Aborting..." exit 0 fi fi sudo -i <<EOF cd /etc/wireguard/ wg genkey | tee client${client_id}_private_key | wg pubkey > client${client_id}_public_key chmod 400 client${client_id}_private_key client${client_id}_public_key exit EOF sudo tee -a /etc/wireguard/wg0.conf > /dev/null <<EOF [Peer] PublicKey = $(sudo cat /etc/wireguard/client${client_id}_public_key) AllowedIPs = 10.10.10.${client_id}/32 EOF sudo tee /etc/wireguard/client${client_id}.conf > /dev/null <<EOF [Interface] PrivateKey = $(sudo cat /etc/wireguard/client${client_id}_private_key) Address = 10.10.10.${client_id}/24 DNS = 1.1.1.1 [Peer] PublicKey = $(sudo cat /etc/wireguard/server_public_key) EndPoint = $(curl ifconfig.me):51820 AllowedIPs = 10.10.10.0/24 PersistentKeepalive = 25 EOF
-
クライアントの設定ファイルを閲覧
下記のコードで、後の設定に必要な設定ファイルを閲覧できます。sudo cat /etc/wireguard/client${client_id}.conf
-
VPNサーバーの起動
sudo systemctl enable wg-quick@wg0 sudo systemctl start wg-quick@wg0
もし新しくクライアントを追加した場合は、以下のコマンドで再起動する必要があります。
sudo wg-quick down wg0 sudo wg-quick up wg0 sudo systemctl start wg-quick@wg0
-
接続できているかテスト
以下のようにしてpingコマンドで接続できるか確認できます。ちなみに、Windowsはpingを返答してくれません。ping 10.10.10.X
クライアントサイドのセットアップ(Windowsの場合)
- GUIアプリのインストール
https://www.wireguard.com/install/ からインストールできます。 - 接続設定
アプリを起動して、左下のAdd Tunnel -> Add Empty Tunnelをクリックし、先程のクライアントの設定ファイルをコピペします。
クライアントサイドのセットアップ(Chromebookの場合)
- GUIアプリのインストール
https://www.wireguard.com/install/ に記載されている、PlayStoreからインストールできます。 - 接続設定
アプリを起動し、先程のクライアントの設定ファイルを参考に接続先を追加します。設定ファイルを.confという拡張子でテキストファイルとして保存すれば、import from a fileから簡単に追加できます。
WSLに直接SSHする
このままでは、Windowsに接続できるようになりましたが、WSLに接続はできていません。私の別記事を参考にしてください。
まとめ
以上を持って無事、グローバルIPのないパソコンの仮想環境に構築した機械学習サーバーに、VPNサーバーを踏み台として、出先のノーパソから接続できるようになりました。快適なリモート環境を楽しんでください。
あとがき
VS Codeの拡張機能であるRemote SSHは、現時点ではLinuxかMacでのみリモート上でDockerコンテナを開くことができます。つまり、WindowsのDocker Desktopを使用してDevcontainer環境をリモートから利用することは難しいです。
私は意地でもDevcontainerを使用したいと考えていたため、WSLにDockerをインストールし、最初はWSLがWireguardクライアントとしてVPN接続することで解決できると思っていました。しかし、Wireguardはopenresolvコマンドを使用する一方で、WSLはopenresolvを使用しない特殊な仕組みを持っているため、WSLからのVPN接続はできないことがわかりました。
そのため、WindowsがWireguardでVPN接続し、内部でポートフォワードを行うことで、環境構築を完了させました。
付録
クライアントサイドのセットアップ(Linuxの場合)
クライアントがLinuxの場合でも同様に行えます。
-
Wireguardのインストール
sudo apt install wireguard -y
-
接続設定
sudo nano /etc/wireguard/wg0.conf
に設定ファイルをコピペしてください。
-
接続開始
sudo systemctl enable wg-quick@wg0 sudo systemctl start wg-quick@wg0
すべての通信をVPN経由で行いたい場合
今回、クライアントは10.10.10.X
に当てた通信だけをVPN経由で行いました。しかしながら、出先ではブラウジングもVPN経由で行いたいはずです。すべての通信をVPN経由で行うためには、クライアントの設定ファイルのAllowedIPsを0.0.0.0/0
に変更してください。
[Interface]
...
[Peer]
...
AllowedIPs = 0.0.0.0/0
...
Discussion