AWS VPNを用いて固定IPアドレスでインターネットを使う

## はじめに
株式会社medibaでエンジニアをしております、馬淵と申します。

今回は、一部端末がインターネットに出る際のIPアドレスを固定したいという要件がありました。
そこで、AWS VPNの証明書認証を用いてそれを実現・管理できる仕組みを作ってみました。
今回はその作った物の紹介をしていきたいと思います。
同じようなものを作る方の参考になればと思います。

## 前提条件
認証は証明書認証を利用する
使いたいIPが決まっている

## 構成図
![スクリーンショット 2023-08-18 19.17.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/9805ebd6-5376-c23d-47f0-29ed71e35f59.png)

## 手順の流れ
１、VPCを構築
２、証明書を作成
３、作った証明書をACMに登録
４、クライアントVPNエンドポイントを作成
５、クライアントVPNエンドポイントの設定
６、クライアント側の証明書の作成
７、動作確認
８、料金

## 手順
### １、VPCを構築
まずはVPC内のリソースを構築していきます。
使用するサービスは、InternertGateway、public/private subnet、Nat Gateway、ルートテーブルになります。
構成図のように、VPCを作成し、publicとprivateのサブネットを作成します。
■VPC
CIDRは10.0.0.0/16で作成しました。クライアントの数によってここを調整します。
![スクリーンショット 2023-08-28 17.22.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/dec019f3-bc44-4e76-03ba-0ec9a25a7082.png)
■Subnet：
Public、Privateの二つを作成します。
マルチAZで稼働系と待機系で冗長化する際はもう１セット作成し、ルートテーブルももう１セット作成します。
![スクリーンショット 2023-08-28 17.31.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/434ba002-28cf-f11c-9dfd-c459df31b792.png)
■NAT Gateway：
NAT Gatewayを作ります。固定したいEIPをこのNATに設定します。
Public Subnetに配置します。
■Internet Gateway：
Internet Gatewayを作ります。先ほど作成したVPCにアタッチします。
■ルートテーブル：
・Public Subnetのルートテーブル
0.0.0.0/0をInternet Gatewayに向けます。
![スクリーンショット 2023-08-28 17.35.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/d5eb644e-ce1a-0449-10b2-17215087b5c1.png)
・Private Subnetのルートテーブル
0.0.0.0/0をNat Gatewayに向けます。
![スクリーンショット 2023-08-28 17.35.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/bb574df8-1dd1-acd2-a7e6-1aa0c6100975.png)


