OpenVPNサーバーの構築

Debian 10 でOpenVPNサーバーを構築する

今回はQNAPにContainer StationにあるDebian 10 (LXC)にOpenVPNサーバーを構築した。

コンテナではなく通常のDebianを使っている人はコンテナの初期設定を無視して構いません(入っていないものは入れてください)。以下全てrootで実行した場合のコードになっています。

コンテナの初期設定(入っていなものがあればインストール)

  1. コンテナ作成時、ネットワークはbridgeにしてIPアドレスを固定する。
  2. timedatectl set-timezone Asia/Tokyo」でタイムゾーンを変更し、「date」で現在時刻が正しいか確認する。
  3. passwd」でrootのパスワードを設定する。
  4. apt update」でパッケージ一覧を更新。
  5. apt -y install openssh-server」でsshサーバーをインストール。
  6. apt -y install sudo」でsudoをインストール。
  7. adduser user1」でユーザーを追加する。user1にssh用のユーザー名を入れる。パスワードを聞かれたらuser1のパスワードを入力する。
  8. gpasswd -a user1 sudo」でuser1にsudo権限を付与する
  9. systemctl restart sshd」でsshdを再起動
  10. これ以降、QTSのコンソール画面だけでなく、sshから入れる。
  11. ssh user1@192.168.***.***」でsshする。IPアドレスは1で確認したもの。
  12. sudo su」でuser1のパスワードを入力し、rootとなる。
    • sudo: unable to resolve host **** : Name or service not known」と表示される場合は「sh -c 'echo 127.0.1.1 $(hostname) >> /etc/hosts'」でhostsにホスト名を追加する。
  13. apt -y install cron」でcronをインストールし、「crontab -e」で文末に「@reboot mkdir -p /dev/net && mknod /dev/net/tun c 10 200 && chmod 600 /dev/net/tun」を追加し、起動時にtunを存在させる。
  14. apt -y install gpg wget」でgpgとwgetをインストール

OpenVPNのインストール

  1. wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg|apt-key add -」で公開GPGキーをインポート
  2. echo "deb http://build.openvpn.net/debian/openvpn/release/2.4 buster main"> /etc/apt/sources.list.d/openvpn-aptrepo.list」でレポジトリを追加(最新版を入れるため)する。2.4は自分のインストールしたいバージョンを入力、busterは自分のOSを入力する(実際に存在するかは上記URLにアクセスして確認可能)。
  3. apt update && apt install -y openvpn」でOpenVPNをインストール
  4. インストールが完了したら「openvpn --version」で正しいバージョンかを確認する。
  5. apt -y install easy-rsa iptables-persistent」で、認証ファイル生成をするEasy RSAと、iptablesの設定を恒久化するためにiptables-persistentをインストール

OpenVPNの認証鍵の作成

  • CAの構築
    1. cp -r /usr/share/easy-rsa /etc/openvpn/」でEasy RSAのディレクトリをコピー
    2. cd /etc/openvpn/easy-rsa/」で移動
    3. cp vars.example vars」でvarsのサンプルをコピー
    4. vim vars」で91~96行目あたりのコメントアウトを外して、自分の環境に合わせて編集し保存する
      • set_var EASYRSA_REQ_COUNTRY “JP”
      • set_var EASYRSA_REQ_PROVINCE “Kanagawa”
      • set_var EASYRSA_REQ_CITY “Yokohama”
      • set_var EASYRSA_REQ_ORG “QNAP”
      • set_var EASYRSA_REQ_EMAIL “admin@example.com”
      • set_var EASYRSA_REQ_OU “OpenVPN”
    5. ./easyrsa init-pki」で初期化する
      • Enter New CA Key Passphrase:」と質問されるので、パスフレーズを入力する。このパスフレーズは後ほど使うので忘れないようにする。
      • Re-Enter New CA Key Passphrase:」でもう一度パスフレーズを入力する。
    6. cp pki/ca.crt /etc/openvpn/」で生成されたCAの証明書ファイルを移動させる
  • サーバー秘密鍵・証明書の生成
    1. ./easyrsa build-server-full server nopass」でサーバーの秘密鍵と証明書ファイルを生成する。途中でパスフレーズを聞かれるので、先ほどのパスフレーズを入力する。サーバーの秘密鍵にパスワードを付けるとサービス起動時に面倒くさいので、nopassオプションにより秘密鍵はパスワード無しで生成する。
    2. cp pki/private/server.key /etc/openvpn/」で秘密鍵をコピーする。
    3. cp pki/issued/server.crt /etc/openvpn/」で証明書ファイルをコピーする。
  • DHパラメータの生成
    1. ./easyrsa gen-dh」でDHパラメータを生成する。
    2. cp pki/dh.pem /etc/openvpn/」でDHパラメータをコピーする。
  • TLS認証鍵の生成
    1. openvpn --genkey --secret ta.key」でTLS認証鍵を生成する。
    2. cp ta.key /etc/openvpn/」でTLS認証鍵をコピーする。
  • クライアント秘密鍵・証明書の生成
    1. ./easyrsa build-client-full client01 nopass」でクライアントの秘密鍵・証明書を生成する。パスフレーズを聞かれるので先ほど同様に入力する。「client01」はクライアントとなるユーザー名に置き換えること。
    2. cp pki/private/client01.key /etc/openvpn/client/」でクライアント秘密鍵をコピーする。
    3. cp pki/issued/client01.crt /etc/openvpn/client/」でクライアント証明書をコピーする。

