1. AWS Clinent VPN 導入の目的
スマホからのアクセスを固定IP化したい。
2. AWS Clinetn VPN 導入の経緯
とある受託案件の検証環境は、今までIP制限
をしていました。
会社のIPはもちろん許可していたため、PCもスマホも会社のネットワークに繋ぐことで検証環境にアクセスできていました。
しかしコロナウイルスによって在宅勤務が強制
されることになったため、自宅環境ではIPの固定化ができず、検証環境にアクセスすることができなくなってしまいました。
※PCであれば会社が用意したVPNに接続することができるのですが、スマホは会社が用意したVPNに接続することができません。
そのため案件専用のVPNとしてAWS Client VPN
を用意し、スマホからのアクセスを固定IP化
することにしました。
3. AWSClientVPNのポイント
-
VPC上に
Client VPN Endpoint
を作成することで、クライアント(PCやスマホ)とVPCの間でVPNを張ることができます。 -
OpenVPN
(オープンソースのVPNソフトウェア)を利用しています。 -
認証は
ActiveDirectoryによるアカウント管理
,サーバ証明書・クライアント証明書による相互認証
のいづれか、もしかはその両方
を利用できます。 -
ActiveDirectory認証では
AWSDirectoryService
を利用することになります。オンプレのADと連携したい場合はADConnector
を噛ませることで実現可能です。
4. AWSClientVPNの料金
- A) ClientVPNEndpointに関連付けられているサブネットの数 × 利用時間(hrs)
- B) アクティブなクライアント接続の数 × 利用時間(hrs)
AとBの合算になります。
4-1. シミュレーション
条件
冗長構成にするために2つのサブネットに関連付けをし、営業日には10端末からそれぞれ2h利用する。
金額計算
- A) 2 × 24 × 30 × 0.15 =
$216
- B) 10 × 2 × 20 × 0.05 =
$20
合計 $236/月
5. 今回構築した構成のアーキテクチャ
5-1. 認証
"ActiveDirectoryによるアカウント管理" をするためには別途 "AWSDirectoryService" の費用がかかってしまうため、今回はサーバ証明書・クライアント証明書による相互認証のみ
で構築しました。
SimpleAD
で最低$36/月
かかるっぽいです。
###5-2. 証明書の作成
もちろん自分自身のPCでもできますが、他のインフラ担当者も同じ認証局が使えるように、共用環境としてVPN Client Endpointを構築するVPCのbastionサーバー
にて作成しました。
証明書は内部利用(いわゆるオレオレ証明書)に限られるので、有効期限を100年
に設定しました。
###5-3. VPC
アクセス先はステージング環境のVPCとなりますが。Client VPN Endpointをステージング環境に構築しても基本的には問題ありませんが、なるべく外部からのアクセスっぽくしたかったのと、ステージング環境に極力手を入れたくなかったため、Client VPN Endpointは別のVPNに構築することにしました。
###5-4. 関連付けるサブネット
導入の経緯に書いたようにサービスにクリティカルな用途ではないため、冗長構成にせず1つのサブネットのみに関連付けさせるようにしました。
6. 構築手順
6-1. 証明書の作成
bastionサーバーログインしOpenVPN Easy-RSA レポジトリのクローンを作成
します。
なお私はbastionサーバーのrootユーザーになりホームディレクトリをカレントディレクトリとして作業をしましたが、rootユーザーである必要性はありません。
$ cd ~
$ git clone https://github.com/OpenVPN/easy-rsa.git
作成した証明書や鍵をまとめて保管ためのディレクトリを作成しておきます。
$ mkdir ssl
ローカルリポジトリの easy-rsa/easyrsa3 フォルダに移動します
$ cd easy-rsa/easyrsa3
証明書の有効期限を100年に変更します。
$ cp vars.example vars
$ vim vars
$ diff vars.example vars
125c125
< #set_var EASYRSA_CA_EXPIRE 3650
---
> set_var EASYRSA_CA_EXPIRE 36500
129c129
< #set_var EASYRSA_CERT_EXPIRE 825
---
> set_var EASYRSA_CERT_EXPIRE 36500
134c134
< #set_var EASYRSA_CRL_DAYS 180
---
> set_var EASYRSA_CRL_DAYS 36500
新しい PKI 環境を初期化します。
$ ./easyrsa init-pki
6-1-1. ルート証明書
1つだけ作成します。ACMに登録する必要があります。
まずは新しい認証機関(CA)を構築します。
$ ./easyrsa build-ca nopass
画面の指示に従って、CA を構築します。
作成されたルート証明書とルート鍵を保管用ディレクトリにコピーします。
$ cp pki/ca.crt ~/ssl/
$ cp pki/private/ca.key ~/ssl/
ACMに登録します。その際中間証明書(chain)は指定無しで大丈夫です。
$ cd ~/ssl
$ aws acm import-certificate --certificate file://ca.crt --private-key file://ca.key --region ap-northeast-1
6-1-2. サーバー証明書
サーバー証明書は1つだけ作成します。ACMに登録する必要があります。
サーバー証明書とキーを生成します。
$ ./easyrsa build-server-full server nopass
作成されたルート証明書とルート鍵を保管用ディレクトリにコピーします。
$ cp pki/issued/server.crt ~/ssl/
$ cp pki/private/server.key ~/ssl/
サーバー証明書をACMに登録します。その際中間証明書(chain)はルート証明書を指定します。
$ cd ~/ssl
$ aws acm import-certificate --certificate file://server.crt --private-key file://server.key --certificate-chain file://ca.crt --region ap-northeast-1
6-1-3. クライント証明書
ルート証明書をベースに作成します。ユーザー単位、もしくは端末単位など、管理したい単位ごとに作成します。
クライント証明書はACMに登録する必要はありません。
ここでは例として、山田太郎さんのandroid端末用
としてクライント証明書を発行します。
$ ./easyrsa build-client-full taro.yamada.android nopass
これでクライント証明書とクライント鍵が以下に作成されました。
###6-2. Client VPN Endpoint の作成
AWSマネジメントコンソールにログインし下記の手順で Client VPN Endpoint を作成します。
ステップ 2: Client VPN エンドポイントを作成する
エンドポイント名前、クライアントに割り当てるCIDR、利用するサーバ証明書・ルート証明書などを選択します。(選択する証明書はACMに登録されている必要があります)
接続ログを CloudWatch Logs
に残すかどうかも選択できますが、ロググループは自動生成してくれないため、事前に作成したうえで指定するあります。ログストリームはおそらく自動生成してくれるかも。
またクライアントが使用するDNSサーバやTLSセッションにTCP/UDPのどちらを利用するかを選択することができますが、特にこだわりはないのでデフォルトのままとしています。
なお Client VPN Endpoint を作成した時点ではまだ利用料金は発生しません
###6-3. Client VPN Endpoint をVPCのサブネットに関連付ける
Client VPN Endpointをサブネットに関連付けすると、サブネットごとにENIが作成されます。ENIが作成された時点から料金が発生することになります。
ステップ 3: クライアントの VPN 接続を有効にする
作成されたENIには、自動的にそのVPCのデフォルトセキュリティグループがアタッチされます。
通信元/先IPアドレスやポートを制限したい場合は、別のセキュリティグループをアタッチすることができます。
本来であれば専用のセキュリティグループをアタッチすべきですが、今回はちょっとサボってデフォルトのままとしました。
またクライアントPCからVPN経由でVPC内のリソース等にアクセスすると、接続元IPアドレスはENIのIPになっています(NATされている)。接続先リソースのセキュリティグループ設計はそれを考慮する必要があります。
###6-4. クライアントのアクセスの「承認」
クライアント端末からVPC内のどのIPレンジへの通信を許可するか、CIDR形式で許可する必要があります。
ステップ 4: クライアントのネットワークへのアクセスを承認する
認証タブ
を選択すると、クライアント端末から接続可能な接続先一覧が表示され、許可を追加することができます。デフォルトではどのCIDRも許可されていないので、接続先を追加します。
VPC内の特定のCIDRのみを許可すれば、クライアント端末からはその範囲までにしかアクセスできません。
今回はNATGateway経由でインターネットに出る必要があるため0.0.0.0/0
への通信を許可する必要があります。
###6-5. 追加のネットワークへのアクセスを有効にする
Client VPN Endpoint には「ルートテーブル」の設定があります。
ステップ 5: (オプション) 追加のネットワークへのアクセスを有効にする
クライアント端末からVPC内にだけ通信する用途であれば、デフォルト設定で問題ありません。
今回はクライアント端末からNATGateway経由でインターネットに出たいので、追加の設定が必要になります。
Client VPN Endpointのルートテーブルにレコードを追加する際には、宛先のCIDR
とターゲットサブネット
の2つを指定します。クライアント端末から通信がClient VPN Endpointに到達すると、その後パケットは、宛先CIDR
情報をもとにターゲットサブネット
に振られ、そのサブネットのルートテーブルに従います。
そのため今回の用途のように、NATGateway経由でインターネットに出たい場合は、以下のレコードをClient VPN Endpointのルートテーブルに追加することになります。
宛先のCIDRが「0.0.0.0/0」。ターゲットサブネットが「Client VPN Endpointに関連付けたプライベートサブネット」
※そもそもターゲットサブネットは、関連付けたサブネットからしか設定することができません。今回は1つしか関連付けていないため一択となります。
###6-6. クライアント用の設定プロファイルをダウンロードする
クライアント用の設定プロファイルをダウンロードして、クライアントソフトに設定します。
ステップ 6: Client VPN エンドポイントの設定ファイルをダウンロードする
マネコンでクライアント設定のダウンロード
ボタンを押せば.ovpn
という拡張子の設定プロファイルをダウンロードできます。
中身は以下のようになっているはずです。
client
dev tun
proto udp
remote cvpn-endpoint-xxxxxxxxxxxxxxxxx.prod.clientvpn.ap-northeast-1.amazonaws.com 443
remote-random-hostname
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
verb 3
<ca>
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
</ca>
reneg-sec 0
しかし、このプロファイルそのままではVPN接続ができないため、少しイジってあげる必要があります。
####6-6-1. 接続先エンドポイントの細工
接続先のエンドポイントとしては、*.[エンドポイント名].prod.clientvpn.ap-northeast-1.amazonaws.com
でIPを取得できますが、ダウンロードしたクライアント設定プロファイルは以下のようになっていました。
remote cvpn-endpoint-xxxxxxxxxxxxxxxxx.prod.clientvpn.ap-northeast-1.amazonaws.com 443
そこで、接続先に適当なホスト部を追記します。
remote dummy.cvpn-endpoint-xxxxxxxxxxxxxxxxx.prod.clientvpn.ap-northeast-1.amazonaws.com 443
####6-6-2. クライント証明書と鍵の埋め込み
作成したクライアント証明書の—–BEGIN CERTIFICATE—–
から—–END CERTIFICATE—–
までと、
クライアント鍵の—–BEGIN PRIVATE KEY—–
から—–END PRIVATE KEY—–
までを追記します。
<cert>
-----BEGIN CERTIFICATE-----
YYYYYYYYYYYYYYYYYYYY
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
ZZZZZZZZZZZZZZZZZZZZ
-----END PRIVATE KEY-----
</key>
設定プロファイルは最終的には以下のようになります。
client
dev tun
proto udp
remote *.cvpn-endpoint-XXXXXXXXXXXXXXXX.clientvpn.ap-northeast-1.amazonaws.com 443
remote-random-hostname
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
verb 3
<ca>
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
YYYYYYYYYYYYYYYYYYYY
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
ZZZZZZZZZZZZZZZZZZZZ
-----END PRIVATE KEY-----
</key>
reneg-sec 0
##7. 運用フェーズ
###7-1. クライアント証明書の新規発行
ここでは例として、山田太郎さんのios端末用
クライント証明書を新規発行します。
$ CLIENTNAME=taro.yamada.ios
$ cd ~/easy-rsa/easyrsa3
$ ./easyrsa build-client-full ${CLIENTNAME} nopass
$ cp pki/issued/${CLIENTNAME}.crt ~/ssl/
$ cp pki/private/${CLIENTNAME}.key ~/ssl/
###7-2. クライアント証明書の無効化
端末を紛失した場合や、漏洩の可能性がある場合には、クライアント証明書を無効化する必要があります。
CRL(クライアント証明書失効リスト)
を使用すると、特定のクライアント証明書をブラックリストに入れることができます。ブラックリストに入れたクライアントは、クライアント VPN エンドポイントにアクセスできなくなります。
ここでは例として山田太郎さんのios端末用
クライント証明書を失効させます。
ルート証明書・サーバー証明書・クライアント証明書などを作成したbastionサーバー
にログインし、easy-rsa/easyrsa
フォルダに移動します。
$ CLIENTNAME=taro.yamada.ios
$ cd ~/easy-rsa/easyrsa3
失効リスト用の前準備をします。プロンプトが表示されたらyes
と入力します。
$ ./easyrsa revoke ${CLIENTNAME}
Note: using Easy-RSA configuration from: /root/easy-rsa/easyrsa3/vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Please confirm you wish to revoke the certificate with the following subject:
subject=
commonName = taro.yamada.ios
Type the word 'yes' to continue, or any other input to abort.
Continue with revocation:
クライアント証明書失効リストを生成します。
$ ./easyrsa gen-crl
Note: using Easy-RSA configuration from: /root/easy-rsa/easyrsa3/vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Using configuration from /root/easy-rsa/easyrsa3/pki/easy-rsa-17745.1UBzCm/tmp.XrqfAj
An updated CRL has been created.
CRL file: /root/easy-rsa/easyrsa3/pki/crl.pem
このcrl.pem
は、今まで失効されたクライアント証明書情報も入っています。
Cleient VPN Endpointに適用します。
$ aws ec2 import-client-vpn-client-certificate-revocation-list --certificate-revocation-list file:/root/easy-rsa/easyrsa3/pki/crl.pem --client-vpn-endpoint-id ${endpoint_id} --region ap-northeast-1
これ以降、該当のクライアント証明書からはVPN接続ができなくなります。
##8. AWS Clinetn VPNの制限
Key | Value |
---|---|
アカウントあたりの クライアント VPN エンドポイント数 | 5 |
クライアント VPN エンドポイントあたりの承認ルールの数 | 50 |
クライアント VPN エンドポイントあたりのルート数 | 10 |
クライアント VPN エンドポイントあたりの同時クライアント接続数 | 2000 |