AWS Client VPN を構築してみた(相互認証)

記事タイトルとURLをコピーする

こんにちは!イーゴリです。

この記事では、AWS Client VPN の導入をご紹介したいと思います。今回の認証方法としては相互認証(自己証明書版)を選びます。

目標

  • VPC内にあるAWSリソース(EC2など)に接続できるようにする
  • AWS Client VPN で VPC を経由してインターネットへアクセスできるようにする
  • 静的 GIP アドレスでインターネットにアクセスする
  • 認証方法として「相互認証」(サーバー証明書・クライアント証明証)を使う

構成図

前提条件

  • VPC、サブネットが存在すること
  • NAT GWが存在すること(プライベートサブネットと関連付けたい場合)
  • EC2が存在すること(任意)

証明書の作成

自己証明証を作成する方法

自己証明証を作成するには、いくつかの方法があります。

CloudShellを使う方法については下記の記事で詳しく書いてありますので、今回はEC2で証明書発行環境を準備し、証明書を発行する方法をご紹介致します。

blog.serverworks.co.jp

自己証明証を作成する

EC2に接続します。

[ec2-user@ip-10-123-10-12 ~]$ cd ~
[ec2-user@ip-10-123-10-12 ~]$ yum git
[ec2-user@ip-10-123-10-12 ~]$ sudo yum update -y
~~ログを省略~~
Complete!
[ec2-user@ip-10-123-10-12 ~]$ git version
git version 2.32.0

OpenVPN easy-rsaをインストール

[ec2-user@ip-10-123-10-12 ~]$ git clone https://github.com/OpenVPN/easy-rsa.git
Cloning into 'easy-rsa'...
remote: Enumerating objects: 3296, done.
remote: Counting objects: 100% (1155/1155), done.
remote: Compressing objects: 100% (592/592), done.
remote: Total 3296 (delta 572), reused 1102 (delta 534), pack-reused 2141
Receiving objects: 100% (3296/3296), 25.46 MiB | 12.21 MiB/s, done.
Resolving deltas: 100% (1514/1514), done.

新しい PKI 環境を初期化します。

[ec2-user@ip-10-123-10-12 ~]$ mkdir ssl #SSL用のTMPディレクトリを作成
[ec2-user@ip-10-123-10-12 ~]$ cd easy-rsa/easyrsa3/
[ec2-user@ip-10-123-10-12 easyrsa3]$ ./easyrsa init-pki
* Notice:

  init-pki complete; you may now create a CA or requests.

  Your newly created PKI dir is:
  * /home/ec2-user/easy-rsa/easyrsa3/pki

  IMPORTANT: Easy-RSA 'vars' file has now been moved to your PKI above.

新しい認証機関 (CA) を構築します。

[ec2-user@ip-10-123-10-12 easyrsa3]$ ./easyrsa build-ca nopass
* Notice:
Using Easy-RSA configuration from: /home/ec2-user/easy-rsa/easyrsa3/pki/vars

* Notice:
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017

~~ログを省略~~

Common Name (eg: your user, host, or server name) [Easy-RSA CA]:test-ca

* Notice:

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/home/ec2-user/easy-rsa/easyrsa3/pki/ca.crt

[/home/ec2-user/easy-rsa/easyrsa3/pki/ca.crt]がCAのルート証明書です。

下記のコマンドで自分自身(Subject)及び認証局(Issuer)を確認することができます。

[ec2-user@ip-10-123-10-12 ~]$ openssl x509 -text -noout -in pki/ca.crt

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            82:6d:c3:4a:4a:cc:3d:c9
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=test-ca
        Validity
            Not Before: May 10 07:59:18 2022 GMT
            Not After : May  7 07:59:18 2032 GMT
        Subject: CN=test-ca
〜省略〜

サーバーの証明書とキーを生成します。

[ec2-user@ip-10-123-10-12 easyrsa3]$ ./easyrsa build-server-full server nopass
* Notice:
Using Easy-RSA configuration from: /home/ec2-user/easy-rsa/easyrsa3/pki/vars

* Notice:
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017

~~ログを省略~~

クライアントの証明書とキーを生成します。

[ec2-user@ip-10-123-10-12 easyrsa3]$ ./easyrsa build-client-full client123.domain.tld nopass
* Notice:
Using Easy-RSA configuration from: /home/ec2-user/easy-rsa/easyrsa3/pki/vars

