OpenVPNで低コストにVPNサーバを自作構築して、固定IPでアクセス制限する
はじめに
こんにちは、Acompanyの田中です。この記事は、Acompanyのバレンタインアドカレ25日目の記事です。 今回は、OpenVPNで低コストにVPNサーバを自作構築して、固定IPでアクセス制限できるようにする手順を紹介します。
やりたいこと
- 固定IPでサーバへのアクセス制限がしたい
- 複数人で同じ固定IPを使えるようにしたい
- MacのPC環境でもUbuntuのサーバ環境でも同じ固定IPが使いたい
- できるだけ低コストで構築・管理したい
実現方法
StaticIP代の$3.6と合わせて大体月$20(3000円)くらいで運用できる。50クライアント分くらいは問題なく使えそう。
動作確認済み条件
- VPNクライアント動作環境
- OS: Ubuntu 22.04(GCE/n2-standard-2)
- OpenVPN: 2.5.9 x86_64-pc-linux-gnu
- OS: M1 MacBookPro(2021) Ventura 13.3.1
- OpenVPN Connect: 3.4.8
- OS: Ubuntu 22.04(GCE/n2-standard-2)
- VPNサーバ動作環境
- OS: Ubuntu 22.04(GCE/e2-small)
- OpenVPN: 2.5.9 x86_64-pc-linux-gnu
- OS: Ubuntu 22.04(GCE/e2-small)
1. VPNサーバの構築
VPNサーバとして利用するVMはEC2でもAzure VMでも何でも良いが、今回はGCE(Google Compute Engine)を使う。
1-1. VPCネットワークを作成
名前を適当に設定する。ここではvpc-openvpn-server
とした。
新しいサブネットsubnet-openvpn-server
を作成する。
リージョンはどこでも良いが、物理的に近い方が何かと良いのでasia-northeast-1
にしておく。
IPv4範囲は特にこだわりがなければ10.0.0.0/24
で良い。
ファイアウォールを設定する。
vpc-openvpn-server-allow-custom
のフィルタ
を0.0.0.0/0
、プロトコル/ポート
をudp:1194
とし、vpc-openvpn-server-allow-custom
とvpc-openvpn-server-allow-icmp
とvpc-openvpn-server-allow-ssh
にチェックを入れておく。
作成ボタンを押してVPCネットワークを作成する。作成が完了するまで数分待つ。
1-2. VMインスタンスを作成
GCEでVMインスタンスを作成していく。
名前とリージョンを設定する。名前はvm-openvpn-server
とした。リージョンは1-1でサブネットに設定したのと同じasia-northeast-1
としておく。
マシンの構成を選択する。今回はe2-small
としたが、一般的なvpnサーバとしての用途であればこのスペックで事足りると思う。
参考までに、40名ほどが利用している環境で`e2-medium`はオーバースペック気味。
そこまでCPUとメモリはあまり積む必要はない。ヘビーな使い方でなければネットワーク帯域幅もそこまで気にすることはないと思う。
帯域幅が気になる方はここを参照。
ブートディスクをUbuntu22.04(x86/64)に設定する。デフォルトでDebianになっているので変更を忘れずに。
IP転送を有効にする。VM作成後に設定を変更できないのでこれも忘れずに。
ネットワークインターフェースを設定する。default
は削除して「ネットワーク インターフェースを追加」を押して1-1で作成したVPCネットワークvpc-openvpn-server
とサブネットワークsubnet-openvpn-server
を選択する。
この時、「外部IPv2アドレス」の項目から静的外部IPv4アドレスを予約する。vmを再起動してもIPを固定するために必要。
作成ボタンを押してVMインスタンスを作成する。作成が完了するまで数分待つ。
1-3. OpenVPNのインストールとVPNサーバの設定
1-2で作成したVMインスタンスにsshし、以下のコマンドを叩いてoepnvpnをインストールする。
$ sudo apt-get -y install dnsutils
$ wget -O openvpn.sh https://get.vpnsetup.net/ovpn
$ sudo bash openvpn.sh --auto
引用: https://github.com/hwdsl2/openvpn-install
ログが以下で終わっていれば問題なくインストールとclient.ovpnファイルの作成が完了しているはず。
OpenVPN Script
https://github.com/hwdsl2/openvpn-install
(中略)
Finished!
The client configuration is available in: /home/XXXX/client.ovpn
New clients can be added by running this script again.
正常に完了したことの確認
$ openvpn --version
OpenVPN 2.5.9 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep 29 2023
library versions: OpenSSL 3.0.2 15 Mar 2022, LZO 2.10
Originally developed by James Yonan
Copyright (C) 2002-2022 OpenVPN Inc <sales@openvpn.net>
Compile time defines: enable_async_push=no enable_comp_stub=no enable_crypto_ofb_cfb=yes enable_debug=yes enable_def_auth=yes enable_dependency_tracking=no enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown enable_fast_install=needless enable_fragment=yes enable_iproute2=no enable_libtool_lock=yes enable_lz4=yes enable_lzo=yes enable_maintainer_mode=no enable_management=yes enable_multihome=yes enable_option_checking=no enable_pam_dlopen=no enable_pedantic=no enable_pf=yes enable_pkcs11=yes enable_plugin_auth_pam=yes enable_plugin_down_root=yes enable_plugins=yes enable_port_share=yes enable_selinux=no enable_shared=yes enable_shared_with_static_runtimes=no enable_silent_rules=no enable_small=no enable_static=yes enable_strict=no enable_strict_options=no enable_systemd=yes enable_werror=no enable_win32_dll=yes enable_x509_alt_username=yes with_aix_soname=aix with_crypto_library=openssl with_gnu_ld=yes with_mem_check=no with_openssl_engine=yes with_sysroot=no
$ sudo systemctl status openvpn-server@server.service
● openvpn-server@server.service - OpenVPN service for server
Loaded: loaded (/lib/systemd/system/openvpn-server@.service; enabled; vendor preset: enable>
Active: active (running) since Mon 2024-02-12 19:28:34 UTC; 3min 48s ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 3381 (openvpn)
Status: "Initialization Sequence Completed"
Tasks: 1 (limit: 2337)
Memory: 2.0M
CPU: 134ms
CGroup: /system.slice/system-openvpn\x2dserver.slice/openvpn-server@server.service
└─3381 /usr/sbin/openvpn --status /run/openvpn-server/status-server.log --status-ve(略)
上記から自動的にopenvpn2のインストールと、daemonの作成/再起動設定が行われていることがわかる。
.ovpn
ファイルを作成してVPNクライアント端末に配布
1-4. 以下のコマンドを実行すると、client-0001.ovpn
という名前のファイルが生成される。
$ sudo bash openvpn.sh <<ANSWERS
1
client-0001
ANSWERS
以下のようなログが出力される。
OpenVPN Script
https://github.com/hwdsl2/openvpn-install
OpenVPN is already installed.
Select an option:
1) Add a new client
2) Export config for an existing client
3) List existing clients
4) Revoke an existing client
5) Remove OpenVPN
6) Exit
Provide a name for the client:
+ ./easyrsa --batch --days=3650 build-client-full client-0001 nopass
client-0001 added. Configuration available in: /home/XXXX/client-0001.ovpn
この.ovpn
ファイルはVPNクライアントで使用する際に必要な設定ファイルのため、クライアント端末に配布しておく。
追加で別のユーザーを作成したい場合は、以下のようなコマンドを実行すれば<ユーザー名>.ovpn
という形式で新たにファイルが生成される。
$ sudo bash openvpn.sh <<ANSWERS
1
<ユーザー名>
ANSWERS
2. OpenVPNクライアントの設定(Mac Ventura編)
2-1. OpenVPN Connect をインストール
OpenVPN公式リンクからMacOSに対応したOpenVPN Connectをダウンロード&インストールする。
※ もし上記で解決しなかった場合はこちらの「インストール」セクションも併せて参照してください
2-2. .ovpn をインポート
- OpenVPN Connectを開いて「+」ボタンを押す
- Import Profileで.ovpnファイルをimportして「Connect」を押す
以下のようにCONNECTEDとなればVPN接続成功。
2. OpenVPNクライアントの設定(Ubuntu22.04編)
2-1. インストール
$ sudo apt update && sudo apt install -y openvpn
インストールできたことを確認する。
$ openvpn --version
OpenVPN 2.5.9 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep 29 2023
library versions: OpenSSL 3.0.2 15 Mar 2022, LZO 2.10
Originally developed by James Yonan
Copyright (C) 2002-2022 OpenVPN Inc <sales@openvpn.net>
Compile time defines: enable_async_push=no enable_comp_stub=no enable_crypto_ofb_cfb=yes enable_debug=yes enable_def_auth=yes enable_dependency_tracking=no enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown enable_fast_install=needless enable_fragment=yes enable_iproute2=no enable_libtool_lock=yes enable_lz4=yes enable_lzo=yes enable_maintainer_mode=no enable_management=yes enable_multihome=yes enable_option_checking=no enable_pam_dlopen=no enable_pedantic=no enable_pf=yes enable_pkcs11=yes enable_plugin_auth_pam=yes enable_plugin_down_root=yes enable_plugins=yes enable_port_share=yes enable_selinux=no enable_shared=yes enable_shared_with_static_runtimes=no enable_silent_rules=no enable_small=no enable_static=yes enable_strict=no enable_strict_options=no enable_systemd=yes enable_werror=no enable_win32_dll=yes enable_x509_alt_username=yes with_aix_soname=aix with_crypto_library=openssl with_gnu_ld=yes with_mem_check=no with_openssl_engine=yes with_sysroot=no
2-2. 設定
sudo openvpn --config "$CONFIG_FILE"
でvpnをopenできるが、今後sshでshellにログインする際に毎回上記のコマンドを実行するのは大変なので、以下のカスタムshellscriptを作成しておく。
/usr/local/bin/vpn.sh
を作成する。
$ sudo touch /usr/local/bin/vpn.sh
$ sudo chmod +x /usr/local/bin/vpn.sh
$ sudo vi /usr/local/bin/vpn.sh
以下のshellscriptをコピペする。
#!/bin/bash
# setup:
# $ sudo apt update && sudo apt install openvpn -y
# create client.ovpn
# $ sudo vi /etc/openvpn/client.ovpn
CONFIG_FILE="/etc/openvpn/client.ovpn"
LOG_FILE="/tmp/openvpn-status.log"
PID_FILE="/var/run/openvpn-client.pid"
function get_current_ip() {
curl -s https://api.ipify.org
}
function start_vpn() {
if pgrep -F "$PID_FILE" >/dev/null 2>&1; then
echo "VPN is already running."
return
fi
echo "Current IP: $(get_current_ip)"
echo "Starting VPN..."
sudo openvpn --config "$CONFIG_FILE" --log "$LOG_FILE" --daemon --writepid "$PID_FILE"
sleep 5
echo "New IP: $(get_current_ip)"
}
function stop_vpn() {
if [ -f "$PID_FILE" ]; then
sudo kill "$(cat $PID_FILE)"
sudo rm -f "$PID_FILE"
echo "VPN closed."
else
echo "VPN is not running."
exit 1
fi
}
function check_vpn_status() {
if pgrep -F "$PID_FILE" >/dev/null 2>&1; then
echo "VPN is running."
echo "Current IP: $(get_current_ip)"
else
echo "VPN is not running."
exit 1
fi
}
case "$1" in
open)
start_vpn
exit 0
;;
close)
stop_vpn
exit 0
;;
status)
check_vpn_status
exit 0
;;
*)
echo "Usage: $0 {open|close|status}"
exit 1
;;
esac
vpn.shが実行できるか確認する。
$ vpn.sh status # 接続確認
VPN is not running.
$ vpn.sh open # 接続
Current IP: ?.?.?.?
Starting VPN...
New IP: X.X.X.X
$ vpn.sh close # 切断
VPN closed.
これにより、以降はvpn.sh {open|close|status}
で接続, 切断, 接続確認ができるようになった。
3. 固定IPでアクセス制限
AWSの場合はセキュリティグループ、GCPの場合はファイアウォールのようなマネージドサービスを利用してIP制限ができる。今回はGCPの場合で説明する。
以下のように特定のネットワーク(dafault
)にファイアウォールルールを作成する。
この場合、default
ネットワークを利用しているすべてのリソースのうち、vpn
というタグがついたものはVPNからのすべての通信が許可されるルールが適用される。
このように、自由にstatic-ip-openvpn-server
で予約した静的IPを固定IPとして任意の環境でアクセス制限を行える。
備考
- https://github.com/angristan/openvpn-install で起動したVPNサーバはwebに繋がらなくて断念した
- ssh中のVMでLinux版のopenvpn3 clientを使うと一生VMにsshできなくなる問題にぶち当たったのでopenvpn2を使っている
- openvpn3を使いたい方はこちらを参照
おわりに
弊社Acompanyは次世代暗号技術である秘密計算やゼロ知識証明、k匿名化、差分プライバシーなどのプライバシーテックの研究開発と、それらを用いてプライバシー保護した状態でデータ分析が利用可能なデータクリーンルームの開発・提供を行っています。
絶賛採用中なので興味があれば下記採用ページ内のGoogleFormか、XのDMから連絡お願いします。
Discussion