OpenVPNサーバーの設定

  • cd /etc/openvpn」で移動
  • cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz ./」でserver.confのサンプルコードをコピーする。
  • gunzip server.conf.gz」でサンプルコードを解凍する。
  • cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ./client/client01.conf」でclient.confのサンプルコードをコピーする。
  • vim server.conf」でサーバーの設定ファイルを編集し、各自の環境に合わせて設定を変える。当方の変更箇所のみ以下に記述。
    • 85行目「dh dh.pem」ファイル名の修正
    • 192行目「push "redirect-gateway def1 bypass-dhcp"」コメントアウト(;)を外す
    • 200行目「push "dhcp-option DNS 8.8.8.8"」DNSの通知
    • 201行目「push "dhcp-option DNS 8.8.4.4"」DNSの通知
    • 222行目「duplicate-cn」で同じユーザーの複数接続を許可
    • 267行目「max-clients 10」最大接続数は10
    • 274行目「user nobody」ユーザー属性の制約なし
    • 275行目「group nogroup」グループ属性の制約なし(nobodyをnogroupに変更)
    • 287行目「status /var/log/openvpn/openvpn-status.log」ログの記録
    • 296行目「log /var/log/openvpn/openvpn.log」ログの記録
    • 297行目「log-append /var/log/openvpn/openvpn.log」ログの記録
    • 315行目「explicit-exit-notify 1」UDPの場合。TCPの場合はコメントアウト(;)すること。
    • 317行目「reneg-sec 43200」を追記し、再認証するまでの時間を指定する。当方は43200秒(12時間)とした。長すぎるとセキュリティ上好ましくないが、短すぎるとその都度接続が切れて認証が必要となるので、1回の使用時間を目安に設定する。

OpenVPNサーバーの起動

  1. systemctl start openvpn」でVPNサーバーを起動させる。
  2. systemctl status openvpn」で「active」になっていれば成功。
  3. journalctl -xe」でエラーが出ていないことを確認する。
  4. ip a」でインターフェイスに「tun0」が追加されていることを確認する。
  5. 問題がなければ正常にOpenVPNが作動している。

※QNAPで動かすと「journalctl -xe」で「systemd[1]: openvpn@server.service: Main process exited, code=killed, status=9/KILL」が出ることがある。これはQTSがOpenVPNを見つけると強制終了させることが原因と思われる。以下の手順で強制終了させないようにする。

  1. QTSにsshでログインする。(adminまたはsudo権限が必要)
  2. vim /etc/deamon_mgr.conf」でopenvpnを探し、行ごと削除する。
  3. killall daemon_mgr」で強制停止させる。
  4. /sbin/daemon_mgr」で起動させる。
  1. 「demon_mgr.conf」が見つからない場合は、GUIのQTSにadminでログインする。
  2. App CenterよりQVPNをインストールする。
  3. QVPNを開いてOpenVPNを選択する。
  4. 「OpenVPN Serverを有効にする」にチェックを入れ、ポートに空いていない適当な数値を入力し「適用」を押下する。
  5. これにより、QTSでOpenVPNが動いているため、独自にOpenVPNを動かしてもkillされなくなる。