* Notice:
Using SSL: openssl OpenSSL 1.0.2k-fips  26 Jan 2017

Generating a 2048 bit RSA private key
~~ログを省略~~

* Notice:
Certificate created at: /home/ec2-user/easy-rsa/easyrsa3/pki/issued/client123.domain.tld.crt

作成した証明書を~/ssl/にコピーします。

[ec2-user@ip-10-123-10-12 easyrsa3]$ cp pki/ca.crt ~/ssl/
[ec2-user@ip-10-123-10-12 easyrsa3]$ cp pki/issued/server.crt ~/ssl/
[ec2-user@ip-10-123-10-12 easyrsa3]$ cp pki/private/server.key ~/ssl/
[ec2-user@ip-10-123-10-12 easyrsa3]$ cp pki/issued/client123.domain.tld.crt ~/ssl/
[ec2-user@ip-10-123-10-12 easyrsa3]$ cp pki/private/client123.domain.tld.key ~/ssl/

サーバー証明書をAWS Certificate Managerへのインポート

上記に作成したサーバー証明書をACM(AWS Certificate Manager)にインポートします。

ACM(AWS Certificate Manager)にインポートするには下記の方法があります。

  • AWSマネジメントコンソール
  • CLI(今回の記事)
  • CloudShell

今回はEC2のCLIを使用しますので、EC2からACMにインポートしたい場合、AWSCertificateManagerFullAccessが入っているポリシーのロールを作成した上、付与してください。

[ec2-user@ip-10-123-10-12 easyrsa3]$ cd ~/ssl

サーバー証明書をインポートします。

[ec2-user@ip-10-123-10-12 ssl]$ aws acm import-certificate --certificate file://server.crt --private-key file://server.key --certificate-chain file://ca.crt --region ap-northeast-1
{
    "CertificateArn": "arn:aws:acm:ap-northeast-1:<AWSアカウントID>:certificate/54f73188-ba18-424a-9397-8a3f2d2932"
}

クライアント証明書をインポートする必要な場合、下記のコマンドを実行します(今回の作業では不要)。

[ec2-user@ip-10-123-10-12 ssl]$ aws acm import-certificate --certificate file://client123.domain.tld.crt --private-key file://client123.domain.tld.key --certificate-chain file://ca.crt --region ap-northeast-1
{
    "CertificateArn": "arn:aws:acm:ap-northeast-1:<AWSアカウントID>:certificate/4c2b9bce-8253-430d-ac2e-ecc3d960ba"
}

ACMインポートの確認:[サービス]>[AWS Certificate Manager]をクリックする。

サーバー証明書が無事にインポートされました。

クライアント VPN エンドポイントの作成 

[サービス]>[VPC]>[クライアント VPN エンドポイント]>[クライアント VPN エンドポイントを作成]をクリックする。

[クライアント IPv4 CIDR]の箇所でAWS環境と重複しないクライアントVPNが使うCIDRブロックを入力します。

[サーバー証明書 ARN]の箇所でサーバー証明書を選択します。

今回の記事では、「相互認証」を使用するため、[相互認証を使用]にチェックをつけて、表示されるようになった[クライアント証明書 ARN]で、サーバー証明書※を選択します。

※下記の公式ドキュメントの通りなので、CAが同じだったら、クライアント証明書を使わなくても問題ありません。

docs.aws.amazon.com

クライアント証明書を ACM にアップロードする必要があるのは、クライアント証明書の CA がサーバー証明書の CA と異なる場合だけです

接続ログ記録を設定したい場合、[接続ログ記録]にチェックをつけて、適切な設定を行います。

私の場合、DNSサーバー1で Route 53 Resolver (旧名:Amazon Provided DNS) を指定※し、他の設定をせずに[次へ]をクリックしますが、スプリットトンネルの設定についても説明致します。

※VPCのCIDR 第4オクテッドに+2した値になる(例:VPC CIDR→192.168.0.1/16の場合、192.168.0.2がRoute 53 ResolverのIPになる)

[スプリットトンネル]を有効にしますと、VPNを接続している時に、AWSリソースにVPNトンネル経由でアクセスされますが、これ以外(インターネット通信など)はVPNトンネルを通らず通常通りクライアントの端末からインターネットなどへ通信させるようにする機能となります。

