私の戦闘力は53万です

awsとgcpについて書きます

(初心者向け)AWS ClientVPNを設定してみる

リモートワークがどの会社でも進んでいますね・・・
割と問合せの多いClientVPNを調べてみましたのでブログにまとめてみようと思います。

ClientVPNの概要

clientVPNの概要は下記が分かりやすいと思います。
AWS Client VPN の詳細 - AWS Client VPN

f:id:remmemento:20200430022921p:plain
ClientVPNの概要

ポイントは下記です。
・End Userがインターネット経由でClientVPNエンドポイントへ接続
・ClientVPNエンドポイントからVPC内のサブネットへアクセス可能
 (サブネット内へENIを作成しNAT感覚で利用)
・Subnetと接続のあるリソースを利用可能
 (DirectConnect、VPCピアリング等)
・接続を制限するために認証機能がある
 認証方式は2つありますが、この記事では相互認証について扱います
 詳しくはこちらです。
クライアント認証と認可 - AWS Client VPN

相互認証の設定の流れ

相互認証での設定の流れはざっと下記です。
(1)認証局の構築
(2)証明書(ACM)の設定
(3)ClientVPNのAWS側設定
(4)ClientVPNクライアント設定(インストール)
(5)ClientVPNクライアント側設定
(6)VPN接続
(7)認証局の運用

検証の構成図

今回の検証では下記構成で設定してみました。
目的は、外部インターネットからClientVPNでアクセスし、
VPC内のEC2にローカルIPでアクセスすることです。

f:id:remmemento:20200502161719p:plain
試すこと

(1)認証局の構築と(2)証明書(ACM)の設定

EC2(AmazonLinux2)で認証局を構築します。
こちらの認証局のEC2は上記の構成図には登場しません。
別の場所で構築しても大丈夫です。
https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/authentication-authrization.html

cd ~
sudo yum install git -y
git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa build-server-full server nopass
./easyrsa build-client-full client1.domain.tld nopass


mkdir acm
cp pki/ca.crt acm/
cp pki/issued/server.crt acm/
cp pki/private/server.key acm/
cp pki/issued/client1.domain.tld.crt acm
cp pki/private/client1.domain.tld.key acm/
cd acm/
#ここでエラーが出る場合は、EC2へ適切なIAMRoleを付与しているかを確認してみてください。
aws acm import-certificate --certificate file://server.crt --private-key file://server.key --certificate-chain file://ca.crt --region region

ドキュメント内では、クライアント証明書もアップロードしていますが、
クライアント証明書の認証機関 (発行者) がサーバー証明書の認証機関 (発行者) と異なる場合にのみ、
クライアント証明書を ACM にアップロードする必要があります。
そのため、ここではクライアント証明書はアップロードしません。

下記を実行時に、入力が促されますが、なんでも大丈夫です
./easyrsa build-ca nopass
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:clientVPN-test

(3)ClientVPNのAWS側設定

ClientVPNを設定します。
ここで、作業前に全体像を整理します。
下記図に示すように、Subnet内のリソースにアクセスさせるために
複数の箇所で設定が必要となります。
f:id:remmemento:20200502162619p:plain

(A)ClientVPN エンドポイント作成

まず、ClientVPNエンドポイントを作成します。
構成図で言う、下記の赤字部分です。
f:id:remmemento:20200502162853p:plain
AWSの画面で言うと、下記の設定です。
f:id:remmemento:20200430025820p:plain
スプリットトンネルは有効化しておきます。
f:id:remmemento:20200430024156p:plain

(B) ClinetVPNとSubnetを紐付け

続いて、ClinetVPNとSubnetを紐付け設定します。
図の下記赤字部分です。
f:id:remmemento:20200502163248p:plain

f:id:remmemento:20200430024217p:plain
f:id:remmemento:20200430024252p:plain

紐付けたいVPCとSubnetを入力します。

Subnetを紐付けると、ルートテーブルも自動的に作成されます。
このルートテーブルにより、clientVPNのエリアからSubnetへのルーティングが可能となります。

f:id:remmemento:20200430024311p:plain
続いて認証を設定します。
f:id:remmemento:20200430024322p:plain
今回はSubnetの通信に送信を許可したいので、
「172.30.5.0/24」を入力します。

f:id:remmemento:20200430024348p:plain

(C) セキュリティグループの設定

続いてセキュリティグループの設定をします。
図の下記赤字部分です。
f:id:remmemento:20200502163427p:plain


f:id:remmemento:20200430024359p:plain

