【ベストプラクティス】Amazon VPC の構築方法を分かりやすく解説

# はじめに
**Amazon VPC**は、**AWS上で仮想ネットワークを構築**できるサービスです。
VPCの**概要や理論**については**以下の記事**で詳細に解説しました。

https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77

一方で、「**理論だけでなく実践も重要！**」
と思われる方も多いと思いますので、
**本記事では実際にVPCによる仮想ネットワークを構築**する方法を解説します。

構築の指針として、以下の**ベストプラクティスを極力満たすよう**進めていきたいと思います。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-security-best-practices.html

特に[**VPCフローログ**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcとログ)や[**VPCピアリング**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcピアリング)、[**VPN**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpn-仮想プライベートネットワーク)等は**設定が複雑**でハマりがちですが、**極力分かりやすく解説**したつもりなので、効率よく構築法を習得できる記事となれば幸いです。

## 本記事で構築するVPCの構成
下図構成のVPC ([上記記事の冒頭で紹介した構成](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcとは))の構築を、実際のコンソール操作方法を交えて解説します。

<img width=720 alt="構築するVPC構成図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/42d9caf9-082f-9340-3cb7-490628d5938e.png">

**上記構成の意図**として、VPC1 (**Webアプリ用のVPC**)とVPC2 (**社内ネットワークを模擬したVPC**)を組み合わせる事で、**アプリ公開用ネットワークと社内ネットワークを擬似的に再現**する事を目指します。
(今回は本筋から外れるので紹介しませんが、実運用時はWAFやIDS等の防御用製品と組み合わせたり、証明書を取得してHTTPS化する等の対策を行い、セキュリティレベルを高めて下さい)

長いですが、完了する頃には簡単な業務用ネットワークに相当するVPCが構築できると思うので、ぜひお付き合い頂ければと思います。

## VPCのセキュリティベストプラクティス
実際に構築に入る前に、**満たすべきベストプラクティス**の内容を確認します ([AWS公式を参照](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-security-best-practices.html))

**・ベストプラクティス一覧**