その他設定

  • パケット転送の有効化
    1. vim /etc/sysctl.conf」で28行目の「net.ipv4.ip_forward=1」のコメントアウトを外して保存する。
    2. sysctl -p」で設定を反映させる。
  • IPマスカレードの設定
    1. iptables-legacy -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE」でIPマスカレードの設定をする。eth0は「ip a」でVPNサーバーのIPアドレスが割り振られていたインタフェース名を入力する。
    2. iptables-legacy-save > /etc/iptables/rules.v4」で設定を恒久的に保存する
    3. update-alternatives --config iptables」でデフォルトを変更し、「iptables-legacy」の番号を入力する。
  • ここまでできたらrebootし、「iptables -L -t nat」で再行動しても設定が残っているか確認する。
  • systemctl status openvpn」でOpenVPNも正常に作動しているか確認する。

クライアント用ファイルの設定

  • cd /etc/openvpn」で移動し、「vim client/client01.conf」でクライアントの設定ファイルを編集し、各自の環境に合わせて設定を変える。当方の変更箇所のみ以下に記述。
    • 42行目「remote my-server 1194」my-serverをVPNサーバのIPアドレスにする。外から入る場合はグローバルIPアドレスを設定する。その場合、ルータのポートフォワーディング(方法は各自で確認)で1194を開放し、VPNサーバのIPアドレスに転送する。(固定のグローバルIPアドレスがない場合はDDNSを設定する)
    • 61行目「user nobody」ユーザー属性の制約なし
    • 62行目「group nogroup」グループ属性の制約なし(nobodyをnogroupに変更)
    • 129行目「reneg-sec 0」を追記し、再認証するまでの時間を無効(0)にする。サーバーとクライアントで設定できるが、短い方の時間で再認証されるため、今回はクライアントでの指定を無効としサーバーの時間で再認証する。特定のクライアントにサーバーより短い時間を設定したい場合は0を消して秒数を指定する。
  • cp client/client01.conf client/client01.ovpn」でovpnファイルを作成する。
  • vim client/client01.ovpn」でovpnファイルを編集する。
  • ca ca.crt」「cert client.crt」「key client.key」の3行を削除し、以下のように書き換える。「:vnew ca.crt」など並行で開きながらコピペすると作業しやすい。
<ca>
-----BEGIN CERTIFICATE-----
	・・・ ca.crt の CERTIFICATE の中身 ・・・
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
	・・・ client/client.crt の CERTIFICATE の中身 ・・・
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
	・・・ client/client.key の PRIVATE KEY の中身 ・・・
-----END PRIVATE KEY-----
</key>
  • 「tls-auth ta.key 1」の行を削除し、以下のように書き換えて保存する。
key-direction 1
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
	・・・ ta.key の OpenVPN Static key V1 の中身 ・・・
-----END OpenVPN Static key V1-----
</tls-auth>

クライアント(GUI)から接続する

  1. scp /etc/openvpn/client/client01.ovpn user@192.168.***.***:Downloads/」で先ほど作成したovpnファイルをクライアントPCに転送する。userは受け取るPCのユーザー名、192.168.***.***は受け取るPCのIPアドレスを指定する。Downlodsは例なので、好きなフォルダを指定する。
  2. こちらのOpenVPN公式サイトから一番上の「OpenVPN Connect」を自分の使用環境(OS)に合わせてダウンロードする。
  3. ダウンロードしたものをインストールする。
  4. 先ほど転送した「client.ovpn」をOpenVPN Connectのアプリにドラッグ&ドロップ、またはダブルクリックしてアプリに読み込ませる。
  5. addを押下するとプロファイルが追加される。
  6. ボタンを押下して接続できるか確認する。

PAM認証によるID/パスワード認証の設定

