AWS ClientVPN作成手順(プライベートホストゾーン)
上記のAWS ClientVPN関連の部分(ClientVPN Endpoint , ClientVPN ENI)がまだ作られていない状態で、東京リージョンで上記の様なCDPだと仮定します。CDPはWEBサーバーのサブネットがパブリックサブネットで非セキュアなので、ご注意ください(ClientVPNの意味がない!と言われそうですが、適宜、ルートテーブルをパブリック用からプライベート用に変えてください)。さらにネットワークACLについてもデフォルトで、CISベンチマーク、PCI DSS、AWSセキュリティベストプラクティスの対応前という前提です。あらかじめご了承ください。WEBサーバーのEC2インスタンスには、Route53パブリックホストゾーン経由で常時ブラウザで見られるhttps://hogehoge.comと、ClientVPN接続時しかブラウザ表示できないRoute53プライベートホストゾーンhttps://admin.hogehoge.comの2つをapache2.4で動かしています。この記事ではapache2.4のバーチャルホスト設定は記載しません。
AWS ClientVPNは以下の3種類のクライアント認証がありますが、この記事は相互認証(証明書ベース)で行う手順です。
- Active Directory 認証 (ユーザーベース)
- 相互認証 (証明書ベース)
- シングルサインオン (SAML ベースのフェデレーション認証) (ユーザーベース)
CDPのポイント
Route53は、パブリックホストゾーン https://hogehoge.com で、SSL証明書をACMでアスタリスク証明書として取得。さらに、Route53のプライベートホストゾーンでhttps://admin.hogehoge.comを作っています。hogehoge.comについて、Route53でホストゾーンが2つであることに注意してください。
ELBも、https://admin.hogehoge.com用にinternal(VPNで使う内部向けロードバランサ)とhttps://hogehoge.com用にinternet-facingで2台必要です。ELBのAZは1a 1c 1dの3か所についてVPN専用のプライベートサブネットと通常のWEBアクセス用にパブリックサブネットとしてサブネット合計6つです。https://admin.hogehoge.comのSSL証明書は、https://hogehoge.com のアスタリスク証明書を使えばAWSのお高い(月4万だったかな?)プライベート証明書を買う必要はありません。
ELBのターゲットグループは、internal ELBとinternet-facing ELBともに同じapache2.4のWEBサーバーEC2インスタンスとしています。
ClientVPNのENIはウェブサーバのサブネットにくっつけると考えます。
作成順番
- 認証機関/クライアント証明書/サーバー証明書を何で発行するか決めてください。今回は、発行専用のためだけにEC2インスタンスAmazonLinux2をWEBサーバとは別に1つ起動しました。手元のWindowsやMacbookで作成してaws-cliでACMにアップロードすることも可能です。
- 証明書専用のEC2インスタンスからACMへ証明書アップロードするためのIAMロールを作る
- 2で作ったIAMロールを証明書発行専用のEC2インスタンスにアタッチ
- 証明書発行専用のEC2インスタンスにgitをインストール
- 証明書発行専用のEC2インスタンスにてeasyrsa3をgit clone/インストール、認証機関を作り、サーバー証明書とクライアント証明書を発行。
- aws-cliのコンフィグを証明書発行専用のEC2インスタンスで設定し、証明書発行専用のEC2インスタンスでaws-cliを使えるようにする
- 発行した証明書をaws-cliでACMにアップロード
- ClientVPNのログを残すためにCloudWatchロググループとログストリームを作る
- AWSでClient VPN設定(AWSのDNSサーバーも設定する)。ovpnファイルを手元のPCにダウンロード
- OpenVPNを手元のPCにインストールして、ovpnファイルを読み込んで接続開始。AWS Client VPN downloadはトラブルが起きたので使うの辞めました。VPN専用のhttps://admin.hogehoge.comのWEBページをブラウザで見られたら完成。ブラウザのタブで同時に他のウェブサイトも普通に見られます。VPN接続による他のWEB閲覧の排他無しでいけます。
手元のWindows10やMacbookでAWS CLIでeasyrsa3を使って証明書を発行することも出来ますが、その場合、AWS CLIでAWSと接続するためにはアクセスキーを使うことになります。CISベンチマークでもアクセスキーはなるべく使わないことが推奨されているため、IAMでアクセス権を管理できる様に証明書発行専用のEC2インスタンスを使っています。
EC2からACMへ証明書アップロードをするためのIAMロールを作る
フルアクセスじゃないほうがいいですが・・・。
- IAMロールへ進み、ロールの作成へ
- ロールを割り当てるサービスでEC2を選び次へ
- ポリシーは、AWSCertificateManagerFullAccess(検索でCertificateで出てくる)を選び次へ
- タグは 例えば、iam-role-ec2-acm-fullaccess とした。次へ
- ロール名 ec2-acm-fullaccess-role ロールの説明も同じく ec2-acm-fullaccess-role 次へ
- ロールの作成 をクリック
※EC2インスタンスのIAMロール名はプロジェクトの命名ルールなど、お好きなように名前を付けられます。複数の異なるIAMポリシーをアタッチすることがほとんどなので、単体IAMポリシーの命名をIAMロール名にそのまま影響させないことが正解です。
IAMロール(ec2-acm-fullaccess)をEC2にアタッチ
- EC2ダッシュボードのインスタンスへ
- 該当のEC2インスタンスを選ぶ
- アクション「インスタンスの設定」
- IAMロールの割り当て/置換
- ロール名 ec2-acm-fullaccess を選ぶ
- 適用
AWS CLIコンフィグ設定
EC2インスタンスにSSH接続して以下のコマンドを実行
aws configure
AWS Access Key ID 、AWS Sercret Access Key は両方ともに未入力でEnter、Default reigion nameに東京リージョンとして以下を入力してEnter
ap-northeast-1
Default oputput format は
json
を入力してEnterでOK。
AWS CLIコンフィグの中身の確認方法
以下のコマンドで確認できる
cat ~/.aws/config
AWS CLIバージョン確認
aws --version
証明書発行専用のEC2インスタンスにgitインストール、easyrsa3インストール、証明書作成
AWS本家ドキュメント、認証 – AWS Client VPN の「相互認証」のLinux/macOSの手順でサーバー証明書/クライアント証明書を作成し、各種証明書をACMにアップロードしていきます。
gitインストール
sudo yum update
sudo yum install git
git version
OpenVPN easy-rsa リポジトリのクローンを以下のコマンドでEC2インスタンスにクローン
git clone https://github.com/OpenVPN/easy-rsa.git
移動
cd easy-rsa/easyrsa3
PKI環境を初期化
./easyrsa init-pki
認証機関(CA)構築
./easyrsa build-ca nopass
サーバー証明書とキーを生成(serverの部分は任意で命名できます)
./easyrsa build-server-full server nopass
クライアント証明書とキーを生成。以下コマンドでclient1.domain.tldの部分が名称となるのでプロジェクトの命名ルール等に従って変えることを推奨します。
./easyrsa build-client-full client1.domain.tld nopass
証明書をまとめて置くデイレクトリを作る
mkdir ~/cert/
ca証明書をコピー
cp pki/ca.crt ~/cert/
サーバー証明書をコピー
cp pki/issued/server.crt ~/cert/
サーバーキーをコピー
cp pki/private/server.key ~/cert/
クライアント証明書をコピー
cp pki/issued/client1.domain.tld.crt ~/cert/
クライアントキーをコピー
cp pki/private/client1.domain.tld.key ~/cert/
移動
cd ~/cert/
ACMへ証明書アップロード
証明書をACMにアップロードすると、ACMに証明書作成日時のタイムスタンプもアップロードされます。そのため、事前にEC2のタイムゾーンをAsia/Tokyoにしておくとわかりやすくていいです。AmazonLinux2を最初に構築した際にタイムゾーン設定をするようにするべきですね。
証明書アップロード先は、S3ではなくACMとなります。
※アップロードコマンドは、以下の様にリージョンを指定してください(以下は東京)。EC2のセキュリティグループのhttp/https(おそらくhttps)のアウトバウンドを空けておかないと上記のコマンド実行してACMにアップロードきませんのでご注意ください。
サーバー証明書とキーをACMへアップ
aws acm import-certificate --certificate file://server.crt --private-key file://server.key --certificate-chain file://ca.crt --region ap-northeast-1
EC2でACMに証明書をアップロードするコマンド実行後、コンソール画面で以下の赤い部分あたりの様に各証明書のARNが表示されます。実際にAWSのACM画面で同じ証明書がアップロードされていることをARNで確認してください。
クライアント証明書とキーを ACM にアップ
aws acm import-certificate --certificate fileb://client1.domain.tld.crt --private-key fileb://client1.domain.tld.key --certificate-chain fileb://ca.crt --region ap-northeast-1
VPCダッシュボードでクライアントVPNエンドポイントの作成
AWS本家ドキュメントは、クライアントVPNの開始方法 です。かなり翻訳に違和感を感じますので、何が言いたいのか予測しながらゆっくりドキュメントを読んだほうがいいです。
ClientVPNの接続ログを取る場合、事前にCloudWatchLogsで専用のロググループを作っておきます。ロググループの暗号化は、東京リージョンの場合、KMSカスタマー管理型キーも作っておき、そのキーポリシーのprncipalに”Service”: “logs.ap-northeast-1.amazonaws.com”を追加しておきます。ロググループ作成後に既存ロググループを暗号化する場合、AWS CLIじゃないと出来ないので、くれぐれもご注意ください。
- VPCへ
- クライアントVPNエンドポイントへ
- クライアントVPNエンドポイントの作成へ
- 名前タグと説明に同じ文章を入力 EX)プロジェクト名-client-vpn-endpoint
- クライアントIPv4 CIDRにVPCに適したCIDR値を「サブネットマスク255.240.0.0の/12」から「サブネットマスク255.255.252.0の/22」の範囲で入力 EX)10.0.60.0/22
- 認証情報のサーバー証明書ARNで、aws acm import-certificate にてACMにアップロードしたサーバー証明書を選択
- 「相互認証の使用」にチェックを入れる
- クライアント証明書ARNで aws acm import-certificate にてACMにアップロードしたクライアント証明書を選択
- 「クライアント接続の詳細を記録しますか?」 で専用のCloudWatchロググループを既に作っている人は、「はい」をえらんでロググループを選んでください。
- 「その他のオプションパラメータ」にて「DNS サーバー 1 IP アドレス」にVPCのDNSサーバーを入力 EX)10.0.0.2
- 「クライアントVPNエンドポイントの作成」をクリック
VPCのDNSサーバーについては、AWS VPCの予約IP領域の決まりごとでVPC IPv4 CIDRアドレスの ×××.×××.×××.2 が自動的にDNSサーバーになるという決まりがあります。
Client Connect Handler を使い、クライアントVPNエンドポイントでLambdaを使い、固定IP制限なども出来ます。ClientVPN作成後に変更する事も出来ます。ですが、developes.ioのpython3のやり方だと上手く出来ませんでした。
ClientVPNエンドポイントセキュリティについて
デフォルトセキュリティグループを他のEC2インスタンスやRDSやELBなどに使っていない場合に限り、ClientVPNエンドポイント作成ではセキュリティグループ選択を意識せず、自動的にdefaultが選択されるようにします。そして、ClientVPNに適用されたデフォルトセキュリティグループのインバウンドの通信はすべて設定無しのままにしてください。それでもClientVPNは接続できます。エンドポイントセキュリティをしっかりいしきしてください。
クライアント VPN エンドポイントの各種設定
クライアント VPN の開始方法 ステップ 3: クライアントの VPN 接続を有効にする
から
ステップ 5: (オプション) 追加のネットワークへのアクセスを有効にする
を行います
ですが、この部分のAWS本家ドキュメント翻訳がわかりにくいです。手順は以下となります。
- VPC
- クライアントVPNエンドポイントへ
- 「プロジェクト名-client-vpn-endpoint」にチェック
- タブで「関連付け」にすすむ
- 「関連付け」をクリック
- VPCは該当するVPCを選ぶ
- 関連するサブネットの選択で、WEBサーバのEC2のサブネットを選ぶ。この手順では踏み台サーバー無しです。
上記CDPのClientVPN ENIとしてネットワークインターフェイスをサブネットに関連付けていることになります。 - 「関連付け」をクリック
- 次にタブで、「認証」へ
- 「受信の承認」をクリック
- 「アクセスを有効にする送信先ネット」へ「VPC の IPv4 CIDR ブロックを指定」します
EX) 10.0.0.0/16 など - 「認証ルールの追加」をクリック
- 次にタブで「ルートテーブル」へ
- 「ルートの作成」をクリック
- 「ルート送信先」は、0.0.0.0/0 とする
- 「ターゲット VPC サブネット ID」は、WEBサーバのEC2のサブネットを選ぶ
- 「ルートの作成」をクリック
- 次にタブで、再び「認証」へ
- 「受信の承認」をクリック
- 「アクセスを有効にする送信先ネット」へ「0.0.0.0/0」を入力
- 「認証ルールの追加」をクリック
クライアント設定のダウンロードとovpnファイル編集
- VPC
- クライアントVPNエンドポイント
- 「プロジェクト名-client-vpn-endpoint」にチェック、「クライアント設定のダウンロード」をクリック
- ダウンロードしたovpnファイルをVSCなどのエディタで開く
- 4行目 cvpn-endpoint を asdf.cvpn-endpoint に変える
- 35行目</ca>のあとに<cert>Contents of client certificate (.crt) file</cert><key>Contents of private key (.key) file</key>を貼り付け
- Contents of client certificate (.crt) fileの部分に証明書発行専用のEC2インスタンスの中のクライアント証明書のeasy-rsa/easyrsa3/pki/issued/client1.domain.tld.crtの中身を上書き貼り付け
- Contents of private key (.key) fileの部分に証明書発行専用のEC2インスタンスの中のクライアントのプライベートキーのeasy-rsa/easyrsa3/pki/private/client1.domain.tld.keyの中身を上書き貼り付け
- .ovpnファイルを上書きか別名で保存してください
ClientVPNで接続する
- クライアントVPNエンドポイントの画面で「プロジェクト名-client-vpn-endpoint」にチェックを入れて「概要」で状態が「保留中-関連付け」から「使用可能」になっていたら接続可能です。保留中なら待ちましょう、早ければ2~3分で使用可能になっているはずです。
- OpenVPNに編集済みの.ovpnファイルを設定し、「接続」開始してhttps://admin.hogehoge.comをブラウザで表示出来ることを確認してください。
さらにClientVPNを、OpenVPNで切断するとhttps://admin.hogehoge.comがブラウザで表示されなくなったら成功です。
AWS ClientVPN接続がWindows10 Proで接続出来ない
Windows10 ProにAWS ClientVPNをインストールしてovpnファイルを設定して「接続」にしても・・・、
「接続に失敗しました。もう一度お試しください。」
「vpnプロセスの開始に失敗しました。ポートは別のプロセスですでに使用されています。」
などの現象が起きます。Windows Deffender でしょうか。まだ、原因追求中です。
OpenVPNを使うとうまくいきますので、めんどくさいのでこの問題からは逃げました。
その他には、certlm.mscにて他のクライアント証明書のファイル (.pfx) を手元のWindows10Proにインストール状態の場合も接続出来ませんでした。
接続エラーが出た
以下のエラーが出ました。
Connecting to management interface failed.
View log file (C:\Users\hogehoge\OpenVPN\log\・・・)for more detailes.
ovpnファイルを編集したエディタのencodingの設定なども影響あるらしく、notepad++からVSCに変えてovpnファイルを再作成(編集)しました。
尚、ovpnファイルの編集まわりでエラーが出た際は、クライアント VPN エンドポイントを参考にしてAWSからDownload後の.ovpnファイル編集をやりなおします。
ACMへの証明書アップロード数には数量制限がある!
aws acm import-certificateコマンドの実行について、AWSの1アカウントでACMで管理できる証明書はデフォルトで年間20らしいです。マジで開発のボトルネックになります。AWSの利点、小さな失敗をしながらどんどんより良いアーキテクチャを素早く作る!に対して、結構致命的な弱点です。20回なんて作り直し何回もやるとスグです。納期が明日とかに迫ってるときは、死ぬかもしれません。ちなみに私は死にました。
An error occurred (LimitExceededException) when calling the ImportCertificate operation: You have imported the maximum number of 20 certificates in the last year.
このあたりは、ACMへの証明書アップロード数量制限と上限緩和と確認でまとめました。