IBM Cloud のプライベートクラウド環境内にアクセスするための(サーバーインスタンス代以外は不要という意味で)安価な VPN サーバーを構築する、という機会があったので、その手順をまとめておきます。先に書いておくと、構築する際に手を動かす部分だけはさほど大変ではないのですが、事前準備というか、環境確認というか、構築用途を考慮した上で準備する部分がそこそこのボリュームを占めています。



【システム図】
今回紹介するシステム環境はこのようなものです:
2020100201

IBM Cloud 内にプライベート VLAN を1つ用意して、プライベートクラウド環境内に業務環境を構築します。このプライベートクラウドにアクセスするための VPN サーバー(上図の赤箱)を専用のサーバーインスタンスを1つ追加して構築する、というものです。

今回、このサーバーを CentOS 8.x をベースに、OpenVPN サーバーを使って構築します。OSS をベースとすることで、OS もソフトもサービスも追加料金不要です。


この作業を行う前に、環境についていくつか事前に決めておく必要があります。順を追って紹介します。


【セキュリティグループの定義】

セキュリティグループは IBM Cloud 内のセキュリティ設定を担う機能です。今回構築する VPN サーバーではどのようなセキュリティ設定で構築する必要があるかを事前に考え、定義し、この後作成する VPN サーバーに適用します。

※今回の記事の中で IBM Cloud に特化している部分でもあります。このセキュリティグループや内部ネットワークの確認方法に関わる箇所以外の内容は他のインフラ環境でもほぼ流用できると思っています。

IBM Cloud のセキュリティグループ定義内容を確認するには、まず左上のメニューから Classic Infrastructure を選択してインフラ一覧ページに移動します:
2020100202


そして同ページから更にメニューを Security - Network Security - Security Groups とたどった先にあります:
2020100203


デフォルトで定義済みのものも含めて、セキュリティグループの一覧が表示されます。新規セキュリティグループを追加する場合は画面右上の Create group を選択します:
2020100204


新規作成時のダイアログです。ここではセキュリティグループの Name(必須)と、必要に応じて Description(説明、任意)を入力します。なお Create group with .. と書かれたチェックは外して、空の定義状態で作成します:
2020100205


作成後の一覧です。入力した名前のセキュリティグループが登録されていることを確認します:
2020100206


一覧から1つ選択すると定義内容が表示されます。作成直後は定義内容が空の状態です。ここで Inbound(リクエスト受付)/Outbound(リクエスト送付) にわけてセキュリティ内容を定義します:
2020100207


例えば HTTP(=TCP/80) を通す設定を加えたい場合、Inbound ルールを以下の内容で追加します。特定のネットワークアドレスからのリクエストのみ受け付ける条件を加えることも可能です(無指定の場合はすべてのネットワークアドレスからのリクエストに適用されます):
2020100208


この作業を繰り返して、Inbound ルールと Outbound ルールを加えてゆきます。なお実際のサーバーインスタンスにはここで作成したルールを複数組み合わせて割り当てることができるので、1つのセキュリティグループにすべての設定内容を記述する必要はありません:
2020100201


更に、別のセキュリティグループで SSH を通すセキュリティ設定を用意しました。こちらは Source を定義することで、特定の IP アドレス(自分の IP アドレス)からのリクエストのみ許可するような内容にしており、環境構築後のこちらのセキュリティグループのみ除去する予定です:
2020100202


一覧ではこのように2つのセキュリティグループを追加しました:
2020100203


【プライベート VLAN ネットワーク環境の確認】

次に、この後 VPN サーバーをインストール&設定する際の、設定内容を現在のプライベート VLAN 内容から確認します。

まず対象サーバーインスタンスを1つ確認します。IBM Cloud ダッシュボードから Classic Infrastructure - Device List を選択します:
2020100204


(止まっているものも含めた)定義済みのサーバー一覧が表示されます。ここから今回 VPN で接続することになるプライベート VLAN 内のサーバーを1つ選択します:
2020100205


選択したサーバーインスタンスの詳細画面が表示されます。ここで以下の内容を確認しておきます(後の作業で使います):
2020100206