### ２、証明書を作成
EC2内で発行しました。EC2でなくても問題はないと思います。
今回は、任意のEC2インスタンスにセッションマネージャーでSSH接続し、自己証明書を作っていきます。
セッションマネージャーの設定方法は[こちら](https://dev.classmethod.jp/articles/ec2-access-with-session-manager/)が参考になりました。


まず、作成した証明書等を格納するフォルダを作成します。
```
$ mkdir ssl
```
gitを使い、OpenVPN easy-rsaをインストールします。
```
$ git clone https://github.com/OpenVPN/easy-rsa.git
```
インストールしたディレクトリで、PKI環境を初期化します。
```
$ cd easy-rsa/easyrsa3/
$ ./easyrsa init-pki
```
認証期間(CA)を構築します。
ビルドした際に発行される、[{ディレクトリ}/easy-rsa/easyrsa3/pki/ca.crt]がルート証明書です。
```
$ ./easyrsa build-ca nopass
```
サーバー向けと、クライアント向けに証明書とキーを生成します。
``` 
  # サーバー用
$ ./easyrsa build-server-full server nopass
  # クライアント用
$ ./easyrsa build-client-full {クライアント識別名} nopass
```
作成したフォルダに写します。
```
$ cp pki/ca.crt ~/ssl/
$ cp pki/issued/server.crt ~/ssl/
$ cp pki/private/server.key ~/ssl/
$ cp pki/issued/client123.domain.tld.crt ~/ssl/
$ cp pki/private/client123.domain.tld.key ~/ssl/
```

### ３、作った証明書をACMに登録
作成したサーバー証明書とクライアント証明書をACMに登録します。
CLIで登録する場合、EC2に「AWSCertificateManagerFullAccess」が含まれているIAMポリシーを一時的に付与する必要があります。
僕はなかなかうまく行かなかったため、手動で登録しました。
■手動で登録する場合
![スクリーンショット 2023-08-28 19.21.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/e0089117-bd33-314c-a106-29425062aa47.png)
・証明書本文
証明書の本文の情報を入力します。 
「-----BEGIN CERTIFICATE-----」から、「-----END CERTIFICATE-----」までを入力します。
・証明書のプライベートキー
証明書の秘密鍵の情報を入力します。 
「-----BEGIN PRIVATE KEY-----」から、「-----END PRIVATE KEY-----」までを入力します。
・証明書チェーン
今回はルート証明書の情報を入力します。
「-----BEGIN CERTIFICATE-----」から、「-----END CERTIFICATE-----」までを入力します。

■AWS CLIでやる場合　※参考程度に
```
$ aws acm import-certificate --certificate {サーバー証明書} --private-key {サーバーのキーファイル} --certificate-chain {ルート証明書} --region {リージョン}
$ aws acm import-certificate --certificate {クライアント証明書} --private-key {クライアントのキーファイル} --certificate-chain {ルート証明書} --region {リージョン}
```

### ４、クライアントVPNエンドポイントを作成
画面右上の「クライアントVPNエンドポイントを作成」から作成します。
![スクリーンショット 2023-08-28 19.26.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/9425be42-6b12-edda-7a95-5943fbf45c91.png)
・詳細
名前とCIDRを任意のものに設定します。
![スクリーンショット 2023-08-28 19.30.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/b7fe5bb6-6786-f659-3e04-a87441040fc5.png)
・認証情報
サーバー側の証明書を指定します。
![スクリーンショット 2023-08-28 19.30.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/ffa04414-7b69-0cf1-2017-f11b052a3300.png)
「相互認証」にチェックを入れ、クライアント側の証明書を指定します。
![スクリーンショット 2023-08-28 19.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/720e3d0c-c2ee-3ca1-da31-e6a2ac067d77.png)
・接続ログ記録
ログを取りたい場合、Cloudwatchのロググループを指定します。
・その他のパラメータ
VPCIDに先ほど作成したVPCを指定します。

### ５、クライアントVPNエンドポイントの設定
・クライアントVPNエンドポイントをサブネットに紐づける
作成したクライアントVPNをクリックし、「ターゲットネットワークの関連付け」から、先ほど作成した"プライベート"サブネットを関連つけます。
この操作には少し時間がかかります。![スクリーンショット 2023-08-28 20.34.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/16324157-1974-327b-dcf5-bad24b324c34.png)
・承認ルールを設定する
「承認ルール」から、VPC内のどのIPレンジに通信を許可するかを設定します。
今回はNAT Gateway経由でインターネットへアクセスをするため、CIDRとして0.0.0.0/0を指定します。
![スクリーンショット 2023-08-28 20.40.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/429ee757-db48-46a6-6f6a-abe1bc83a607.png)
・ルートテーブルを設定する
「ルートテーブル」から、「ルートを作成」をクリックし、ルートを追加で作成します。
![スクリーンショット 2023-08-28 20.44.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/676062a7-dbe2-6c1d-8bb3-809fa6b12156.png)
これでVPNエンドポイントの設定は完了です。

### ６、クライアント側の証明書の作成
作成したクライアントVPNの詳細画面にある、「クライアント設定をダウンロード」をクリックし、.ovpnファイルをダウンロードします。
![スクリーンショット 2023-08-28 20.48.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960719/d03a4429-3b2d-a5b6-63cf-7ae60f5962fa.png)
ファイル上部にある、以下の記述を修正します。
変更前
``` 
remote cvpn-endpoint-xxxxxxxxxxxx.prod.clientvpn.ap-northeast-1.amazonaws.com 443
```
変更後(fooでなくてもなんでも大丈夫です)
``` 
remote foo.cvpn-endpoint-xxxxxxxxxxxx.prod.clientvpn.ap-northeast-1.amazonaws.com 443
```
ファイルの最後に、クライアント用の証明書ファイルの「-----BEGIN CERTIFICATE-----」から、「-----END CERTIFICATE-----」までと、クライアント用キーファイルの「-----BEGIN PRIVATE KEY-----」から、「-----END PRIVATE KEY-----」までを追記します。
変更前
``` 
略
</ca>
reneg-sec 0
```
変更後
``` 
略
</ca>
reneg-sec 0

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

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

```
これで作成完了です。


### ７、動作確認
[こちら](https://aws.amazon.com/jp/vpn/client-vpn-download/)からクライアントソフトを落とし、先ほど作成したクライアント用ソフトを読み込ませれば接続できます。

### ８、料金
料金は、ActiveなVPNエンドポイントが存在している時間と、接続しているクライアントの数によって変動します。
NAT Gatewayにも料金がかかります。
僕が作成した時(23年8月)は以下の料金式で計算していました。
```
■クライアントVPNエンドポイント
エンドポイント：
　0.10USD × h　×　関連付けたサブネット数
接続　　　　　：
　0.05USD × h　×　接続数
■AWS Nat Gateway
NATゲートウェイ：
　0.045USD × h　
NATデータ処理　：
　0.045USD × トラフィック(GB) 
```


## 終わりに
以上になります。ここまで長い記事をご覧いただきありがとうございました。
実作業時間は、ぽちぽちするだけなら1時間あれば設定することができると思います。
初めに作る時は何の事かわからない事だらけでしたが、作って見ると意外とシンプルで、VPN周りの考え方を勉強でき、いい機会になりました。
数日動かす程度ならそこまで料金がかからないので、一度作ってみてはいかがでしょうか。
また丁度いいネタを見つけ次第、アウトプットしていこうと思います。

## 参考記事
[AWS VPN の料金](https://aws.amazon.com/jp/vpn/pricing/)
[Amazon VPC の料金](https://aws.amazon.com/jp/vpc/pricing/)
[セッションマネージャーを使って鍵ストレスの無いEC2アクセス](https://dev.classmethod.jp/articles/ec2-access-with-session-manager/)
[AWS Client VPN を構築してみた（相互認証）](https://blog.serverworks.co.jp/aws-client-vpn-self-signed-certificate)
[【Azure AD】AWS Client VPN の SSO環境構築](https://blog.serverworks.co.jp/ClientVPN_AzureAD_SSO#AWS-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88VPN%E3%82%A8%E3%83%B3%E3%83%89%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A)
[AWS VPC の Client VPN を構築してみた](https://www.membersedge.co.jp/blog/aws-vpc-client-vpn-building/)
[AWS Client VPN構築・設定（相互認証、プライベートDNS）](https://qiita.com/kj_hira/items/55849418b108b14b8243)
[AWS Client VPN の IP アドレスを固定化してインターネットと通信する](https://labs.snaq.me/entry/2020/12/28/101333)
[AWSクライアントVPNエンドポイントとCertificate Manager(ACM)を用いて証明書を発行・再発行・更新・失効する](https://zenn.dev/horitomo/articles/9d5c42a2386397#4.-%E8%A8%BC%E6%98%8E%E6%9B%B8%E5%A4%B1%E5%8A%B9%E4%BD%9C%E6%A5%AD)
[AWS Certificate Manager (ACM)にインポートしたSSL/TLS証明書の更新方法について](https://dev.classmethod.jp/articles/aws-ssl-certificate-update/)
[AWS Client VPNクライアント証明書の管理手順を整理してみた](https://dev.classmethod.jp/articles/manage-aws-client-vpn-client-certificates/)