ここまでは鍵認証方式によるOpenVPN接続について設定したが、セキュリティを強化するためにID/パスワード認証を追加で導入する。

  • ファイルの場所を確認
    1. find / | grep openvpn-plugin-auth-pam」で「openvpn-plugin-auth-pam」の場所を確認する。当方は「/usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so」であった。
    2. /etc/pam.d/login」が存在するか確認する。
  • VPNサーバーの設定
    1. vim /etc/openvpn/server.conf」でサーバの設定ファイルを開く。
    2. plugin /usr/lib/x86_64-linux-gnu/openvpn/plugins/openvpn-plugin-auth-pam.so login」を文末に追記する。ディレクトリは先ほど確認した場所を指定する。
    3. systemctl restart openvpn」でVPNサーバーを再起動させる。
  • クライアントファイルの修正「vim /etc/openvpn/client/client01.ovpn」でクライアントファイルを開く。
    1. auth-user-pass」を文末に追記する。これにより、ID/パスワードを入力できようになる。
    2. 「client.ovpn」をクライアントPCに移動させる。
    3. ファイルをインポートし、IDとパスワードを入力する。
    4. ボタンを押下して接続できるか確認する。rootではログインできないため、管理権限のないユーザーで認証すること。

Google Authenticatorを用いた認証

セキュリティをさらに強化するために、鍵認証方式+パスワード認証方式+OTPの3つを合わせた強固な認証を行う。そのためにGoogle Authenticatorを用いた認証を導入する。

  • Google認証システムの導入
    1. apt install -y libpam-google-authenticator」でGoogle Auth PAMモジュールをインストールする。
    2. addgroup gauth」でgauthグループを作成する。
    3. useradd -g gauth gauth」でgauthグループに属するgauthというユーザーを作成する。
    4. mkdir /etc/openvpn/google-authenticator」でGoogle Auth用のディレクトリを作成する。
    5. chown gauth:gauth /etc/openvpn/google-authenticator」でgauthにディレクトリの所有者を変更する。
    6. chmod 0700 /etc/openvpn/google-authenticator」でgauthにのみ権限を与える。
  • シークレットキーの生成
    1. su -c "google-authenticator -t -d -r3 -R30 -f -l \"My VPN\" -s /etc/openvpn/google-authenticator/client01" - gauth」でGoogle Authトークンを作成する。「client01」はVPNでログインするクライアントのユーザー名に変えること。
    2. QRコードの下にある「Your new secret key is: #####」の右側の#####のシークレットキーをコピーする。
    3. 「Do you want to do so? (y/n)」と質問されたら「n」とする。
    4. apt install -y qrencode」でQRコードを出力するためのツールをインストール。
    5. qrencode -o QR.png otpauth://totp/label?secret=#####」#####に先ほどのシークレットキーを貼り付ける。
    6. scp QR.png user@192.168.***.***:Downloads/」でクライアントPCにQRコードを転送する。
    7. スマホにインストールしたGoogle Authenticatorアプリに転送されたQRコードを読み込ませる。
    8. 転送後はセキュリティの観点から、「rm QR.png」でVPNサーバーからQRコードは削除したほうが良い。
  • PAMの設定
    • vim /etc/pam.d/openvpn」でPAMの設定ファイルを開く。
    • auth required pam_google_authenticator.so authtok_prompt=pin secret=/etc/openvpn/google-authenticator/${USER} user=gauth」を追記して保存する。
  • VPNサーバーの設定
    1. vim /etc/openvpn/server.conf」でサーバー設定ファイルを開く。
    2. ID/パスワード認証で最終行に追記した「plugin」の文末にある「login」を「"openvpn login USERNAME password PASSWORD pin OTP"」に書き換える。
    3. 317行目「reneg-sec 43200」の再認証までの時間が問題ないか確認する。短すぎると再認証の度にGoogle Authのコード入力が必要となるので注意すること。
    4. systemctl restart openvpn」でVPNサーバーを再起動させる。
  • クライアントファイルの設定
    1. vim /etc/openvpn/client/client01.ovpn」でクライアントファイルを開く
    2. static-challenge "Enter Google Authenticator Code:" 1」を文末に追記する。
    3. 「client.ovpn」をクライアントPCに移動させる。
    4. ファイルをインポートし、IDとパスワードを入力する。
    5. 接続ボタンを押下すとコードを聞かれるので、Google Authenticatorアプリに表示されている6桁の数字を入力し、接続できるか確認する。

まとめ

以上の設定でOpenVPNサーバーを構築することができる。

鍵認証方式+パスワード認証方式+OTPの3つを合わせた認証により、外向きにポートを空けても安全性をある程度確保することができるようになった。