また、接続先のEC2へ、このセキュリティグループ、または
IPアドレスからの接続が許可されている必要があります。


全て設定した後、利用可能状態になるまで待ちます。
私の環境では10分ぐらいかかりました。

(4)ClientVPNクライアント設定(インストール)

AWS側の設定の準備ができたので、次はクライアントの設定です。
AWSが提供するClientをインストールします
https://aws.amazon.com/jp/vpn/client-vpn-download/

(5)ClientVPNクライアント側設定

f:id:remmemento:20200430024438p:plain
続いて「クライアント設定のダウンロード」を押下します
「〜.ovpn」のファイルがダウンロードされますのでテキストエディタで開きます。
下記のようになっているかと思います。

client
dev tun
proto udp
remote xxxxxxxxxxxxxxxxxxxxxxxxxxx.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-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
</ca>

reneg-sec 0

ここに追記していきます。
追記内容は(1)で作成した下記ABの内容です
(A)client1.domain.tld.keyの下記で囲まれた部分
 -----BEGIN PRIVATE KEY-----
 -----END PRIVATE KEY——

(B)client1.domain.tld.crtの下記で囲まれた部分
 -----BEGIN CERTIFICATE——
 -----END CERTIFICATE——
追加後のイメージは下記です。

client
dev tun
proto udp
remote xxxxxxxxxxxxxxxxxxxxxxxxxxx.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-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
</ca>

reneg-sec 0
<cert>
-----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END PRIVATE KEY-----
</key>


Clinet VPNのアプリを開き、File > ManageProfilesを選択します。
下記はMacでの実行例です。

f:id:remmemento:20200430024559p:plain

f:id:remmemento:20200430024615p:plain


Add Profileから上記で作成したファイルを選択し、適当な名前をつけます

(6)VPN接続

Connectボタンを押下します
Connectedと表示されれば接続されています。

f:id:remmemento:20200430024650p:plain

これで、Subnet内のEC2にローカルIPで直接アクセスできます。

ssh  172.30.5.120
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
https://aws.amazon.com/amazon-linux-2/
1 package(s) needed for security, out of 5 available
Run "sudo yum update" to apply all updates.

(7)認証局の運用

こちらは繋がった後の運用作業です。
相互認証では、クライアント側も機密データ(証明書)を保持します。
そのためクライアント側で問題が発生した場合には、その対応をする必要があります。
(例えば社員がパソコンを無くしてしまった時、その端末は接続不可となるよう設定すべき、など)
その場合、下記に従い、証明書失効リストを作成し
クライアントVPNエンドポイントにインストールすることで
クライアント証明書を無効化させ、接続を不可とします。
上記の例で言うと、パソコンを無くした社員に配布していたクライアント証明書を無効化させる流れです。
下記にサンプルがあるので実際に試してみます。
https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/cvpn-working-certificates.html


(1)を実施したEC2上でコマンドを実行します。

./easyrsa revoke  client1.domain.tld
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                = client1.domain.tld


Type the word 'yes' to continue, or any other input to abort.
  Continue with revocation: yes
Using configuration from /home/ec2-user/easy-rsa/easyrsa3/pki/xxxxxxxxxxxxx
Revoking Certificate xxxxxxxxxxxxxxxxxxx.
Data Base Updated

IMPORTANT!!!

Revocation was successful. You must run gen-crl and upload a CRL to your
infrastructure in order to prevent the revoked cert from being accepted.

CRLファイルを作成

./easyrsa gen-crl
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017
Using configuration from /home/ec2-user/easy-rsa/easyrsa3/pki/xxxxxxxxxxx
An updated CRL has been created.
CRL file: /home/ec2-user/easy-rsa/easyrsa3/pki/crl.pem

CRLファイルをインポート

aws ec2 import-client-vpn-client-certificate-revocation-list --client-vpn-endpoint-id xxxxxxxxxx --region ap-northeast-1 --certificate-revocation-list file:///xxxxxxxxxxx/crl.pem
{
    "Return": true
}

こちらを実行すると、クライアント証明書が無効化され、接続が不可となります。

まとめ

以上が大まかに利用の流れになります。
認証局の運用を自分でやらなくてはならないのが面倒ですが、
VPN自体の接続にはサーバを利用しないため、
自前でVPNサーバを構築するのと比較して可用性や性能の面でメリットがありそうです。
AWSACMにはプライベートCAの機能もあるので、
こちらを利用すれば(高いですが)サーバを利用しなくても良いようです。