|ベストプラクティス推奨事項|関連機能|
|---|---|
|[**複数の AZ へのサブネットの追加 (マルチ AZ 構成)による高可用性の確保**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#マルチaz構成による高可用性の確保)|[AZ](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#-アベイラビリティゾーンaz)<br>[サブネット](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcとサブネット)<br>[ELB](https://aws.amazon.com/jp/elasticloadbalancing/)<br>[Auto Scailing](https://aws.amazon.com/jp/autoscaling/)|
|[**ネットワーク ACL を使用してサブネットへのアクセスを、セキュリティグループを使用してサブネット内のインスタンスへのトラフィックを制御する**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ネットワークaclを使用してサブネットへのアクセスをセキュリティグループを使用してサブネット内のインスタンスへのトラフィックを制御する)|[セキュリティグループ](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#セキュリティグループ)<br>[ネットワークACL](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ネットワークacl)|
|[**IAM の ID フェデレーション、ユーザー、ロールを使用して、AWS VPC リソースおよび API へのアクセスを管理する**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#iam-の-id-フェデレーションユーザーロールを使用してaws-vpc-リソースおよび-api-へのアクセスを管理する)|[IAM](https://qiita.com/c60evaporator/items/0121399880625cc1de51)|
|[**VPC フローログで Amazon CloudWatch を使用して IP トラフィックを監視する**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc-フローログで-amazon-cloudwatch-を使用して-ip-トラフィックを監視する)|[セキュリティグループ](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#セキュリティグループ)<br>[ネットワークACL](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ネットワークacl)|

それぞれ解説します

### マルチAZ構成による高可用性の確保
VPC内の**複数のAZに並列**にサブネットおよびインスタンスを設置する**マルチAZ構成**を構築することで、**片方のAZで障害**が起きたとしても、**高可用性、耐障害性、拡張性を確保**できます。

特に商用のWebアプリケーションにおいては必須とも言える構成であり、[ELB](https://aws.amazon.com/jp/elasticloadbalancing/) (ALB, NLB)や[Auto Scaling](https://aws.amazon.com/jp/autoscaling/)と組み合わせることで、平常時もアクセス数に応じて適切にAZ間で負荷分散を実現する事ができます (ELB, Auto Scalingについては別記事で詳細に紹介します)

下記記事のように、過去のAWS障害においてもマルチAZ構成の運用法選択が耐障害性に大きく寄与した事が見て取れます

https://www.itmedia.co.jp/news/articles/1908/28/news127.html

本記事においては、[**冒頭の構成**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)の「**VPC1**」のように、**2個のAZに並列にサブネットを作成**し、それぞれWebサーバ・APサーバ・DBサーバを設置することで、**マルチAZ構成を実現**しています

<br>

### ネットワークACLを使用してサブネットへのアクセスを、セキュリティグループを使用してサブネット内のインスタンスへのトラフィックを制御する
[前述の記事で触れたように](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcのセキュリティ機能)、VPCではファイアウォールの役割を果たす[**ネットワークACL**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ネットワークacl)と[**セキュリティグループ**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#セキュリティグループ)を利用して、**VPC内部のアクセス制御**を実施します。

これらのアクセス制御機能はVPCのセキュリティの要と言える存在のため、**ユースケースに合わせて必ず設定してください**。

両者の主な違いは以下の表を参照下さい。

|名称|外部側フィルタ対象|フィルタ方式|戻り通信の扱い|内部側フィルタ対象|
|---|---|---|---|---|
|**ネットワークACL**|外部側IPアドレス + ポート番号 + [プロトコル](https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)|ホワイトリスト + ブラックリスト|ステートレス|サブネットごと|
|**セキュリティグループ**|外部側IPアドレス ([セキュリティグループID](https://www.sunnycloud.jp/column/20210716-01/), [プレフィックスリスト](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#マネージドプレフィックスリスト)も指定可) + ポート番号 + [プロトコル](https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)|**ホワイトリスト**|**ステートフル**|**インスタンスごと** (セキュリティグループIDでグルーピング)|

なお、AWS公式では触れられていませんが、以下のような多くのサードパーティーの記事では、**ネットワークACLよりもセキュリティグループを優先して使用**する事が**推奨**されています。

https://dev.classmethod.jp/articles/why-i-prefer-sg-to-nacl/

主な理由として、[ステートレス](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ステートレス)かつ[ホワイトリストとブラックリスト](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ファイアウォールとacl)両方を指定可能な**ネットワークACLは設定が煩雑**で、[ステートフル](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ステートフル)かつホワイトリストのみで指定する**セキュリティグループは設定がシンプル**であり、**ミス等を防ぎやすい**事が挙げられます (他にも、サブネット単位でしかルール設定できないネットワークACLと比べ、セキュリティグループはインスタンス単位でより細かいアクセス制御ができることも挙げられます)

**本記事でも、セキュリティグループによるアクセス制御を実施**します　(ネットワークACLはデフォルト設定のまま使用します)

<br>

### IAM の ID フェデレーション、ユーザー、ロールを使用して、AWS VPC リソースおよび API へのアクセスを管理する
こちらはVPCというよりIAMに関する内容 ([公式の解説](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/security-iam.html)もIAMの定義そのもの)となりますが、**VPC内外のリソース** (インスタンスやS3のバケット)には**IAMによるアクセス権限を適切に付与**する必要があります。

前述のネットワークACLやセキュリティグループが「ネットワーク側でのアクセス制御」であれば、このIAMは「**ホスト側でのアクセス制御**」に相当します。

**詳細は以下のIAMの記事を参照**ください

https://qiita.com/c60evaporator/items/0121399880625cc1de51

本記事では、[VPCフローログ](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#フローログの作成-vpc1)や[S3](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#s3アクセス用iamロールの付与)へのアクセスにおいてIAMの設定が登場します。
このようにCloudWatchやS3等、**VPC外のサービスとのアクセス制御**において、特に**IAMは重要な役割**を果たします。

<br>

### VPC フローログで Amazon CloudWatch を使用して IP トラフィックを監視する
セキュリティ対策として、**ログを保存**して後から攻撃や不具合の原因を追跡できるようにする事は重要です。

VPCにおいては、[**VPCフローログ**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcとログ)がこの役割を果たします。

VPCフローログの保存場所にはCloudWatchとS3を選択する事ができます。
[こちらのサイト](https://dev.classmethod.jp/articles/vpc-flow-logs-athena/)をみる限り、2つの保存場所は以下のように使い分けるとよさそうです。

|フローログの保存場所|用途|
|---|---|
|**CloudWatch Logs**|ネットワークトラフィックの特定のアクセス傾向を検知してアラームを発する場合|
|**S3**|フローログを蓄積してAthenaで分析する場合 or コストを低減したい場合|

ベストプラクティスにおいては、CloudWatch Logsへの保存が推奨されています。

**本記事**においても、[**CloudWatchへのフローログ保存の設定**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#フローログの作成-vpc1)を実施します

<br>
<br>

# 具体的な構築方法
ここからは具体的な構築方法を解説します。
繰り返しとなりますが、以下のVPC構成をベストプラクティスを満たすよう構築していきます。

<img width=720 alt="構築するVPC構成図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/42d9caf9-082f-9340-3cb7-490628d5938e.png">

以下の手順で構築を進めます

- [**VPCとサブネットの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpcとサブネットの作成-vpc1)
- [**セキュリティグループの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#セキュリティグループの作成-vpc1)
- [**ルートテーブルの設定 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ルートテーブルの設定-vpc1)
- [**EC2インスタンスの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ec2インスタンスの作成-vpc1)
- [**フローログの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#フローログの作成-vpc1)
- [**ELBの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#elbの作成-vpc1)
- [**RDSの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#rdsの作成-vpc1)
- [**S3バケットの作成 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#s3バケットの作成-vpc1)
- [**各インスタンスへの疎通確認 (VPC1)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#各インスタンスへの疎通確認-vpc1)
- [**VPCとサブネットの作成 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpcとサブネットの作成-vpc2)
- [**セキュリティグループの作成 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#セキュリティグループの作成-vpc2)
- [**EC2インスタンスの作成 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ec2インスタンスの作成-vpc2)
- [**VPCピアリングの作成 (VPC1＆2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpcピアリングの作成-vpc2)
- [**ルートテーブルの設定 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ルートテーブルの設定-vpc2)
- [**プロキシサーバの設定 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#プロキシサーバの設定-vpc2)
- [**VPNの作成 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpnの作成-vpc2)
- [**各インスタンスへの疎通確認 (VPC2)**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#各インスタンスへの疎通確認-vpc2)

長いですが、**Webアプリを前提としたVPC構築ではほぼ同様のフローが生じる** (Lambdaのようなサーバレス主体の構成を除く)ため、VPCをこれから使おうという方は、ぜひご一読頂ければと思います。

<br>

## VPCとサブネットの作成 (VPC1)
最初にVPCを作成する際には、VPCと一緒にサブネットやエンドポイント等を作成できる**VPCウィザード**を使用すると便利です。

VPCウィザードは、以下のように「VPCウィザード」→「VPCを作成」の順で操作することで作成できます

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/2e173aa0-93d9-16b9-65a4-e243b99085a9.png">

※以下のように「お使いのVPC」タブから作成することもできます

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/0be70350-37f5-3721-3415-f05435f07fab.png">

###  VPCウィザードで指定できる設定
VPCウィザードでは、下図のような設定を指定することができます。

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/cce110f1-f7cb-0ebb-b0eb-d6d5ff83235d.png">

選択した設定のVPC構成が「プレビュー」に表示されるため、GUIで逐一設定を確認できて便利です。

それぞれ解説します

#### ・作成するリソース
「VPCのみ」と「VPCなど」どちらかを選択でき、「VPCなど」を選択した場合は一緒にサブネットやエンドポイントを作成する事ができます。

「VPCなど」を選択した方が設定が楽になるため、最初はこちらを選択すると良いでしょう

#### ・名前タグの自動生成
こちらで設定した名称がVPC名や内部のリソース名 (サブネット、ルートテーブル、IGW、NATゲートウェイ、エンドポイント)の冒頭に付加されます（厳密には`Name`タグに登録されます）

VPCの機能を表す名称を付けておくと、あとで名前順でソートするだけで整理できて便利です。

今回は`for-web`という名前を付ける事とします

#### ・IPv4 CIDRブロック
VPC全体のネットワークアドレスをCIDR記法で指定します。

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせ、`172.16.0.0/23`を指定します。

#### ・IPv6 CIDRブロック
IPv6におけるVPC全体のネットワークアドレスを指定します

通常はIPv4のみを使用する事が多いので、「IPv6 CIDRブロックなし」を選択すると良いでしょう

#### ・テナンシー
「デフォルト」「専有」どちらかを選択します。

「専有」を選択した場合、VPC内のインスタンスには[ハードウェア専有インスタンス](https://aws.amazon.com/jp/ec2/pricing/dedicated-instances/)が適用されます (詳細は[EC2の記事 (作成中)]()で解説します)

「デフォルト」を選択した場合、ハードウェア専有インスタンスは適用されません。その分コストが安くなるので、通常はこの「デフォルト」を選択すると良いでしょう。

#### ・AZの数
VPC内のAZの数を選択する事ができます。

冗長性を確保するためには、2以上を設定する事がおすすめです ([3を選択すると可用性がさらに向上することもあるようです](https://www.itmedia.co.jp/news/articles/1908/28/news127_2.html))

また、「AZのカスタマイズ」を展開すると、具体的なAZの場所を選択できます。

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせ、「2」を選択します

#### ・パブリックサブネットの数
VPC内のパブリックサブネットの数を選択できます。デフォルトでは各AZに均等にサブネットが配置されます (冗長性確保のため)

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせ、「2」を選択します

#### ・プライベートサブネットの数
VPC内のプライベートサブネットの数を選択できます。デフォルトでは各AZに均等にサブネットが配置されます (冗長性確保のため)

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせ、「2」を選択します

#### ・サブネットCIDRブロックをカスタマイズ
作成する各サブネットのネットワークアドレスを、CIDR記法で指定できます。

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせて、4個のサブネットそれぞれのアドレスを指定します

#### ・NATゲートウェイ
[NATゲートウェイ](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#natゲートウェイ)の作成数を選択します。

「なし」を選択すると、NATゲートウェイを作成しません
「1AZ内」を選択すると、VPC内に1個のみNATゲートウェイを作成します
「AZごとに1」を選択すると、各VPCに1つずつNATゲートウェイを作成します

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせ、「なし」を選択します。
([S3用ゲートウェイエンドポイント経由でプライベートサブネット内のインスタンスもyumコマンドを実行できる](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ゲートウェイエンドポイント経由でプライベートサブネットからyumコマンド実行)ため、最低限のアップデート適用が実現できます)

NATゲートウェイはそれなりの維持費が掛かるため、プライベートサブネット内のインスタンスからyum以外のインターネットアクセスが必要な時のみ、都度作成することとします。

#### ・VPCエンドポイント
S3用の[ゲートウェイエンドポイント](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#エンドポイント-vpcエンドポイント)の作成有無を選択します。

「なし」を選択すると、ゲートウェイエンドポイントを作成しません
「S3ゲートウェイ」を選択すると、S3用のゲートウェイエンドポイントを作成します

今回は[上記構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)に合わせ、「S3ゲートウェイ」を選択します。

#### ・DNSオプション
詳細は以下を参照頂きたいですが、VPC内のパブリックIPアドレスを持つインスタンスにドメイン名でアクセス (Route53で名前解決)したい場合は、「DNSホストを有効化」「DNS解決を有効化」両方をチェックしてください

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-dns.html#vpc-dns-support

今回はWebアプリ用という用途を考慮し、「DNSホストを有効化」「DNS解決を有効化」両方をチェックします

<br>
<br>

## セキュリティグループの作成 (VPC1)
[ベストプラクティス](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ネットワークaclを使用してサブネットへのアクセスをセキュリティグループを使用してサブネット内のインスタンスへのトラフィックを制御する)に従い、ファイアウォールの役割を果たす[**セキュリティグループ**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#セキュリティグループ)を作成することで、**VPC内のネットワークセキュリティを高めます**。
(後でEC2インスタンスや起動テンプレートと[紐づける](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ec2インスタンスの作成-vpc1)必要があります)

今回は、「1. Webサーバ用のセキュリティグループ」、「2. APサーバ用のセキュリティグループ」、「3. RDS用のセキュリティグループ」を別個に作成する事とします。
(VPC作成時にデフォルトのセキュリティグループも作成されていますが、こちらは利用しません)

### 1. Webサーバ用のセキュリティグループ
セキュリティグループを作成するには、以下のように「セキュリティグループ」→「セキュリティグループの作成」を押します

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/e8698752-ba53-4f48-6115-0308722df2df.png">

セキュリティグループは、以下のような画面で作成する事ができます。

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/ca03991f-0f85-f44a-64f5-575b69d2fb10.png">

基本的には画面の指示に従い作成できますが、以下に注意が必要です

- **インバウンドルール**の「**プロトコル**」は、**対象インスタンスにアクセスする必要のあるプロトコルのみを指定**する(不要なプロトコルは指定しない)
- **インバウンドルール**の「**ソース**」は、**送信元**のAnywhere-IPv4(全送信元)、CIDRブロック、セキュリティグループ、プレフィックスリスト等を指定可能。セキュリティ的にはAnywhere-IPv4よりも**範囲を絞った方が良い**
- **アウトバンドルール**はデフォルトでは全許可。**通常はそのままでも良い**が、**高度なセキュリティ**(C&Cサーバとの通信防止等)**を実現したい場合は制限を加える**
- **セキュリティグループは見分け辛い**ので、**"Name"タグを指定した方がよい** (例えば、VPC作成時の名前タグ"for-web"と類似した名称を指定)

今回はWebサーバーとして使用するので、Web通信用のHTTP, HTTPSおよび開発用のSSH通信を許可する事とします。
最初は全てソースとしてAnywhere-IPv4を許可しますが、SSHの全許可はセキュリティ的にやや危険なため、[後ほど](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc1内のセキュリティグループ設定の修正)VPC2の範囲内のみにアクセスを絞ります。

### 2. APサーバ用のセキュリティグループ
APサーバ用に以下のようなセキュリティグループを作成します

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/03d64419-e0f6-3778-7640-2b9e5def1c36.png">

Webサーバ用と同様に、インバウンドルールのSSH、HTTP、HTTPSを許可しますが、HTTP, HTTPS通信はWebサーバとしか行わないため、ソースをWebサーバ用のセキュリティグループに変更します

上記作成が完了後、以下のように**HTTP, HTTPS通信の許可対象として自身**(APサーバ用のセキュリティグループ)**を追加**します
<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/1e4880cb-6f38-7c13-0ad7-5a23a1b28668.png">

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/5139396d-8eac-6685-7604-266b69fc2348.png">

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/caee59c9-f372-1d88-007a-d4cf26916f76.png">

本セキュリティグループには後ほどAPサーバ用インスタンスとAPサーバ用ELBを所属させますが、[前述のように](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97)**自身を許可対象に追加しないと内部のインスタンスとELB間の通信が許可されない**ため、上記操作を実施します。
(セキュリティ的にはインスタンスとELBのセキュリティグループを分けた方がより強固となりますが、Webサーバから直接APサーバにアクセスできなくなったりと開発や管理が煩雑となるため、今回は同一のセキュリティグループに所属させます)

また、1と同様に[後ほど](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc1内のセキュリティグループ設定の修正)SSH通信をVPC2の範囲内のみにアクセスを絞ります。

### 3. RDS用のセキュリティグループ
RDS用に以下のようなセキュリティグループを作成します。

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/d1009c36-2edf-fe2f-c966-caf4d1fd20ba.png">

今回はRDSのDBエンジンとしてMySQLを使用する前提で、インバウンドルールのタイプとしてMYSQL/Auroraを許可し、ソースをAPサーバ用のセキュリティグループに変更します。

PostgreSQL等**他のDBエンジンを使用する場合**は、適宜**タイプを変更**してください。

## ルートテーブルの設定 (VPC1)
本来であれば[ルートテーブル](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ルートテーブル)を作成して各サブネットや外部とのルーティングを設定する必要がありますが、[**VPCウィザード**](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpcとサブネットの作成-vpc1)を**使用してVPCを作成した場合**、デフォルトで以下のルートテーブルが設定されており、**基本的には設定変更は必要ありません**。

|対象サブネット|作成されるルートテーブルの数|ルーティング先|
|---|---|---|
|パブリックサブネット用のルートテーブル|全AZで1個|インターネットゲートウェイ、プライベートサブネット|
|プライベートサブネット用のルートテーブル|各AZあたり1個ずつ|パブリックサブネット、S3用エンドポイント、(NATゲートウェイ※)|

※今回、NATゲートウェイは作成していないためルートも設定されていない

なお、**後からNATゲートウェイやサブネットを追加**した場合、**別途ルートテーブルを作成・修正する必要**があります。NATゲートウェイでの設定例は[後述](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#参考natゲートウェイの作成)します

<br>
<br>

## EC2インスタンスの作成 (VPC1)
Webサーバ用およびAPサーバ用のインスタンスを作成します。
詳細な作成方法は割愛しますが (別途[EC2の記事]()を作成中)、以下の内容で図中の4個のインスタンス(Webサーバ用×2 + APサーバ用×2)を作成します

- 名前: "web-server-1", "web-server-2", "ap-server-1", "ap-server-2"
- AMI: Amazon Linux2 AMI (HVM)
- インスタンスタイプ: デフォルトのt2.microを選択
- キーペア: あり (作成していなければ新たに作成)
- VPC: 先ほど作成したVPCを指定
- サブネット: 作成したサブネットのうち[冒頭の構成図](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#本記事で構築するvpcの構成)でインスタンスに対応するものを選択
- パブリックIPの自動割り当て: Webサーバ用は「有効化」、APサーバ用は「無効化」
- ファイアウォール: 「既存のセキュリティグループを選択する」をチェックし、先ほど作成したWebサーバ用またはAPサーバ用から対応するセキュリティグループを選択する
- ストレージ: デフォルトの8GBのgp2を選択 ([EC2ベストプラクティス](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-best-practices.html)的には複数EBSをアタッチする事が望ましいですが、今回はデフォルト設定とします)

なお、キーペアを新たに作成した場合は、後でSSH接続に必要となりますので忘れずにローカルにダウンロードしておいてください

<br>
<br>

## フローログの作成 (VPC1)
[ベストプラクティス](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc-フローログで-amazon-cloudwatch-を使用して-ip-トラフィックを監視する)に従い、**CloudWatchにフローログを保存するよう設定**します。

IAMのポリシー設定が少し複雑なので、[IAMの記事](https://qiita.com/c60evaporator/items/0121399880625cc1de51)も併せて参照ください。

### フローログ用のCloudWatchロググループ作成
まず、CloudWatchのコンソールからロググループの作成画面に入ります。

<img width=480 alt="CloudWatchロググループ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/81b9690e-d552-b4aa-b3a8-61b500e307b1.png">

ロググループ名等を指定して、ロググループを作成します

<img width=480 alt="CloudWatchロググループ作成画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/374659d0-f869-106e-77dd-b5cc5cdb6c2e.png">

### フローログ記録用のIAMポリシー作成

IAMのコンソールへ移動し、「ポリシー」→「ポリシーを作成」をクリックします

<img width=600 alt="IAMポリシー作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/695e3fc8-2ed7-73b8-1037-9f2cfb22df38.png">

JSON形式のエディタを開き、以下のポリシーを貼り付けます

<img width=600 alt="フローログ用ポリシーJSON" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/a845b0c7-ef6c-938b-d4a4-368d8b2cb6ed.png">

```json:フローログの記録用ポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Resource": "*"
    }
  ]
}
```

必要に応じてタグを追加します（今回は追加しない）

<img width=540 alt="フローログ用ポリシーのタグ追加" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/bd4f4131-3960-83e8-1ea8-dcd3aa631e71.png">

ポリシーに名前と説明を追記して作成を完了します

<img width=540 alt="フローログ用ポリシーの名前" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/1d68e84d-96e3-3a6a-3dd1-139d68a1b2fb.png">

### フローログ記録用のロール作成

IAMコンソール画面に戻り、「ロール」→「ロールを作成」をクリックします

<img width=480 alt="IAMロールの作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/370dd370-8a43-a403-f909-504e99643e39.png">

信頼されたエンティティタイプ「AWSのサービス」、ユースケース「EC2」を選択し、次へを押します

<img width=600 alt="ロールの種類選択" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/4f93b913-142a-1139-bafa-d3533715732b.png">

先ほど作成したポリシーをアタッチします

<img width=600 alt="フローログ記録用ポリシーのアタッチ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/30dbd456-accc-c6d3-ac8e-f8839b8f60ca.png">

ロールの名称と説明を記載し、「ロールを作成」をクリックします

<img width=400 alt="ロールの種類選択" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/ea771a85-feab-c5cb-360b-0ff103e8264f.png">

<img width=600 alt="フローログ記録用ポリシーの作成完了" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/cfae4fd3-cacf-6704-f3f3-49d52fffff9f.png">

IAMコンソール画面に戻り、「ロール」→作成したロールを選択します

<img width=480 alt="作成したロールの選択" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/a15f5392-53b2-e791-d034-4703f6a4b321.png">

「信頼関係」タブ→「信頼ポリシーを編集」とクリックします

<img width=480 alt="信頼ポリシーの編集" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/257c2cbc-d67b-89d9-210a-4e2c6dc2d228.png">

元々このロールはEC2のユースケースを元に作成されているので、[信頼ポリシーの権限移譲先 ("Principal"フィールド)](https://qiita.com/c60evaporator/items/0121399880625cc1de51#1-権限移譲用のロール作成-1)もEC2が適用されていますが、これを以下のようにVPCフローログに書き換えて保存します

```json:フローログ用の信頼ポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "vpc-flow-logs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
} 
```

### フローログの作成

VPCのコンソールに戻り、該当するVPCを選択して「アクション」→「フローログを作成」をクリックします

<img width=480 alt="フローログを作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/148fe200-e2bf-29a9-a1ad-d6f016c86e43.png">

以下のようにフローログの各種設定を選択し、作成を完了させます

<img width=360 alt="フローログ作成画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/e29427c8-c449-2616-938e-71a52fed40ae.png">

以上でフローログの設定は完了です

#### ※S3にフローログを保存したい場合
CloudWatchではなく**S3にフローログを保存**し、Athenaで分析したい場合は**以下を参照**下さい

https://dev.classmethod.jp/articles/vpc-flow-logs-athena/

S3に保存した方がCloudWatchよりも[料金が安め](https://dev.classmethod.jp/articles/vpc-flow-logs-support-s3-output/)なので、コスト重視の方もS3を選択肢に入れて良いかと思います。

<br>
<br>

## ELBの作成 (VPC1)
EC2インスタンスへの通信をロードバランシングするELBを作成します。

ELBの詳細は以下の記事を参照ください

[記事作成中]()

今回は**ELBの中で最も一般的**な**ALB**を作成します。
また、本来であれば暗号化されたHTTPS通信をロードバランシングする事が望ましいですが、証明書の登録等、本記事の本筋とは外れた操作が多くなるため、今回はHTTP通信によるロードバランシングを採用します

### Webサーバ用ELBの作成
Webサーバ用インスタンスに紐づけるELBを作成します

#### ・ターゲットグループの作成
インスタンスを紐づけるためのターゲットグループを作成します。
**EC2コンソール**から「ターゲットグループ」→「ターゲットグループの作成」をクリックし、

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/f29b3e11-1d0d-f773-c6ef-f4b3c9f73958.png">

以下のようにターゲットグループの設定を指定します

<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/d312abe8-652d-7728-8b65-fb44cd674aff.png">
<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/14b723d8-ae32-48d0-4a27-c6a5358e5c36.png">

以下のようにWebサーバ用のインスタンスをターゲットグループに登録します

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/f1a06d12-b225-dcc6-f712-147fe9ff774f.png">

#### ・ロードバランサー(ALB)の作成
**EC2コンソール**から「ロードバランサー」→「ロードバランサーの作成」をクリックし、

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/56e92583-a450-65e6-f3b3-d4d16b64739b.png">

以下のようにApplication Load Balancer (ALB)を選択します

<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/259f5e4e-eb82-1fa1-f7ad-777f7e8db0db.png">

以下のようにALBの詳細設定を選択します

<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/95d98155-6653-241c-b6e2-c0d86a247f62.png">
<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/fc5e8a20-6fa1-64b6-b47e-100222397160.png">

※セキュリティグループは[Web用のEC2インスタンスに設定したもの](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#1-webサーバ用のセキュリティグループ)と同じでOKです

※「AWS Global Accelerator」をチェックすると[Global Accelerator](https://dev.classmethod.jp/articles/aws-globalaccelerator-speed-comparison/)による高速化を有料で設定できます

### APサーバ用ELBの作成

#### ・ターゲットグループの作成
[Webサーバ用ELB](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ターゲットグループの作成)と同じ方法で、APサーバ用のインスタンスをターゲットグループに登録します
（Nameタグは例えば"for-web-tg-ap"とします）

#### ・ロードバランサー(ALB)の作成
[Webサーバ用ELB](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ロードバランサーalbの作成)と同じ方法で、ロードバランサーを作成します。Webサーバ用との差として以下にご注意ください

- ロードバランサー名、NameタグはWeb用と別の名称にしてください (例: ロードバランサー名"alb-ap", Nameタグ"for-web-alb-ap")
- APサーバ用は内部のWebサーバからのリクエストのみを受け付けるため、「スキーム」に「内部」を選択してください
- サブネットはプライベートサブネットを指定してください
- セキュリティグループはAPサーバ用を指定してください
- ターゲットグループはAPサーバ用を指定してください

<br>
<br>

## RDSの作成 (VPC1)
WebアプリのDBとして使用する、RDSのインスタンスを作成します。
RDSのエンジンにはAurora、MySQL、PostgreSQL等が使用できますが、**今回はMySQLを使用**する事とします。

### サブネットグループの作成
まずはRDSを設置するサブネットを指定するため、[サブネットグループ](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html#USER_VPC.Subnets) (RDSの機能のため詳細解説は割愛します)を作成します。

**RDSのコンソール**に入り、「サブネットグループ」→「DBサブネットグループを作成」とクリックします

<img width=480 alt="サブネットグループ作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/d750389c-1a5d-a5de-4df1-0c50102e2a97.png">

以下のようにサブネットグループの設定を入力し、「作成」をクリックします

<img width=320 alt="サブネットグループの各種設定" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/5a6b25bf-57ee-b5cc-bf54-fb3b9754e037.png">

### RDSデータベースの作成
RDSのデータベースを作成します

RDSのコンソールから、「データベース」→「データベースの作成」をクリックします

<img width=480 alt="RDSデータベース作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/c4472b3b-a1bd-0dcf-8c67-e44c44d7ada4.png">

以下のようにデータベースの詳細設定を指定し、「データベースの作成」をクリック

<img width=360 alt="RDS作成時の設定1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/7b866e4f-765b-a688-26ad-dee27a137366.png">
<img width=360 alt="RDS作成時の設定2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/4e1fc641-ce6a-11ac-5351-845f0770c461.png">
<img width=360 alt="RDS作成時の設定3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/dbff33fe-e05b-2e8e-67d8-2445b5d6e215.png">

※データベース認証に「パスワードとIAMデータベース認証」を指定すると、パスワードの代わりにIAMロールの付与でDBにアクセス可能となり、セキュリティレベルが向上します([参考](https://blog.serverworks.co.jp/rds-iamdblogin))。[一方で大量アクセスには向かない方式](https://qiita.com/NewGyu/items/24cb9ba8ec5f0717e565)のためご注意ください

<br>
<br>

## S3バケットの作成 (VPC1)
非構造データを保存するための、S3 のバケットを作成します

### バケットの作成
S3のコンソールに移動し、「バケット」→「バケットを作成」とクリックします

<img width=480 alt="S3バケット作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/19227738-4a7c-25ba-6f06-79f833e7a511.png">

以下のようにバケットの詳細設定を指定し、「バケットを作成」をクリック

<img width=360 alt="S3バケット作成時の設定1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/dacf4bed-3e7a-9b75-f83d-edd64f56b543.png">

<img width=360 alt="S3バケット作成時の設定2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/4bb7bcae-cf7e-7f35-343e-34144d36e519.png">

### S3アクセス用IAMロールの付与
[後述の疎通確認④と同様の方法](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#sshの疎通確認-webサーバを踏み台にした場合)で、Webサーバを踏み台としてAPサーバ1にSSH接続し、以下コマンドでS3のバケット一覧を表示させます

```
aws s3 ls
```

恐らく以下のようなメッセージが表示され、バケット一覧の取得に失敗するかと思います (いきなり指示に従って"aws configure"コマンドで[アクセスキーを登録してはいけません](https://qiita.com/c60evaporator/items/0121399880625cc1de51#ロールを使用してアクセス許可を委任する))

```
Unable to locate credentials. You can configure credentials by running "aws configure".
```

EC2からS3にアクセスするためには、EC2インスタンスにS3へのアクセス権 (`S3FullAccess`ポリシー)を付与したロールをアタッチする必要があります。

付与方法は以下の[こちら](https://qiita.com/c60evaporator/items/0121399880625cc1de51#ロールの作成)と[こちら](https://qiita.com/c60evaporator/items/0121399880625cc1de51#ec2へのロールのアタッチ)を参照下さい

※なお、今回はEC2とS3を同アカウントで作成しているので、バケットポリシーでの明示的な許可は不要です

## 各インスタンスへの疎通確認 (VPC1)
以上でVPC1の作成は完了です。現時点では以下のようなネットワークが構築されているはずです

<img width=640 alt="構築するVPC構成図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/bf6ebdc3-7ec7-d7b2-d977-f0dbbce4f0b0.png">

このネットワークが、**想定通り設定できているか疎通確認**します。

具体的には、以下の内容を確認します

①外部からWebサーバへSSH通信できる※
②外部からWebサーバへHTTP通信できる
③外部からWebサーバへELB経由でHTTP通信できる
④WebサーバからAPサーバへSSH通信できる※
⑤WebサーバからAPサーバへHTTP通信できる
⑥WebサーバからAPサーバへELB経由でHTTP通信できる
⑦外部からAPサーバへELB経由でHTTP通信できない
⑧APサーバからRDS内のデータを取得できる
⑨APサーバからS3内のデータを取得できる

<img width=640 alt="VPC1疎通確認" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/5cad8587-0a43-a880-b5b6-4a5381e25e13.png">

※なお、①のSSH通信は[VPC2作成後](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc1内のセキュリティグループ設定の修正)には通信不可となるよう再設定する (外部からSSH接続できるのはやや危険なため)のでご注意ください。同様に④もVPC2作成後に遮断します

### Webサーバへの疎通確認
#### ①SSHの疎通確認
以下の手順でWebサーバ用EC2インスタンス1 ("web-server-1")のグローバルIPアドレスを確認します

![スクリーンショット 2022-07-10 14.45.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/33350755-2b46-3f8f-d09b-582a27ee62ce.png)

ターミナル(Mac)やコマンドプロンプト(Windows)から、以下のようなSSH接続コマンドを打ちます

```
ssh ec2-user@[インスタンスのIPアドレス] -i [ダウンロードしたキーペア秘密鍵のパス]
```

以下のようなメッセージが出てきたら「yes」と入力してEnterを押してください

```
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```

以下のようにAmazon Linuxの起動マークが表示されたら成功です

```
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
```

同様の操作をWebサーバ用インスタンス2 ("web-server-2")にも実行し、疎通確認します 

#### ②HTTPの疎通確認 (直接通信)
HTTPの疎通確認にはcurlコマンドを使用する等の方法もありますが、今回はWebアプリの実際の動作を想定し、ブラウザでHTMLファイルを表示できるかで疎通確認をします。

まず、Webサーバ用インスタンス1にSSHでインスタンスに接続した状態で以下コマンドでApache HTTP Server (httpd)をインストールします (nginxを使用したい場合はこちらでもOKです)

```
sudo yum update -y
sudo yum install httpd -y
```

以下コマンドで、Webページ表示用のindex.htmlを作成します

```
cd /var/www/html
sudo nano index.html
```

以下の内容を記述し、ctrl + x で保存します

```index.html
<html><h1>Web server 1</h1></html>
```

以下のコマンドを打ち、Apache HTTP Serverによるホスティングをスタートさせます

```
sudo systemctl start httpd
```

以下のコマンドで再起動後もホスティングを自動実行するようにします

```
sudo systemctl enable httpd
```

Chrome等のブラウザを起動して、`http://Webサーバ用インスタンス1のIPアドレス`とアドレス欄に打ってEnterを押し、以下のように表示されれば成功です

<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/48f2890d-17d5-8b28-567b-05ac3814682b.png">


同様の操作をWebサーバ用インスタンス2 ("web-server-2")にも実行し、疎通確認します (index.htmlの中身を"Web server 2"に変えておいてください)
以下のようにブラウザに表示されれば成功です

<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/f27b0b8a-b0a4-f111-dd9c-4ca4c09fdfe1.png">

#### ③HTTPの疎通確認 (ELB経由)
②ではIPアドレスを指定して各Webサーバ用インスタンスに直接アクセスしましたが、実運用時と同様にELB経由でのアクセスも確認します。

②が完了している状態 (httpdのインストールindex.htmlファイルの設置済)で、
**EC2コンソール**から「ロードバランサー」→ Webサーバ用のELBを選択 → DNS名をコピペします

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/3df6e3b2-f8e0-bae5-7a1f-d7146fb3dfd0.png">

ブラウザのアドレス欄に貼り付けてEnterを押し (あるいは先頭にhttpをつけて`http://コピペしたDNS名`とする)、②の時と同様に以下のように表示されれば成功です
(`Web server 1`、`Web server 2`どちらが表示されてもOKです)

<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/48f2890d-17d5-8b28-567b-05ac3814682b.png">

F5 (Macならctrl + R)でブラウザを何度か更新し、`Web server 1`と`Web server 2`でランダムに切り替わっていればELBが正しく機能しています

### APサーバへの疎通確認
#### ④SSHの疎通確認 (Webサーバを踏み台にした場合)
APサーバ用インスタンス"ap-server-1"は**プライベートサブネット上**に存在するため、**外部から直接アクセスする事ができません**。よってAPサーバにアクセスするためには、**パブリックサブネット上**のWebサーバ用**インスタンスを踏み台とする必要があります**

まずはWebサーバ1用インスタンス"web-server-1"にキーペア秘密鍵を送ります (秘密鍵なので流出には気を付けてください)。これがないと公開鍵認証ができず、APサーバにアクセスできません

```
scp -i [ダウンロードしたキーペア秘密鍵のパス] [ダウンロードしたキーペア秘密鍵のパス] ec2-user@[Webサーバ1のIPアドレス]:~/.ssh
```

①と同様にWebサーバ1用インスタンスにSSH接続します

```
ssh ec2-user@[Webサーバ1のIPアドレス] -i [ダウンロードしたキーペア秘密鍵のパス]
```

以下コマンドで、アップロードした秘密鍵が格納されている事を確認します

```
ls .ssh
```

以下コマンドで、APサーバ1にSSH接続します

```
ssh ec2-user@[APサーバ1のプライベートIPアドレス] -i [アップロードしたキーペア秘密鍵のパス]
```
※APサーバ1のプライベートIPアドレスは、EC2コンソールの「インスタンス」→APサーバ1用インスタンスIDをクリック→「プライベート IPv4 アドレス」に記載されています

以下のようにAmazon Linuxの起動マークが表示されたら成功です

```
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
```

#### ⑤HTTPの疎通確認 (直接通信)
WebサーバからAPサーバへのHTTP通信を確認します。
②ではブラウザを使用しましたが、今回はcurlコマンドで確認します。

まずは④でAPサーバにSSH接続した状態で、[②と同様に](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#httpの疎通確認-直接通信)httpdのインストールindex.htmlファイルの作成を以下のように実施します。

```:httpdのインストールとindex.htmlファイルの作成コマンド
sudo yum update -y
sudo yum install httpd -y
cd /var/www/html
sudo nano index.html
```

```index.html
<html><h1>AP server 1</h1></html>
```

```:httpdの開始と再起動後の有効化
sudo systemctl start httpd
sudo systemctl enable httpd
```

※NATゲートウェイがないのにyum経由でインストールできるのが少し不思議ですが、[前述のように](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ゲートウェイエンドポイント経由でプライベートサブネットからyumコマンド実行)S3用ゲートウェイエンドポイント経由でyumによるネットワーク接続が可能です)

以下コマンドでAPサーバへのSSH接続を切断し、Webサーバに戻ります

```
exit
```

以下curlコマンドで、WebサーバからAPサーバにHTTPリクエストを送ります

```
curl http://[APサーバのIPアドレス]
```

以下のように先ほど作成したindex.htmlファイルの内容が表示されれば成功です

```
<html><h1>AP server 1</h1></html>
```

同様の操作をAPサーバ2"ap-server-2"にも実行(index.htmlのヘッダは"AP server 2"と記載しておく)し、以下のようにindex.htmlファイルの内容が表示されれば成功です

```
<html><h1>AP server 2</h1></html>
```

#### ⑥HTTPの疎通確認 (ELB経由)
Webサーバ用インスタンスからAPサーバ用インスタンスへのAPサーバ用ELB経由でのHTTPアクセスも確認します。

まずはEC2コンソールから「ロードバランサー」→ APサーバ用のELBを選択 → DNS名をコピペします

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/7f456718-e07e-ce32-2960-484af4e6bb96.png">

WebサーバにSSH接続した状態で、以下コマンドでELBにHTTPリクエストを送信します

```
curl http://コピペしたDNS名
```

以下のようにAPサーバ内のindex.htmlファイルの内容が表示されれば成功です
(`AP server 1`、`AP server 2`どちらが表示されてもOKです)

```
<html><h1>AP server 1</h1></html>
```

同じコマンドを何度か実行し、`AP server 1`、`AP server 2`でランダムに切り替わっていればELBが正しく機能しています

#### ⑦外部からのHTTPの非疎通確認 (ELB経由)
⑥ではWebサーバからAPサーバへのELB経由へのアクセスを確認しました。

一方で、**外部からAPサーバへアクセスできてしまうとセキュリティ的にまずい**ので、外部からAPサーバ用ELB経由でインスタンスにHTTPアクセス**できない**ことを確認します

外部から(WebサーバにSSH接続していない状態で)、以下コマンドを打ちます

```
curl http://コピペしたDNS名
```

APサーバ内のindex.htmlファイルの内容が**帰ってこなければ**成功です。

### RDSへの疎通確認
#### ⑧APサーバからRDSへの疎通確認
[④と同様](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#sshの疎通確認-webサーバを踏み台にした場合)に、Webサーバを踏み台としてAPサーバ1にSSH接続します。

APサーバ1に入ったら、以下コマンドでmysqlをインストールします (疎通確認のみに使用するので、確認が完了したらアンインストールしても構いません)

```
sudo yum install mysql -y
```

以下コマンドでRDSのMySQLにアクセスできるか確認します

```
mysql -h [RDSのエンドポイント名] -u [RDSのユーザ名] -p
```

なお、RDSのエンドポイント名はRDSコンソール→「データベース」→該当するデータベースのDB識別子をクリックし、以下から確認できます

<img width=480 alt="RDSのエンドポイント名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/c00adb96-b897-633f-81ff-63be797715e9.png">

RDSのパスワードが求められるので入力し、以下のようにMySQLコマンドが打てる状態となれば成功です

```
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 39
Server version: 8.0.28 Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> 
```

APサーバ2でも同様の操作を実行します


### S3への疎通確認
#### ⑨APサーバからS3への疎通確認
[④と同様に](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#sshの疎通確認-webサーバを踏み台にした場合)、Webサーバを踏み台としてAPサーバ1にSSH接続し、以下コマンドでAWS CLIの初期設定を行います ([**アクセスキーは入力しないでください**](https://qiita.com/c60evaporator/items/0121399880625cc1de51#ロールを使用してアクセス許可を委任する))

```
aws configure
```

```
AWS Access Key ID [None]: 空欄のままEnter
AWS Secret Access Key [None]: 空欄のままEnter
Default region name [None]: ap-northeast-1
Default output format [None]: 空欄のままEnter
```

以下コマンドでバケット一覧を表示され、作成したS3バケットが表示されればOKです

```
aws s3 ls
```

```:表示内容の例
2022-08-08 00:24:28 for-web-bucket
```

以上でVPC1 (Webアプリ用のVPC)の作成は完了です

<br>
<br>

## VPCとサブネットの作成 (VPC2)
**ここからはVPC2** (社内ネットワークを模擬したVPC)の作成に移ります。

まず、[VPCとサブネットの作成 (VPC1)](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpcとサブネットの作成-vpc1)と同様に、**VPCウィザードを使用してVPCを作成**します。
以下の設定でVPCを作成して下さい

- 作成するリソース: VPCなど
- 名前タグの自動生成: "for-internal"と名前を付ける
- IPv4 CIDRブロック: 172.16.2.0/24
- IPv6 CIDRブロック: IPv6 CIDRブロックなし
- テナンシー: デフォルト
- AZの数: 1 (社内ネットでも冗長性を確保したい方は2を選択して下さい)
- AZのカスタマイズ: ap-northeast-1a
- パブリックサブネットの数: 1
- プライベートサブネットの数: 1
- サブネットCIDRブロックをカスタマイズ: パブリックは172.16.2.0/26、プライベートは172.16.2.64/26を指定
- NATゲートウェイ: なし
- VPCエンドポイント: なし (S3アクセスの利便性を上げたい場合は「S3ゲートウェイ」を指定してもOK)
- DNSオプション: 「DNSホスト名を有効化」「DNS解決を有効化」両方チェックする

<img width=720 alt="VPC2作成ウィザード" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/6299b111-5834-4c3a-17ac-0e519ead2dbb.png">

<br>
<br>

## セキュリティグループの作成 (VPC2)
### 1. プロキシサーバ用のセキュリティグループ
セキュリティグループを作成するには、[VPC1のとき](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#セキュリティグループの作成-vpc1)と同様VPCコンソールから「セキュリティグループ」→「セキュリティグループの作成」を押します

プロキシサーバ用に以下のようなセキュリティグループを作成します

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/68c3078d-174b-d445-090b-c92a42a433f6.png">

インバウンドは初期設定用にSSHのみ全許可し、アウトバウンドはデフォルトのまま全許可とします。

SSHの全許可はセキュリティ的にやや危険なため、[VPN接続の確立後](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#セキュリティグループの修正)にインバウンドの許可を内部ネットワーク (プライベートサブネット + VPN)に限定します。
これにより、社内ネットワークからしかアクセスできないセキュアなネットワークを構築する事ができます。

### 2. 開発用サーバ用のセキュリティグループ
開発用サーバ用に以下のようなセキュリティグループを作成します

<img width=720 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/08567ba6-6102-ed5d-28d4-90a7e74caf4b.png">

インバウンドは初期設定用にプロキシサーバ用セキュリティグループからのSSHのみ許可 (プロキシサーバが踏み台の役割を果たす)し、アウトバウンドはデフォルトのまま全許可とします。

こちらもプロキシサーバ用セキュリティグループと同様、[VPN接続の確立後](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#セキュリティグループの修正)にインバウンドのSSH通信許可をVPNに限定します。

<br>
<br>

## EC2インスタンスの作成 (VPC2)
プロキシサーバ用および開発用サーバ用のインスタンスを作成します。

[VPC1のとき](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ec2インスタンスの作成-vpc1)と同様に、以下の内容で図中の2個のインスタンス(プロキシサーバ用×1 + 開発用サーバ用×1)を作成します
名前: "proxy-server-1", "development-server-1"
AMI: Amazon Linux2 AMI (HVM)
インスタンスタイプ: デフォルトのt2.microを選択
キーペア: あり (VPC1と同じものを指定。セキュリティを高めたいなら新たに作成してもOK)
VPC: 先ほど作成したVPC2を指定
サブネット: 作成したサブネットのうち冒頭の構成図でインスタンスに対応するものを選択
パブリックIPの自動割り当て: プロキシサーバ用は「有効化」、開発用サーバ用は「無効化」
ファイアウォール: 「既存のセキュリティグループを選択する」をチェックし、先ほど作成したプロキシサーバ用または開発用サーバ用から対応するセキュリティグループを選択する
ストレージ: デフォルトの8GBのgp2を選択 (EC2ベストプラクティス的には複数EBSをアタッチする事が望ましいですが、今回はデフォルト設定とします)

<br>
<br>

## VPCピアリングの作成 (VPC2)
**VPC2からVPC1への接続路**を確保するため、[**VPCピアリング**](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#vpcピアリング)を作成します

VPCコンソールから「ピアリング接続」→「ピアリング接続を作成」とクリックします

<img width=480 alt="VPCピアリング作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/3b7dd9af-0916-c202-074d-d14bf4c9eece.png">

以下のようにピアリング接続の詳細設定を入力し、「ピアリング接続を作成」をクリックします

<img width=400 alt="VPCピアリング作成時設定" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/9c234312-53dd-4981-1882-2fa1c9aefa69.png">

VPCコンソールに戻り、「ピアリング接続」タブで作成したピアリング接続を選択肢、「アクション」→「リクエストを承諾」をクリックします

<img width=600 alt="VPCピアリング作成時設定" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/d331eaff-5ab2-4a74-39c3-6c01a40f5a17.png">

<br>
<br>

## ルートテーブルの設定 (VPC2)
[VPC1のとき](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#ルートテーブルの設定-vpc1)と同様、VPC作成時にデフォルトで以下のルートテーブルが設定されており、**同一VPC内での通信**に関しては**ルートテーブルの変更は必要ありません**。

|対象サブネット|作成されるルートテーブルの数|ルーティング先|
|---|---|---|
|パブリックサブネット用のルートテーブル|全AZで1個|インターネットゲートウェイ、プライベートサブネット|
|プライベートサブネット用のルートテーブル|各AZあたり1個ずつ|パブリックサブネット、(NATゲートウェイ、S3用エンドポイント※)|

※今回はNATゲートウェイ、エンドポイントは作成していないためルートも設定されていない

一方で、**VPC2→VPC1へのルートはデフォルトでは設定されていない**ため。ルートテーブルで**VPCピアリングへのルートを明示的に追加する必要**があります。

今回はVPC2上の開発用サーバからVPC1のWebサーバおよびAPサーバにアクセスできるよう、ルートテーブルを修正します。

### VPC2→VPC1へのルート
開発用サーバが所属するVPC2のプライベートサブネットから、VPCピアリングへのルートを追加します。

まず、VPCコンソールの「ルートテーブル」→VPC2のプライベートサブネット用ルートテーブルをクリックします

<img width=400 alt="VPC2のプライベートサブネット用ルートテーブル" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/7cd73095-7426-cb99-7863-fb479789dc7c.png">

以下のようにVPCピアリングへのルートが存在しない事が分かるので、「ルートを編集」をクリックします

<img width=600 alt="ルート編集" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/98a024f2-82db-bb3e-2763-c2c0fb1866d5.png">

送信先がVPC1のCIDR (172.16.0.0/23)のとき、VPCピアリング接続にルーティングされるよう以下のようにルートを追加します

<img width=600 alt="VPC2から1へのルート修正" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/16992cfe-bd8a-bea4-8e21-48c0f6e4865d.png">

### VPC1→VPC2へのルート
忘れがちなのがこの部分で、ルートテーブルの指定は[ステートレス](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#ステートレス)のため、**戻り方向のルートも明示的に指定する必要**があります

今回はVPC1の全てのサブネット (WebサーバおよびAPサーバ)にVPC2 (開発用サーバ)からアクセスできるようにしたいので、VPC1以下の3つ (パブリック用 + プライベート用x2)のルートテーブルにVPC2への戻りルートを設定します。

<img width=600 alt="VPC1のルートテーブル一覧" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/16fa758a-3b10-e193-e6b6-98caae2af83d.png">

上記3つのルートテーブル全てに、送信先がVPC2のCIDR (172.16.2.0/24)のとき、VPCピアリング接続にルーティングされるよう以下のルートを追加します

<img width=600 alt="VPC1から2へのルート修正" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/23029c70-6522-eb9d-c2e3-d5525b9d9b01.png">

<br>

### VPC1内のセキュリティグループ設定の修正
VPCピアリングの作成とルートテーブルの修正を実施しましたが、このままでは**VPC1のセキュリティグループでVPC2からのアクセスが許可されていない**ので、アクセスを**許可する修正**が必要です。
また[前述のように](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#1-webサーバ用のセキュリティグループ)外部からWebサーバにSSH接続できる状態はセキュリティ的にやや弱いので、Webサーバ用およびAPサーバ用のセキュリティグループを修正し、VPC2内の開発用サーバのみからアクセスできるようにします。

VPCコンソールから「セキュリティグループ」タブをクリックし、以下の2つのセキュリティグループを修正します

<img width=480 alt="VPC1セキュリティグループ修正" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/41036803-24a4-022f-a15b-3a2af9255cd3.png">

#### 1. Webサーバ用セキュリティグループの修正
インバウンドルールのSSHのソースを、VPC2のプライベートサブネットのCIDR (172.16.2.64/26)に限定します

<img width=600 alt="Webサーバ用セキュリティグループ修正" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/9d63ba75-a038-2a0b-1f10-09aee415a1f2.png">

#### 2. APサーバ用セキュリティグループの修正
Webサーバ用と同様に、インバウンドルールのSSHのソースを、VPC2のプライベートサブネットのCIDR (172.16.2.64/26)に限定します

<img width=600 alt="APサーバ用セキュリティグループ修正" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/fec332bd-92a2-b105-bbe3-e1685d9ce28b.png">

<br>

### 疎通確認
VPCピアリング・ルーティング・セキュリティグループが正しく設定できているか確認するため、作成したEC2インスタンスおよびVPC1にアクセスできるか疎通確認します。

#### ・VPC2内のインスタンスへの疎通確認
まず、ローカルから以下のコマンドでプロキシサーバ用インスタンスにSSH接続します

```
ssh ec2-user@[プロキシサーバのパブリックIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

接続できたら、いったん`exit`コマンドで接続を切断し、以下のコマンドでプロキシサーバ用インスタンスにキーペア秘密鍵を送ります

```
scp -i [ローカルのキーペア秘密鍵のパス] [ローカルのキーペア秘密鍵のパス] ec2-user@[プロキシサーバのパブリックIPアドレス]:~/.ssh
```

キーペア秘密鍵を送信できたら、再び以下コマンドでプロキシサーバ用インスタンスにSSH接続します

```
ssh ec2-user@[プロキシサーバのパブリックIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

ここから以下のコマンドで開発用サーバ用インスタンスにSSH接続します

```
ssh ec2-user@[開発用サーバのプライベートIPアドレス] -i [プロキシサーバ内のキーペア秘密鍵のパス]
```

※開発用サーバのプライベートIPアドレスは、EC2コンソールの「インスタンス」→開発用サーバ用インスタンスIDをクリック→「プライベート IPv4 アドレス」に記載されています

Amazon Linuxのロゴが表示されたら成功です

#### ・VPC1への疎通確認
開発用サーバからVPCピアリング経由でVPC1（WebサーバおよびAPサーバ）にSSH接続できるか確認します。

まず開発用サーバにキーペア秘密鍵を送る必要があるため、**プロキシサーバに接続した状態**で以下コマンドを実行します

```
scp -i [プロキシサーバ内のキーペア秘密鍵のパス] [プロキシサーバ内のキーペア秘密鍵のパス] ec2-user@[開発用サーバのプライベートIPアドレス]:~/.ssh
```

以下コマンドで再度開発用サーバ用インスタンスにSSH接続します

```
ssh ec2-user@[開発用サーバのプライベートIPアドレス] -i [プロキシサーバ内のキーペア秘密鍵のパス]
```

以下コマンドで、**VPC1**のAPサーバ1にSSH接続します

```
ssh ec2-user@[APサーバ1のプライベートIPアドレス] -i [開発用サーバ内のキーペア秘密鍵のパス]
```

Amazon Linuxのロゴが表示されれば接続成功です！

開発用サーバに戻り以下コマンドで、**VPC1**のWebサーバ1にSSH接続します

```
ssh ec2-user@[Webサーバ1のプライベートIPアドレス] -i [開発用サーバ内のキーペア秘密鍵のパス]
```

Amazon Linuxのロゴが表示されれば接続成功です！
同様にWebサーバ2、APサーバ2についても疎通確認して下さい。

<br>
<br>

## プロキシサーバの設定 (VPC2)
VPC2のプロキシサーバにプロキシとしての機能を持たせるため、プロキシサーバーソフト[Squid](https://ja.wikipedia.org/wiki/Squid_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))をインストールします

プロキシサーバにSSH接続した状態で、以下コマンドでSquidをインストールします([参考](https://dev.classmethod.jp/articles/squid-proxy-setup/))

```
sudo yum update -y
sudo yum install squid -y
```

以下のコマンドで再起動後も自動実行するようにします

```
sudo systemctl enable squid
sudo systemctl restart squid
```

Squidがポート3128を使用していることを確認します。

```
sudo lsof -i:3128
```

```:正常時の表示例
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
squid   3598 squid   11u  IPv6  25329      0t0  TCP *:squid (LISTEN)
```

### プロキシサーバ用セキュリティグループの修正
[先ほど設定したプロキシサーバ用セキュリティグループ](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#1-プロキシサーバ用のセキュリティグループ)ではSSH通信のみの通信が許可されており、それ以外の通信は許可されていません。
本プロキシサーバーは開発用サーバからのHTTP, HTTPS通信を中継する役割を果たすため、これらの通信をセキュリティグループで許可する必要があります。

ここで注意すべきが、Squidでのプロキシ使用時のポート(3128)は通常のポート(HTTP: 80, HTTPS:443)と異なる事です。
このような**特殊なポートを使用する場合**、セキュリティグループの「タイプ」は通常の「HTTP」「HTTPS」ではなく、「**カスタムTCP**」を選択して直接ポートを指定する必要があります

以下のように**プロキシサーバ用セキュリティグループのインバウンドルールを修正**します

<img width=720 alt="プロキシサーバ用セキュリティグループ修正" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/374ff66e-0e3a-97b4-59e7-22c17970f0cd.png">


### プロキシサーバの動作確認
プロキシサーバ経由で開発用サーバ (プライベートサブネット)からインターネットにアクセスできる事を確認します。

[先ほどと同様](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc2内のインスタンスへの疎通確認)に、プロキシサーバを踏み台として開発用サーバにSSH接続し、以下のコマンドを打ちます
(`-x`オプションでプロキシを指定します)

```
curl http://www.example.com -x http://[プロキシサーバのプライベートIPアドレス]:3128
```

※プロキシサーバはパブリックでなくプライベートのIPアドレスを指定する事にご注意下さい

`http://www.example.com`から以下のようなHTMLが返って来れば成功です

```html
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
:
以下略
```

<br>
<br>

## VPNの作成 (VPC2)
VPC2はオンプレの社内ネットワークと一体化して運用することを想定しているため、**オンプレとのセキュアな通信路を確保**するために**VPNを使用**します。

AWSでVPNを使用するためには主に[Site-to-Site VPN](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#site-to-site-vpn-サイト間のvpn接続)と[クライアントVPN](https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77#クライアントvpn)が存在しますが、今回はオンプレルータ側の設定が不要で**導入が簡易**な(ノートPC等にもインストールできる)**クライアントVPN**を使用します。

以下の公式チュートリアルに従い、クライアントVPNの構築を進めます

https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/cvpn-getting-started.html


### 証明書とキーの発行
VPNはセキュアな通信路を確保するという特性上、**認証**を実施する必要があります。

Client VPNでは認証方法としてActive Directory (AD) または相互認証 (公開鍵証明書によるクライアント認証とサーバ認証)を利用する事ができますが、今回は個人でも簡単に実行可能な**OpenVPN easy-rsaによる相互認証**を採用します ([公式チュートリアルに準じた方法](https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/client-authentication.html#mutual))

#### ・OpenVPN easy-rsaとは？
セキュリティ的に強固なシステムを構築するためには、認証に使用する証明書(SSL証明書)は信頼できる認証局(CA)から購入する必要があります。

一方で個人や小規模組織では、**個人でCAを構築して発行された証明書**、いわゆる「**オレオレ証明書**」が使用されることも多いです (当然ながらセキュリティレベルは落ちるので、業務用であればオレオレ証明書でなく信頼できる証明書を取得してください)

この個人で**認証局を立ててオレオレ証明書を発行できるツール**の一つが、OpenVPN easy-rsaです。

#### ・OpenVPN easy-rsaのインストール
ローカル内の適当なフォルダに入り、以下コマンドでOpenVPN easy-rsaをダウンロードします

```
git clone https://github.com/OpenVPN/easy-rsa.git
```

#### ・証明書とキーの発行
OpenVPN easy-rsaをダウンロードしたフォルダに入り、以下コマンドでPKI基盤 (公開鍵証明書の運用に必要な認証局、証明書等のセット)を初期化します

```
cd easy-rsa/easyrsa3
./easyrsa init-pki
```

以下コマンドで認証局 (CA)を構築します (途中進めるか聞かれたら"yes"と入力します)

```
./easyrsa build-ca nopass
```

以下コマンドでサーバー証明書とキーを生成します

```
./easyrsa build-server-full server nopass
```

以下コマンドでクライアント証明書とキーを生成します

```
./easyrsa build-client-full client1.domain.tld nopass
```

生成したファイルを以下のコマンドで1つのフォルダに集めます

```
mkdir 送信先フォルダのパス
cp pki/ca.crt 送信先フォルダのパス
cp pki/issued/server.crt 送信先フォルダのパス
cp pki/private/server.key 送信先フォルダのパス
cp pki/issued/client1.domain.tld.crt 送信先フォルダのパス
cp pki/private/client1.domain.tld.key 送信先フォルダのパス
cd 送信先フォルダのパス
```

※各ファイルは以下の意味を持ちます

- ca.crt: ルートCAの証明書
- server.crt: サーバー証明書
- server.key: サーバーの秘密鍵(キー)
- client1.domain.tld.crt: クライアント証明書
- client1.domain.tld.key: クライアントの秘密鍵(キー)

### 証明書とキーのACMへのアップロード
サーバー証明書とキー、およびクライアント証明書とキーを ACM にアップロードします。

<img width=600 alt="ACM証明書インポート" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/1319151a-f18b-cb2d-2021-8379c6420125.png">

#### ・サーバー証明書とキーのアップロード
開いた証明書(server.crt)、キー(server.key)、証明書チェーン(ca.crt)を貼り付けます

<img width=360 alt="サーバー証明書インポート" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/c062fad4-5945-d3e6-d6c1-e3ad8ca3f180.png">

貼り付ける証明書やCAの内容の確認方法ですが、以下のようにnanoエディタ等 (Windowsではメモ帳等)で開いて下の方に記載されている`-----BEGIN CERTIFICATE-----`から`-----END CERTIFICATE-----`の部分をコピペすると便利です

```
cd 証明書が格納されているフォルダ
nano server.key
```

<img width=320 alt="サーバー証明書nanoエディタ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/93457240-9e82-11f3-fbb6-e42d9dfb2760.png">

同様にプライベートキーでは`-----BEGIN PRIVATE KEY-----`から`-----END PRIVATE KEY-----`までをコピペします。

必要に応じてタグを追加し、「次へ」を押します

<img width=360 alt="サーバー証明書インポート時タグ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/0d925740-702a-8a8b-ebff-6f7513abe2e3.png">

「インポート」をクリックしてインポートを完了させます

<img width=360 alt="サーバー証明書インポート完了" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/6343683b-16c5-5a1e-a490-efdfedadccad.png">

#### ・クライアント証明書とキーのダウンロード
サーバとは別に、同様の方法でクライアント証明書(server.crt)、キー(server.key)、証明書チェーン(ca.crt)の内容をアップロードします

### クライアントVPNエンドポイントの作成
VPC側のVPNの出口となる、**クライアントVPNエンドポイント**を作成します。

VPCコンソールから「クライアントVPNエンドポイント」→「クライアントVPNエンドポイントを作成」をクリックします

<img width=400 alt="クライアントVPNエンドポイント作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/bbde64c2-3178-bfeb-3d56-0b67372dbfba.png">

以下のように設定を指定し、クライアントVPNエンドポイントの作成を完了させます
(クライアント側のCIDRブロックは/22より大きい(数字が小さい)必要がある事にご注意下さい。今回は172.16.4.0/22を指定します)

<img width=360 alt="クライアントVPNエンドポイント作成画面1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/3794d1e8-78cf-4038-4944-347d1c0ee4cd.png">
<img width=360 alt="クライアントVPNエンドポイント作成画面2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/1f6c6eb7-b23a-ab4d-88b0-3c0a988d0e97.png">

作成したクライアントVPNエンドポイントを選択し、以下の操作でVPC2のプライベートサブネットをターゲットネットワークとして紐付けます

<img width=480 alt="クライアントVPNエンドポイント選択" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/a3b18654-2bf3-c58b-fa2c-0856e95c5bf7.png">

<img width=480 alt="ターゲットネットワーク関連付け1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/be0b0cd3-3b02-491a-adb1-0239c59ac698.png">

<img width=400 alt="ターゲットネットワーク関連付け2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/5e4c4a25-39e2-3a25-9ad9-f6eab08332e1.png">

### 認証ルールの追加
クライエントVPNでは、**セキュリティグループとは別に**VPNからVPCへの**アクセスを明示的に許可する必要**があります。これを実現するのが「認証ルール」です (「認証」と名前が付いていますが実際は認可です)

先ほどと同様にクライアントVPNエンドポイントを選択し、「承認ルール」→「認証ルールを追加」をクリックします

<img width=400 alt="認証ルールの追加1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/2c9d5f5b-d287-c0e1-47b7-e59bcdfe539f.png">

VPC2のCIDR(172.16.2.0/24)へのアクセスを有効化します。

<img width=400 alt="認証ルールの追加2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/1c551ac8-6136-0924-bff9-355668c299b0.png">


### セキュリティグループの修正
上記操作でVPN接続自体は確立できますが、現状のセキュリティグループはVPNからの通信を想定した設定となっていないため、一部の通信が拒否されてしまいます。

よって、VPNからの通信(開発用サーバ、プロキシサーバ両方へのSSH接続、およびプロキシサーバへのプロキシ接続)を許可するようセキュリティグループを修正します。

VPC側から見て、**VPNからの通信はクライアントVPNエンドポイントがソースとみなせる**ので、この事を念頭に設定を修正します。

#### ・クライアントVPNエンドポイント用セキュリティグループの作成
クライアントVPNエンドポイントをデフォルト設定で作成すると、VPCデフォルトのセキュリティグループが紐づけられます。
クライアントVPNエンドポイントはあくまで通信の経由点で通信の最終目的地となる事はないので、紐付けるセキュリティグループで明示的にインバウンド通信を許可する必要はありませんが、**以下の目的で専用のセキュリティグループを作成して紐付けます**

- 他のセキュリティポイントのインバウンドルールのソース設定用
- VPCデフォルトのセキュリティグループの設定変更時に思わぬ影響が出る事を防ぐ

以下のように、**インバウンド・アウトバウンドルール共にデフォルト設定のままセキュリティグループを作成**します。

<img width=600 alt="クライアントVPNエンドポイント用セキュリティグループの作成" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/4846690c-0820-3022-ba82-372fde369f91.png">

「クライアントVPNエンドポイント」タブに戻り、該当するクライアントVPNエンドポイントを選択した状態で「セキュリティグループを適用」をクリックします

<img width=720 alt="クライアントVPNエンドポイント用セキュリティグループの紐付け" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/28707c27-431d-10cf-cf42-fcb1a48645ad.png">

作成したセキュリティグループを選択して適用します

<img width=400 alt="クライアントVPNエンドポイント用セキュリティグループの適用" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/ad5e10da-801e-1f3f-970e-1ffdf4858c27.png">


#### ・開発サーバ用セキュリティグループの修正
[開発用サーバのセキュリティグループ](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#2-開発用サーバ用のセキュリティグループ)は、現状ではプロキシサーバ用のセキュリティグループからのSSH通信のみが許可されています。よってVPNからSSH接続を行うためには、クライアントVPNエンドポイントからのインバウンド許可設定を追加する必要があります。

**以下のようにソースがクライアントVPNエンドポイント用セキュリティグループのSSH通信を許可**する設定を、開発サーバ用セキュリティグループのインバウンドルールに追加します

<img width=720 alt="開発サーバ用インバウンドルールにVPNを追加" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/82472872-c39c-6be2-47bb-c361727de19a.png">

#### ・プロキシサーバ用セキュリティグループの修正
プロキシサーバに関しては、SSH通信に加えて、[先ほど追加したプロキシ通信用のポート3128のインバウンドルール](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#プロキシサーバ用セキュリティグループの修正)も許可対象に加える必要があります (VPN経由でインターネットに接続できるようにするため)

また、元々全許可となっていたSSH通信の設定はセキュリティ的に脆弱なため、開発サーバ (および上記のVPN)のみにソース範囲を絞るよう変更します。

以下のように**ソースがクライアントVPNエンドポイント用セキュリティグループのSSH通信およびカスタムTCPポート3128の通信を許可**する設定を、開発サーバ用セキュリティグループのインバウンドルールに追加します

<img width=720 alt="プロキシサーバ用インバウンドルールにVPNを追加" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/cef1dd87-feb2-dd38-3381-a065389448a1.png">

上記変更により、**VPC2への接続ルートがVPN経由に絞られる** (インターネットから直接SSH接続できなくなる)ため、よりセキュアなネットワークを実現する事ができます。


### クライアントVPNエンドポイント設定ファイルのダウンロード
**AWS側**のクライアントVPNエンドポイントと**ローカル側**のVPNクライアントソフトを**連携**させるため、**クライアントVPNエンドポイント設定ファイルをダウンロード**します。

「クライアントVPNエンドポイント」タブに戻り、該当のクライアントVPNエンドポイントを選択して「クライアント設定をダウンロード」をクリックします

<img width=720 alt="クライアントVPNエンドポイント設定ファイルダウンロード" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/147c556a-e97a-1dbe-aeff-d27313b6b3ed.png">

<img width=400 alt="クライアント設定をダウンロード" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/c0278ec7-39bb-8bed-6c8a-eac5846bae7b.png">

ダウンロードしたdownloaded-client-config.ovpnファイルを、nanoやメモ帳等のエディタで開きます

```
nano ダウンロードしたdownloaded-client-config.ovpn
```

以下のように記述されているので、

```
前略
:
-----END CERTIFICATE-----

</ca>

reneg-sec 0
```

以下のように[クライアント証明書(client1.domain.tld.crt)とクライアントキー(client1.domain.tld.key)](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#証明書とキーの発行-1)の内容を<cert>タグと<key>タグ内に記述します
(証明書は`-----BEGIN CERTIFICATE-----`から`-----END CERTIFICATE-----`の部分を、キーは`-----BEGIN PRIVATE KEY-----`から`-----END PRIVATE KEY-----`までをコピペします)

```
前略
:
-----END CERTIFICATE-----

</ca>

<cert>
クライアント証明書の内容
</cert>

<key>
クライアントキーの内容
</key>

reneg-sec 0
```


### OpenVPNのクライアントをインストール
クライアントとなるオンプレPCに、OpenVPNのクライアントソフトをインストールします。

私のPCはMac (M1)なので、クライアントソフトとして[TunnelBlick](https://blog.denet.co.jp/macos-tunnelblick/)を使用します (Windowsの場合は[OpenVPN GUI](https://www.apollomaniacs.com/ipod/howto_nas_qnap_cloud_openvpn.htm)等を使用して下さい)

以下コマンドで[HomeBrew](https://qiita.com/c60evaporator/items/aef6cc1581d2c4676504#homebrewのインストール)からTunnelBlickをインストールします

```
brew install --cask tunnelblick
```

### VPN接続の実行
※TunnelBlickの実行例です。Mac以外では[こちらの公式ドキュメント](https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-user/connect.html)を参照ください

TunnelBlickを開いて出てきた画面の「接続先」欄に、先ほどダウンロードしたクライアントVPNエンドポイント設定ファイル (downloaded-client-config.ovpn)をドラッグ＆ドロップします

<img width=600 alt="クライアントVPN設定ファイルのTunnelBlickへのドラッグ＆ドロップ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/e58f23b8-8158-c3e9-e2bb-dc89d439d761.png">

接続先を「個人用」「全ユーザ用」どちらにインストールするかを選択します。特定のユーザでしかログインしない場合は「個人用」を選択すれば良いかと思います

<img width=200 alt="TunnelBlickの設定インストール先" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/6e726eff-ecfe-456d-785f-85f8145a07a9.png">

「接続」をクリックしてVPN接続を開始します。

<img width=400 alt="VPN接続開始" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/bdb770ef-8c08-e5d5-201e-632c5a21e5d3.png">

VPN接続が開始されると、インターネットに繋がらなくなるのでご注意下さい (プロキシサーバを経由させるようブラウザを設定変更すればインターネット接続可)
「切断」を押すと、VPN接続が終了します。

以後の**疎通確認でVPN接続が正常に設定できているか確認します**

<br>
<br>

## 各インスタンスへの疎通確認 (VPC2)
VPC2も[VPC1のときと同様](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#各インスタンスへの疎通確認-vpc1)、想定通り設定ができているか疎通確認します。

具体的には、以下の内容を確認します

⑩VPNから開発用サーバへSSH通信できる
⑪開発用サーバからプロキシサーバへSSH通信できる
⑫VPNからプロキシサーバへSSH通信できる
⑬VPNからプロキシサーバ経由でインターネットへHTTP通信できる
⑭外部からプロキシサーバへSSH通信**できない**
⑮開発用サーバからWebサーバへSSH通信できる
⑯開発用サーバからAPサーバへSSH通信できる
①外部からWebサーバへSSH通信**できない**
④WebサーバからAPサーバへSSH通信**できない**

<img width=720 alt="VPC2の疎通確認" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/73a1c1bf-51a6-ba38-a239-63cecaa71f23.png">

※可能であれば[前述の②〜③, ⑤〜⑨](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#各インスタンスへの疎通確認-vpc1)も再確認する事が望ましいです。

### VPN動作確認
#### ⑩VPNから開発用サーバへのSSH疎通確認
VPN経由で開発用サーバにSSH接続できる事を確認します

[先ほどのVPN接続](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpn接続の実行)で「接続」ボタンを押した状態 (VPN接続が有効となった状態)で、VPN接続されたローカルから以下コマンドで開発用サーバにSSH接続します

```
ssh ec2-user@[開発用サーバのプライベートIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

Amazon Linuxの起動マークが表示されたら成功です。

本来であればローカルからクラウドにプライーベートIPでアクセスする事はできませんが、VPNを経由すればアクセスを実現できる事が分かります。VPNすごい！

#### ⑪開発用サーバからプロキシサーバへのSSH疎通確認
VPN経由でSSH接続した開発用サーバを踏み台に、プロキシサーバにSSH接続できる事を確認します。

⑩で開発用サーバにSSH接続した状態で、以下コマンドでプロキシサーバにSSH接続します

```
ssh ec2-user@[プロキシサーバのプライベートIPアドレス] -i [開発用サーバ内のキーペア秘密鍵のパス]
```

Amazon Linuxの起動マークが表示されたら成功です。

#### ⑫VPNからプロキシサーバへのSSH疎通確認
現在の[プロキシサーバ用セキュリティグループの設定](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#プロキシサーバ用セキュリティグループの修正-1)ではVPNからのSSH接続を許可しているので、開発用サーバを踏み台にしなくともVPNから直接SSH接続できるはずです。

[先ほどのVPN接続](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpn接続の実行)で「接続」ボタンを押した状態で、VPN接続されたローカルから以下コマンドで開発用サーバにSSH接続します

```
ssh ec2-user@[プロキシサーバのプライベートIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

なお、VPNからプロキシサーバへのSSH接続を拒否 (開発用サーバを踏み台にする事を強制する)した方がセキュリティ的には強いので、満たすべきセキュリティレベルに合わせて適宜セキュリティグループの設定を変更してください。

#### ⑬VPNからプロキシサーバ経由でのインターネットへのHTTP疎通確認
[プロキシサーバ用セキュリティグループの設定](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#プロキシサーバ用セキュリティグループの修正-1)ではVPNからのプロキシ通信 (カスタムTCPポート3128)を許可しているので、VPNからプロキシサーバ経由でのインターネットへとHTTPできるはずです。

[先ほどのVPN接続](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpn接続の実行)で「接続」ボタンを押した状態で、VPN接続されたローカルから以下curlコマンドでプロキシサーバ経由でのHTTP通信を実行します

```
curl http://www.example.com -x http://[プロキシサーバのプライベートIPアドレス]:3128
```

`http://www.example.com`から以下のようなHTMLが返って来れば成功です

```html
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
:
以下略
```

[先ほど](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpn接続の実行)「VPN接続が開始されると、インターネットに繋がらなくなる」と言いましたが、このプロキシサーバを経由するようブラウザに設定する事で、VPNからインターネットに接続する事ができます。

ただし、デフォルト設定では速度が遅かったりHTTPSが上手く繋がらなかったりと実用的なレベルではないので、Squidをチューニングする等してプロキシの動作速度を上げてください (本記事の本筋からずれるので詳細は割愛します)

#### ⑭外部からプロキシサーバへのSSH「非疎通」確認
[先ほどのプロキシサーバ用セキュリティグループの設定変更](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#プロキシサーバ用セキュリティグループの修正-1)で、プロキシサーバへのSSH接続は開発用サーバまたはVPN経由のみ許可するように設定しました。

よって**VPNを経由せずに外部からプロキシサーバにSSH接続できない**事を確認します。

ローカルからVPNを切断した状態で以下コマンドを打ち、インターネット経由でプロキシサーバにSSH接続します

```
ssh ec2-user@[プロキシサーバのパブリックIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

セキュリティグループ設定変更前の[VPC2内のインスタンスへの疎通確認](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc2内のインスタンスへの疎通確認)と全く同じコマンドですが、前とは異なり接続できない事がわかります。
インターネット経由でSSH接続できなくなったので、よりセキュリティレベルが高まったと言えるでしょう

### VPN経由でのVPC1への疎通確認
VPNからVPC2の開発サーバを踏み台として、VPC1の各インスタンスにSSH接続できる事を確認します

#### ⑮開発用サーバからWebサーバへのSSH疎通確認
先ほどの「[VPC1への疎通確認](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc1への疎通確認)」とほぼ同内容ですが、VPN経由でも接続できる事を確認します。

[先ほどのVPN接続](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpn接続の実行)で「接続」ボタンを押した状態で、VPN接続されたローカルから以下コマンドで開発用サーバにSSH接続します

```
ssh ec2-user@[開発用サーバのプライベートIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

以下コマンドで、VPC1内のWebサーバ1にSSH接続します

```
ssh ec2-user@[Webサーバ1のプライベートIPアドレス] -i [開発用サーバ内のキーペア秘密鍵のパス]
```

Amazon Linuxのロゴが表示されれば接続成功です！
同様にWebサーバ2についても疎通確認して下さい。


#### ⑯開発用サーバからAPサーバへのSSH疎通確認
引き続き開発用サーバにSSH接続した状態をスタートとし、以下コマンドで、VPC1内のAPサーバ1にSSH接続します

```
ssh ec2-user@[APサーバ1のプライベートIPアドレス] -i [開発用サーバ内のキーペア秘密鍵のパス]
```

Amazon Linuxのロゴが表示されれば接続成功です！
同様にAPサーバ2についても疎通確認して下さい。


### VPC1への直接接続の非疎通確認
[VPC1構築直後の疎通確認](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#各インスタンスへの疎通確認-vpc1)ではインターネット経由でVPC1にSSH接続できましたが、[セキュリティグループ設定の変更](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpc1内のセキュリティグループ設定の修正)でこれが出来なくなった (セキュリティレベルが高まった)事を確認します。

#### ①外部からWebサーバへのSSH「非疎通」確認
[①外部からWebサーバへのSSH疎通確認](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#sshの疎通確認)では疎通していたインターネット→WebサーバのSSH接続の非疎通を確認します。

VPNを切断した状態で、以下コマンドでWebサーバにSSH接続します

```
ssh ec2-user@[WebサーバのパブリックIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

応答が返ってこなければ成功です。

#### ④WebサーバからAPサーバへのSSH「非疎通」確認
[④WebサーバからAPサーバへのSSH疎通確認](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#sshの疎通確認-webサーバを踏み台にした場合)では疎通していたインターネット→WebサーバのSSH接続の非疎通を確認します。

[先ほどのVPN接続](https://qiita.com/c60evaporator/items/b9e645b96afa3a34f41e#vpn接続の実行)で「接続」ボタンを押した状態で、VPN接続されたローカルから以下コマンドで開発用サーバにSSH接続します

```
ssh ec2-user@[開発用サーバのプライベートIPアドレス] -i [ローカルのキーペア秘密鍵のパス]
```

以下コマンドで、VPC1内のWebサーバ1にSSH接続します

```
ssh ec2-user@[Webサーバ1のプライベートIPアドレス] -i [開発用サーバ内のキーペア秘密鍵のパス]
```

以下コマンドで、APサーバ1にSSH接続します

```
ssh ec2-user@[APサーバ1のプライベートIPアドレス] -i [Webサーバ1内のキーペア秘密鍵のパス]
```

応答が返ってこなければ成功です。
APサーバ2についても同様に非疎通を確認しましょう。

Webサーバは外部に公開されているという特性上、攻撃により乗っ取られるリスクが大きいサーバーと言えます。よって内部の他のサーバーへと被害が広がらないよう、今回のように**Webサーバから他のサーバーへのSSH接続をセキュリティグループで拒否**すると、より**セキュアなシステム**を実現できます。

なお、現状では各サーバーに同じ秘密鍵がばら撒かれている状態となっているため、いずれかのサーバーが乗っ取られた際に危険な状態となってしまいます。よって、**開発用サーバ以外の秘密鍵は削除**してしまいましょう。

<br>
<br>
<br>

以上で、**疎通確認および本記事の全作業が完了**しました。

長かったですが、**以下の複雑なネットワークをAWS上に構築出来た**ことに、感動を覚えた方も多いのではないのでしょうか？ (感動の押し売りと言われそうですが…笑)

<img width=720 alt="構築するVPC構成図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/42d9caf9-082f-9340-3cb7-490628d5938e.png">

※CroudFrontやRoute53はVPC外のサービスのため本記事では触れませんが、今後別記事で投稿したいと思います

<br>
<br>

## 【参考】コストについて
参考までに、**今回作成したVPC全体の無負荷時のコスト構成**は、以下のようになりました。
(3日間測定しましたが、どの日もほぼ同じコスト構成でした)

<img width=720 alt="VPCの実コスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/b32a1958-28b3-3294-dca5-ea5cd3fec888.png">

|サービス (機能)名|日あたりのコスト|月換算|割合|
|---|---|---|---|
|クライアントVPN|$3.6|$108|41.9%|
|EC2|$2.2|$65.7|25.5%|
|RDS|$1.2|$37.5|14.6%|
|ELB|$1.2|$35.1|13.6%|
|EBS|$0.2|$5.7|2.2%|
|その他(RDSのストレージ等)|$0.2|$5.5|2.1%|
|計|$8.6|$257.5|100%|

クライアントVPNが多くを占めており、VPNは無負荷時でもそれなりのコストが掛かる事が分かります。

一方でアクセス負荷が増えた場合はWebサーバやRDSのインスタンス数を増やす (またはインスタンスタイプを上げる)必要が生じるため、これらのコストが増大する事が想定されます。

<br>

## 【参考】NATゲートウェイの作成
上記構成にはNATゲートウェイが存在しないため、一見プライベートサブネットからインターネットにアクセスできないように見えますが、以下サイトのように**yumコマンドはS3用ゲートウェイエンドポイント経由で実行可能**です。

https://soypocket.com/it/ec2-yum-privatesubnet-s3endpoint/

よって最低限のパッケージアップデートはNATゲートウェイなしで実行できますが、**yumコマンド以外でプライベートサブネットからインターネットにアクセスしたい場合**は、以下のようにパブリックサブネットに**NATゲートウェイの作成**が必要です。

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/6478f06c-2fc1-e1d3-0907-817107f86a38.png">

<img width=420 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/95a9b3cc-bb28-fc48-6ffb-844c63337bb5.png">

NATゲートウェイは他のAZのプライベートサブネットからもアクセス可能なため、冗長性を考慮しないのであれば1個のみ作成すればOKです。

また、そのままでは作成したNATゲートウェイへのルーティングが設定されておらず、インターネットへのアクセスができないので、以下のように**プライベートサブネットのルートテーブル**(インターネット接続用の0.0.0.0/0)の**ターゲットにNATゲートウェイを指定**する必要があります。

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/1f9a00b0-3f88-dfcd-6737-c2beb4da54a7.png">

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/46345c05-e451-bb13-fb59-af6b44be8a4f.png">

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/eeb634a3-0d3d-e043-0b08-7061f971f866.png">

<br>
<br>

# 感想
長くて疲れました…

ただ、オンプレで動的ルーティングやFWを設定してVRRPやスパニングツリーで冗長化…なんて事になると、この比ではない大変さだと思うので、**気軽に冗長構成やセキュリティ強化**を実現できる**クラウドの有り難み**を感じる事も出来ました。

継続的に開発するのであれば、再現性があり、かつミスを減らせるよう**IaCで自動化**したいですね。
IaC (Terraform)でVPCを構築する方法に関しても、今後記事にしたいと思います。