スプリットトンネルが無効の場合

スプリットトンネルが有効の場合

セキュリティグループ設定について

下記の設定でセキュリティグループを設定します。

インバウンドルール アウトバウンドルール
ルールなし すべてのトラフィック/プロトコル/ポート範囲
送信先:0.0.0.0/0

Client VPN Endpoint をVPCのサブネットに紐づける

[ターゲットネットワークの関連付け]タブをクリックし、[ターゲットネットワークを関連付ける]をクリックします。

対象VPCを選択します。サブネットを選択する時に、パブリックサブネットに置くか、プライベートサブネットに置くかは設計したい構成によって異なります。

今回の記事では、クライアント VPN ユーザーがインターネットにアクセスする時に静的 GIP アドレスで繋ぎたいため、NAT Gatewayを事前に作成して、プライベートサブネットを選択します。そして[ターゲットネットワークを関連付ける]をクリックします。

aws.amazon.com

Associatingの処理は大体5分ぐらいかかります。

冗長化を行いたいため、別のAZにあるプライベートサブネットで上記の作業を再び行います(手順は同じなので、省きます)。

上記の設定を行うだけで、通信はないため、次は承認ルールを設定します。

承認ルール

[承認ルール]タブをクリックし、[認証ルールを追加]をクリックします。

クライアント端末からVPC内のどのIPレンジへの通信を許可するかは、CIDRの形で入力します。

この時点からEC2のプライベートIPでEC2に接続できます(クライアント側の設定についてはまだ説明していないので、現時点でEC2までの接続は確認しなくても大丈夫です)。

NAT Gateway経由でインターネットへのアクセスが必要な場合、上記と同じく、設定しますが、CIDRとして0.0.0.0/0を入力します。

状態が「Active」になるまで待機します。

ルートテーブルの変更

デフォルト(指定したCIDR内)のルートテーブルが自動的に作成されますが(この時点からEC2まで接続は可能)、インターネットにアクセスを許可したい場合、0.0.0.0/0を追加する必要があります。

変更前のPing確認

設定の追加

変更後のPing確認

なお、https://checkip.amazonaws.com/でIPが変わったか、確認できます。

結果としてはNAT GatewayのGIPが表示されます。

クライアントPC側の証明書を設定する

[クライアント VPN エンドポイント]のページで、該当Client VPN Endpoint を選択し、[クライアント設定をダウンロード]をクリックします。

「.ovpn」ファイルがダウンロードされます。

下記のページから適切なAWS Client VPNをダウンロードし、インストールします。

aws.amazon.com

AWS Client VPNで上記の「.ovpn」をインポートすると、下記のエラーが発生します。

設定では、証明書とキー、auth-user-pass、または auth-federate のいずれかが指定されている必要があります。

理由はクライアント証明書及び鍵が足りないからです。

下記の形でクライアント証明書及び鍵を「.ovpn」に追加します。

方法①

変更前:

〜省略〜
</ca>

reneg-sec 0

変更後

〜省略〜
</ca>

<cert>
-----BEGIN CERTIFICATE-----
XXXX
-----END CERTIFICATE-----
</cert>

<key>
<key>
-----BEGIN PRIVATE KEY-----
XXXX
-----END PRIVATE KEY-----
</key>

reneg-sec 0

方法②

変更前:

〜省略〜
</ca>

reneg-sec 0

変更後

〜省略〜
</ca>

cert <パス><クライアント証明書名>.crt
#例)Windowsの場合、cert C:\\vpn\\client123.domain.tld.crt
key <パス><クライアント鍵名>.crt
#例)Windowsの場合、key C:\\vpn\\client123.domain.tld.key

reneg-sec 0

[接続]タブでクライアントClient VPNの接続状況を確認できます。

関連する記事:

blog.serverworks.co.jp

blog.serverworks.co.jp

以上、御一読ありがとうございました。

本田 イーゴリ (記事一覧)

カスタマーサクセス部

・2024 Japan AWS Top Engineers (Security)
・AWS SAP, DOP, SCS, DBS, SAA, DVA, CLF
・Azure AZ-900
・EC-Council CCSE

趣味:日本国内旅行(47都道府県制覇)・ドライブ・音楽