背景
最近VPNを構築する機会があり、クライアント用のovpnファイルをたくさん作成するのが面倒だったのでファイル作成をなるべく自動化できるようにシェルスクリプトを作ることにした。
前提
- OpenVPNインストール済み
- easy-rsaをopenvpnフォルダ以下にダウンロード済み
システム構成
最終的なシステム構成は上記の図のとおり。openvpnフォルダはopenvpnインストール時に、easy-rsaフォルダ、easyrsa3フォルダおよびpki以下のフォルダはeasy-rsaインストール時に作成される。easy-rsaのコマンドはeasyrsa3フォルダ上で実行する必要があるので、今回実行するシェルスクリプトもeasyrsa3フォルダに作成する。
プログラム
概要
mkovpn.shとしてeasyrsa3ディレクトリに置かれている。
# サーバ証明書のパス
ca_path="/etc/openvpn/easy-rsa/easyrsa3/pki"
# クライアント用秘密鍵のパス
key_path="/etc/openvpn/easy-rsa/easyrsa3/pki/private"
# クライアント用証明書のパス
crt_path="/etc/openvpn/easy-rsa/easyrsa3/pki/issued"
# tls-auth用の静的鍵のパス
ta_path="/etc/openvpn/easy-rsa/easyrsa3/pki/"
# 引数チェック
if [ $# -ne 1 ]; then
echo "コマンド実行には対象のユーザを引数にする必要があります。" 1>&2
exit 1
fi
# 対象のクライアント
username=$1
# クライアント用の鍵作成
./easyrsa build-client-full $username nopass
# 作成開始
cat ovpn_header >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
<ca>
EOL
grep -A 30 'BEGIN CERTIFICATE' "$ca_path/ca.crt" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</ca>
<cert>
EOL
grep -A 30 'BEGIN CERTIFICATE' "$crt_path/$username.crt" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</cert>
<key>
EOL
cat "$key_path/$username.key" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</key>
<tls-auth>
EOL
cat "$ta_path/ta.key" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</tls-auth>
EOL
./mkovpn.sh username
でコマンドが実行できる。usernameには使用するクライアントの名前などを指定するとよいと思う。
実行後、ovpn_filesディレクトリ以下にusername.ovpnが作成されるようになっている(ovpn_filesディレクトリは前もって作成しておく)。
必要なファイルの読み込み
# サーバ証明書のパス
ca_path="/etc/openvpn/easy-rsa/easyrsa3/pki"
# クライアント用秘密鍵のパス
key_path="/etc/openvpn/easy-rsa/easyrsa3/pki/private"
# クライアント用証明書のパス
crt_path="/etc/openvpn/easy-rsa/easyrsa3/pki/issued"
# tls-auth用の静的鍵のパス
ta_path="/etc/openvpn/easy-rsa/easyrsa3/pki/"
ovpnファイルの作成に必要な鍵の場所を指定している。鍵の作成方法などについてはここでは割愛する。
引数チェック
# 引数チェック
if [ $# -ne 1 ]; then
echo "コマンド実行には対象のユーザを引数にする必要があります。" 1>&2
exit 1
fi
コマンド実行時に引数が指定されているかを確認する。
クライアント証明書と鍵の作成
# 対象のクライアント
username=$1
# クライアント用の鍵作成
./easyrsa build-client-full $username nopass
easy-rsaのbuild-client-fullをシェルスクリプト内で実行し、username.crtおよびusername.keyを作成する。証明書はpki/issued、秘密鍵はpki/private以下に保存される。
秘密鍵にパスワードを設定したい場合はnopassを削除しておくとよい。
ovpnファイルの作成
# 作成開始
cat ovpn_header >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
<ca>
EOL
grep -A 30 'BEGIN CERTIFICATE' "$ca_path/ca.crt" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</ca>
<cert>
EOL
grep -A 30 'BEGIN CERTIFICATE' "$crt_path/$username.crt" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</cert>
<key>
EOL
cat "$key_path/$username.key" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</key>
<tls-auth>
EOL
cat "$ta_path/ta.key" >> ovpn_files/$username.ovpn
cat <<EOL >> ovpn_files/$username.ovpn
</tls-auth>
EOL
全てのovpnファイルに共通する部分となるovpn_headerをあらかじめ作成しておき、$username.ovpnに書き込む。以下は例。
client
proto tcp-client
remote $domain $port
dev tun
resolv-retry infinite
nobind
auth-nocache
persist-key
persist-tun
remote-cert-tls server
tls-client
tls-version-min 1.2
key-direction 1
verb 3
tun-mtu 1500
cat <<EOL >> ovpn_files/$username.ovpn
を用いて次のEOL
まで$username.ovpn
に書き込みを続けることで自動的にovpnファイルを作成する。またgrep -A 30 'BEGIN CERTIFICATE' "$crt_path/$username.crt"
についてはmkovpn.sh実行時に作成した$username.crt
から'BEGIN CERTIFICATE'を探してそれ以下30行を抽出し、$username.ovpn
に書き込んでいる。$username.key
、ta.key
についても同様である。
まとめ
OpenVPNを作動させるための最低限の準備が整っていれば、名前を指定するだけでクライアント用のファイルがすぐに作れるので便利だと思う(自画自賛)。セットアップではできるだけ楽をしたい...
参考
こちらを改造させていただきました。ありがとうございました。