確認する項目この図での値
LocationTokyo 5
Private ネットワークの VLANtok05.bcr01a.2256
Private ネットワークの IP Address10.193.122.107/26


この IP アドレスの値より、同ネットワークのネットワークアドレスおよびネットマスクを計算すると、
 ネットワークアドレス : 10.193.122.64
 ネットマスク : 255.255.255.192
ということがわかります。


サーバー構築前に調べておく内容は以上です。この後は実際のサーバー構築に移ります。


【CentOS 8 インスタンス作成】

では実際に VPN サーバーを構築していきます。まずは IBM Cloud の同プライベート VLAN 内に CentOS 8.x の VM を追加します。

IBM Cloud ダッシュボードのデバイス一覧画面から Order ボタンを選択します:
2020100207


追加内容はいわゆる VM です。IBM Cloud では Virtual Server for Classic と分類されているので、これを直接検索するか、または検索窓に "classic" などと入力して検索し、Virtual Server for Classic を選択します:
2020100208


次の画面で作成する VM のスペックを決めていきます。名前に加えて CPU やらメモリやら。ここで注意すべきは作成するインスタンスの Location 、先程調べた VPN 接続対象プライベート VLAN(上記例では Tokyo 5)と同じものを選択してください:
2020100301


また OS イメージは CentOS 8.x を、そしてパブリックネットワークのセキュリティグループには上で作ったセキュリティグループ2つを指定して、自端末からの SSH 接続ができるようにします。最後に画面右の Create を選択します:
2020100302


指定した CentOS サーバーがデプロイされて稼働状態になるまで少し待ちます。

この後、この稼働したインスタンスにアクセスして作業するため、その接続のためのネットワーク情報を確認する必要があります。作成したインスタンスを選択します:
2020100304


まず選択直後は Overview ペインが選択され、概要が表示されています。この画面でパブリックネットワークに割り振られた IP アドレスを確認します(この直後の SSH ログイン時に指定します):
2020100305


また Passwords ペインを選択し、ログイン時のユーザー ID およびパスワードを確認しておきます。パスワードはマスクされていますが、目のアイコンを選択するとマスクが外れた状態で視認できるようになります:
2020100306


【CentOS 8 インスタンスへの OpenVPN サーバーのインストール&設定】

では作成した CentOS 8 インスタンスに SSH でログインし、OpenVPN サーバーとしてのセットアップを行っていきます。

まずは Teraterm や PuTTy、WSL などの SSH クライアントを使って、作成した CentOS 8 サーバーにログインします。先程確認した IP アドレス、ユーザー ID 、パスワードを使います:
2020100307


この後はしばらくこの SSH 端末からの入力作業が続きます。

まず最初に、この後 OpenVPN サーバーを EPEL リポジトリを使ってインストールすることになるため、EPEL リポジトリをインストールしておきます:
# dnf install -y epel-release

続けて OpenVPN サーバーや証明書作成に必要なツールなどをまとめてイントールします:
# dnf --enablerepo=epel -y install openvpn easy-rsa net-tools

ここまでの作業で OpenVPN サーバーそのものがインストールできました。続けて証明書ファイルを作成してゆきます(青字はコメントです):
(フォルダを移動)
# cd /usr/share/easy-rsa/3

(easyrsa 初期化)
# ./easyrsa init-pki

(認証局を作成)
# ./easyrsa build-ca

 この時にパスフレーズの入力を求められるので適当なフレーズを2回続けて入力。
 ここで入力したフレーズは下で再度入力する必要があります。


(サーバー証明書を作成) # ./easyrsa build-server-full server1 nopass
 途中でパスフレーズの入力を求められたら、上記で指定したフレーズを入力

(クライアント証明書を作成) # ./easyrsa build-client-full client1 nopass
 途中でパスフレーズの入力を求められたら、上記で指定したフレーズを入力

