今回のゴール
以前、
AWS プライベートサブネット環境からインターネットに接続
環境を構築したのですが、そこからClientVPN経由でAWSのプライベートサブネットに直接アクセスできるようにします。

事前準備
サーバー証明書とクライアント証明書の作成してACMへアップロード
下記サイトを参照して、サーバー証明書とクライアント証明書を作成し、ACMにインポートしてください。
https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/client-authentication.html#mutual
CloudWatchのロググループとログストリームの作成
ClientVPNの接続詳細を記録するときは予めCloudWatchのロググループとログストリームを作成します。
クライアントVPNエンドポイントの作成
VPCメニューより”クライアント VPN エンドポイント”メニューを選択して「クライアント VPN エンドポイントの作成」ボタンをクリックします。

[名前タグ]:識別できる名称
[クライアントIPv4 CIDR]:クライアントに割り当てるCIDR。/22以上で割り当てます。今回は10.10.0.0/22としました
【認証情報】
[サーバー証明書 ARN]:ACMにインポートしたサーバー証明書
[認証オプション]:”相互認証の使用”と”ユーザーベースの認証を使用”にチェックをつけて、”Active Directory 認証”を選択します。
[クライアント証明書 ARN]:ACMにインポートしたクライアント証明書
[ディレクトリID]:ActiveDirectory認証のディレクトリIDを選択します。
同一の認証局(CA)でサーバー証明書とクライアント証明書を発行するときは、クライアント証明書の登録はいらないようなのですが、必須なので選択します。
【接続ログ記録】
※ロググループ・ストリームはここでは作成できませんので事前に作成ください。
[クライアント接続の詳細を記録しますか]:”はい”にチェック
[CloudWatch Logs ロググループ名]:登録済のロググループ名を選択
[CloudWatch Logs ログストリーム名]:登録済のログストリーム名を選択
【その他のオプションパラメータ】
[DNSサーバー1 IP アドレス][DNSサーバー2 IP アドレス]:今回はDirectoryService使用しているのでそのDNSのIPアドレスを入力。(DirectoryServiceメニューで確認できます)

作成したクライアントVPNエンドポイントをサブネットに割り当てていきます。
作成されたクライアントVPNエンドポイントを選択して、”関連付け”タブより「関連付け」ボタンをクリックします。

[VPN]:関連づけるVPCを選択
[関連付けるサブネットの選択]:サブネットを選択します。

サブネットに関連付けされました。
※本来であれば冗長性を考えてもう1つのプライベートサブネットにも関連付けするのですが、今回は予算の関係で見送りました。

次は、クライアントがクライアントVPNエンドポイント経由でどのネットワークにアクセスできるかを設定します。
“認証タブ”より「受信の承認」ボタンをクリックします。

[アクセスを有効にする送信先ネット]:今回プライベートサブネットのサブネットを入力しました。
[アクセスを付与する対象]:”すべてのユーザーにアクセスを許可する”を選択しました。
この登録をもう1つのプライベートサブネット分も登録しました。

クライアントの設定
これでAWSの準備は整いました。
「クライアントの設定をダウンロード」ボタンをおして、OpenVPNクライアント用の設定ファイル(.ovpn)をダウンロードします。

ダウンロードしたファイルをメモ帳で開き、一番下にクライアント証明書と秘密鍵のファイルのディレクトリを追加してください。
(ディレクトリは各自変更してください。)
cert C:\\Users\\[ユーザー名]\\OpenVPN\\config\\client.crt
key C:\\Users\\[ユーザー名]\\OpenVPN\\config\\client.key
今の設定ではすべての通信がVPNに流れてしまいますでの、10.0.0.0/16宛の通信のみVPNに流れるように設定します。
下記も同様に追加します。
※これを設定しないとVPN接続後、インターネットが見れなくなってしまします。
pull-filter ignore redirect-gateway
route 10.0.0.0 255.255.0.0
クライアントからのVPN接続
今回はOpenVPNを使用しますので、下記URLからインストールします。
https://openvpn.net/community-downloads/
インストール後、タスクトレイにあるOpenVPNアイコンを右クリックして”Import file”を選択してクライアント設定ファイル(.ovpn)をインポートします。
(タスクトレイにアイコンがないときはスタートメニュより”OpenVPN GUI”を実行してください)

接続します。

ログイン画面が表示されますので、ADに登録されているユーザーを入力します。

接続成功すると、メッセージが表示され、アイコンの画面が通信中(緑)になります。

確認
ローカルのコマンドプロンプトからAWSのDNSにpingが通るか確認します。
ping 10.0.0.xxx
10.0.0.xxx に ping を送信しています 32 バイトのデータ:
10.0.0.xxx からの応答: バイト数 =32 時間 =11ms TTL=127
ローカルのコマンドプロンプトからnslookupでプライベートサブネットにあるWorkSpacesのVDIの名前解決ができるか確認します。
nslookup XXXXXX-XXXXXXX
サーバー: xxxxx.co.jp
Address: 10.0.0.xxx
名前: XXXXX-XXXXX.xxxxx.co.jp
Address: 10.0.0.xx
【補足】 EC2インスタンスにVPN経由で接続
ローカルのコンピューターからVPN経由でEC2インスタンスにリモート接続する時は、EC2インスタンスのセキュリティーグループの設定でクライアントVPNエンドポイントのセキュリティーグループからのインバウンドを許可するように設定します。
つまり、ローカルPCからの通信は、クライアントVPNエンドポイントで一旦NATされている事になります。
【補足】Client VPN Endpointのセキュリティーグループ
VPCに設定されているdefaultのセキュリティーグループが割り当てられますので、新規でセキュリティーグループを作成してアタッチします。
インバウントは何も許可する必要はありません。
今回はアウトバウンドは全て許可としました。
【追加】リモート端末からClient VPN でVPCを経由してインターネットにアクセスする
外部のサーバー等に接続する際にIPフィルタリング設定(VPCからのIPアドレスのみ許可)をしている時、リモート端末からVPCのNATゲートウェイ経由でインタネットにアクセスしたい時があります。
VPCサービスの[クライアントVPNエンドポイント]で該当のエンドポイントを選択して、[認証]-「受信の承認」をクリックします。

[アクセスを有効にする送信先ネット]:0.0.0.0/0
を入力して認証ルールを追加します。

次に[ルートテーブル]-「ルートの作成」をクリックします。

[ルート送信先]:0.0.0.0/0
[ターゲットVPCサブネットID]:private subnet(任意)

上記の”クライアントの設定”で、OpenVPNの設定ファイルに10.0.0.0/16の通信だけVPN経由とするように設定したのですが、インターネットの通信もVPN経由をなるように、その設定をコメントにします。
#pull-filter ignore redirect-gateway
#route 10.0.0.0 255.255.0.0
Client VPNを接続して、IP確認サイトでNATゲートウェイに割り当てられているIPになっていることが確認できました。
また、下記のように特定のIP・ドメインだけをVPN経由とする事も可能です。
pull-filter ignore redirect-gateway
route www.xxxx.jp
route xxx.xxx.xxx.xxx 255.255.255.255