(DH を生成) # ./easyrsa gen-dh (TLS-Auth キーを生成) # openvpn --genkey --secret ./pki/ta.key (ここまでの作業で作成したファイル群をまとめて /etc/openvpn/server/ 以下にコピー) # cp -pR /usr/share/easy-rsa/3/pki/{issued,private,ca.crt,dh.pem,ta.key} /etc/openvpn/server/ (IP フォワードの設定のため、このファイルを新規作成) # vi /etc/sysctl.d/10-ipv4_forward.conf  (ファイル内容はこの1行だけ)  net.ipv4.ip_forward = 1 (IP フォワード有効化) # sysctl --system (サーバー設定ファイルのサンプルをコピー) # cp /usr/share/doc/openvpn/sample/sample-config-files/server.conf /etc/openvpn/server/ (サーバー設定ファイルを実際の環境に合わせて書き換え、変更内容は以下) # vi /etc/openvpn/server/server.conf  (78行目 コピーした証明書ファイル名を指定)  ca ca.crt  cert issued/server1.crt  key private/server1.key  (85行目 コピーした DH ファイル名を指定)  dh dh.pem    (101行目 VPN で使用する IP レンジを指定、ユーザーの環境と重複しないもの)  server 192.168.123.0 255.255.255.0  (142行目 コメントを解除して、上で確認したプライベート VLAN のネットワークを指定)  push "route 10.193.122.64 255.255.255.192"  (222行目 コメントを解除)  duplicate-cn  (267行目 コメントを解除して値を 32 (クライアント上限数)に変更)  max-clients 32  (287行目 ログファイルの保管場所をフルパス指定)  status /var/log/openvpn-status.log  (296行目 コメントを解除してログファイルの保管場所をフルパス指定)  log /var/log/openvpn.log  log-append /var/log/openvpn.log (変更内容を有効にして再起動) # systemctl enable --now openvpn-server@server
(プライベート VLAN とパブリック LAN のルーティング設定)
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT # iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT


※最後のルーティング設定部分はこのコマンドで実行した場合は再起動時に無効になってしまいます。恒久的に有効にする場合は /etc/rc.d.rc.local などに書いておく、などの対応が必要です。


これで対象プライベート VLAN に接続するための OpenVPN サーバーができあがりました。SSH はログアウトして構いません。


【OpenVPN クライアントのインストール&設定】

VPN サーバー側が用意できたので、残すは VPN クライアント側だけです。以下は Windows 10 を想定した内容で紹介します。

まだ OpenVPN クライアントをインストールしていない場合は以下からダウンロードしてインストールします:
https://openvpn.net/community-downloads/


導入先フォルダ(デフォルトだと C:\Program Files\OpenVPN)内の config サブフォルダ内に、VPN サーバーから以下の4ファイルを転送します(書き込み時に Administrator 権限が必要です):
  • /etc/openvpn/server/ca.crt
  • /etc/openvpn/server/ta.key
  • /etc/openvpn/server/issued/client1.ca
  • /etc/openvpn/server/private/client1.key

更に、導入先フォルダ内の sample-config サブフォルダ内にある client.opvn ファイルを、config サブフォルダ内にコピーします(書き込み時に Administrator 権限が必要です)。上記と合わせて都合5つのファイルを config フォルダにコピーすることになります。

そして、この client.opvn ファイルをテキストエディタで開き、以下を編集して保存します(保存時に Administrator 権限が必要です):
(42行目 OpenVPN サーバーのパブリック IP アドレスを指定)
remote 165.192.xxx.xxx

(88行目 コピーした各種証明書ファイル名を指定)
ca ca.crt
cert client.crt
key client.key

これでサーバーとクライアント、全ての準備が整いました。

なお、このクライアント向け作業で用意した5つのファイルは(後述の動作確認後に)他のユーザーからも利用できるようになります。サーバーからのファイル転送や client.opvn ファイルの編集といった面倒な作業をユーザー全員にさせる必要はなく、ここで動作が確認できていれば同じファイルを流用することができます。


【動作確認】

実際に OpenVPN サーバーにアクセスして VPN 接続します。Windows の場合であればタスクバーから OpenVPN クライアントを右クリックして client に接続します(アイコンが緑になったら VPN 接続成功です):
2020100308


VPN 接続ができたら、プライベートアドレスを指定してプライベート VLAN 内のサーバーにアクセスできるようになっているはずです。ウェブブラウザやリモートデスクトップ接続といったサービスをプライベートアクセスで使ってみてください:
2020100309

2020100309