踏み台サーバーとNAT Gatewayを利用したセキュアなAWS EC2環境構築手順

インフラ

こんにちは。Enjoy IT Life管理人の仁科(@nishina555)です。

前回、HTTPやSSHで接続できるEC2をVPCに構築する手順について紹介しました。

【AWS環境構築手順】VPCとEC2を作成し、実際にアクセスしてみる

2020年5月28日

しかし、外部公開しているWebサーバーに対して直接SSH接続ができるのはセキュリティ的にはあまりよくありません。

実際にサービスが稼働しているAWS環境では、踏み台(Bastion)サーバー経由でSSH接続する方法がよく採用されています。

そこで今回は、インターネットで直接アクセスできないプライベートサブネットワーク内にWebサーバーを配置したセキュアなAWS環境の構築方法について紹介します。

今回のゴール
  • パブリックサブネット経由でプライベートサブネットにアクセスする方法を理解する
  • 踏み台(Bastion)サーバー経由で多段SSH接続する方法を理解する
  • NAT Gatewayの構築方法について理解する

今回作成するAWS環境

今回作成するAWS環境のイメージ図は以下の通りです。

補足説明は以下の通りです。

  • パブリックサブネットにEC2(踏み台サーバー用)とNAT Gatewayを配置
  • プライベートサブネットにEC2(Webサーバー用)を配置
  • WebサーバーへのSSH接続は踏み台サーバー経由で行う
  • NAT Gateway経由でWebサーバーからインターネットへのアウトバウンド通信(yumコマンドなど)を実現する

なお、今回はパブリックサブネットに配置したEC2インスタンスを『踏み台(Bastion)サーバー』、プライベートサブネットに配置したEC2インスタンスのことを『Webサーバー』と呼ぶことにします。

VPCを作成する

AWSマネージメントコンソールでVPCを選択します。

『VPC』→『VPCの作成』を選択します。

必要事項を入力し、『作成』を選択します。

各項目の意味は以下の通りです。

  • 名前タグ: VPCの識別子
  • IPv4 CIDRブロック: VPCで利用するアドレスの範囲を記述。ブロックサイズは`/16`から`/24`の間までである必要がある。
  • Ipv6 CIDRブロック: Amazonが提供するIPv6 CIDRブロックをVPCに紐づけるかどうかの設定。
  • テナンシー: ハードウェアを占有(物理的に確保)に必要性があれば『専用』、特になければ『デフォルト』を選択

なお、IPv4 CIDR ブロックについてですが、/xxの値が小さいほどVPC内に割り当てられるプライベートIPの数が多くなります。

【図解】IPアドレスの仕組み(クラス分類からサブネットまで)

2018年3月31日

今回は例としてsample-devというVPCをIPv4 CIDRブロック10.0.0.0/16で作成しました。

インターネットゲートウェイを作成する

VPCの空間とインターネットの世界を結びつけるために必要な『インターネットゲートウェイ』と呼ばれるものを作成します。

『VPCダッシュボード』を開き、『インターネットゲートウェイ』→『インターネットゲートウェイの作成』を選択します。

『名前タグ』を入力し、『作成』を選択します。

今回はsample-gatewayというインターネットゲートウェイを作成しました。

VPCとインターネットゲートウェイを結びつける

VPCがインターネットゲートウェイを介してインターネットの世界とつながるには、VPCとインターネットゲートウェイを結びつける作業が必要です。この作業をアタッチと呼びます。

インターネットゲートウェイを作成した直後のsample-gatewayは以下のようにdetachedという状態になっています。

アタッチ対象のインターネットゲートウェイを選択し、『アクション』→『VPCにアタッチ』を選択します。

アタッチするVPCを指定し(今回の場合はsample-dev)、『アタッチ』を選択します。

以下のようにattachedになればOKです。

サブネットを作成する

次に、先ほど作成したVPCで利用するサブネットを作成していきます。

今回は踏み台サーバーとNAT Gatewayを配置する『パブリックサブネット』と、Webサーバーを配置する『プライベートサブネット』を作成します。

パブリックサブネットの作成をする

『VPCダッシュボード』を開き、『サブネット』→『サブネットの作成』を選択します。

必要事項を入力し、『作成』を選択します。

各項目の意味は以下の通りです。

  • 名前タグ: サブネットの識別子
  • VPC: サブネット作成対象のVPC
  • アベイラビリティゾーン: サブネットを作成するアベイラビリティゾーン。特に希望がなければ『指定なし』でOK
  • IPv4 CIDRブロック: サブネットで利用するアドレスの範囲を記述。ブロックサイズは『/16』から『/28』の間までである必要がある。

今回は例として10.0.0.0/24public-subnetという名前のプライベートサブネットを、先ほど作成したsample-devVPC内に用意するようにしました。

プライベートサブネットを作成する

パブリックサブネットと同様の手順で作成していきます。

今回は10.0.1.0/24private-subnetという名前のプライベートサブネットを作成しました。

NAT Gatewayを作成する

NAT Gatewayとはプライベートサブネットからインターネットへのアウトバウンド通信を実現するためのものです。

NAT Gatewayを構築することにより、直接インターネットに接続されていないプライベートサブネット配下のサーバーでもライブラリのアップデートやインストールを行えるようになります。

『VPCダッシュボード』を開き、『NAT ゲートウェイ』→『NAT ゲートウェイの作成』を選択します。

『サブネット』に先ほど作成したpublic-subnetを、『Elastic IP割り当てIP』に割り当て可能なElastic IP IDを入力します。

Elastic IPとはパブリックIPを固定するための機能です。今回は割り当て可能なEIPがなかったため『新しいEIPの作成』を選択しました。

入力が完了したら『NATゲートウェイの作成』を選択します。

以下のようにNAT Gatewayが作成され、ステータスが『使用可能』になればOKです。

ルートテーブルを作成する

ルートテーブルとは通信の送信先をルール化したものです。
サブネットごとにルートテーブルを設定することでサブネットからの通信の送信先を制御できるようになります。

今回はパブリックサブネット用とプライベートサブネット用の2つのルートテーブルを作成します。

パブリックサブネット用のルートテーブルを作成する

『VPCダッシュボード』を開き、『ルートテーブル』→『ルートテーブルの作成』を選択します。

必要事項を入力し、『作成』を選択します。

各項目の意味は以下の通りです。

  • 名前タグ: ルートテーブルの識別子
  • VPC: ルートテーブルを利用するVPC

今回は例として、public-routeというルートテーブルを、先ほど作成したsample-devVPC内に用意するようにしました。

ルートテーブルとサブネットを関連付ける

VPC内に存在するパブリックサブネットに先ほど作成したルートテーブルを適用させるため、ルートテーブルとサブネットの関連付けを行っていきます。

関連付け対象のルートテーブルを選択し、『サブネット関連付け』→『サブネットの関連付けを編集』を選択します。

関連付けしたいサブネットをチェックし、『保存』を選択します。

以下のようにルートテーブルにサブネットが紐づいていればOKです。

ルートテーブルを編集する

サブネットからの通信をインターネットへつなぐようにするため、ルートテーブルを編集します。

関連付け対象のルートテーブルを選択し、『ルート』→『ルートの編集』を選択します。

『ルートの追加』を選択し、以下の設定を追加します。

  • 送信先: 0.0.0.0/0
  • ターゲット: インターネットゲートウェイ

追加が完了したら『ルートの保存』を選択します。

0.0.0.0/0デフォルトルートと呼ばれ、すべてのネットワークを集約している意味を持ちます。
つまり、任意IPアドレスに対する通信の送信先がインターネットゲートウェイになるため、このルートテーブルが設定されたサブネットの通信は全てインターネットゲートウェイを向くようになります。

新しく追加したルートがactiveになっていればOKです。

プライベートサブネット用のルートテーブルを作成する

先ほど作成したパブリックサブネット用のルートテーブルと同様の手順で今度はプライベートサブネット用のルートテーブルを作成していきます。

プライベートサブネット用のルートテーブルでは0.0.0.0/0の送信先をNAT Gatewayにし、関連付けるサブネットはprivate-subnetにします。

なお、今回はprivate-routeというルートテーブル名をつけました。

セキュリティグループを作成する

セキュリティグループとはグループ外との通信を制御するためのファイアウォールです。『インバウンド』と『アウトバウンド』の制御をすることができます。

EC2インスタンスを作成する過程でセキュリティグループが必要になるため、まずはセキュリティグループの準備を行います。
今回は踏み台サーバー用とWebサーバー用の2つのセキュリティグループを作成します。

踏み台サーバー用のセキュリティグループを作成する

『VPCダッシュボード』を開き、『セキュリティグループ』→『セキュリティグループを作成』を選択します。

必要事項を入力し、『セキュリティグループを作成』を選択します。

各項目の意味は以下の通りです。

  • セキュリティグループ名: セキュリティグループの識別子
  • 説明: セキュリティグループの説明
  • VPC: セキュリティグループ作成対象のVPC
  • インバウンドルール: 外からの通信に対するルール
  • アウトバウンドルール: 外への通信に対するルール

踏み台サーバー用のセキュリティグループのため、インバウンドルールでSSHのみを許可するように設定しました。
また、ソースを開発者が利用するグローバルIPアドレス/32を指定することで開発者しかSSH接続できないようにしています。

今回は sample-bastionという名前のセキュリティグループ名をつけました。

Webサーバー用のセキュリティグループを作成する

先ほど作成した踏み台サーバー用のセキュリティグループと同様の手順で作成していきます。

Webサーバー用のセキュリティグループの場合、インバウンドルールで踏み台サーバーが所属するセキュリティグループからのみSSH接続をできるように設定します。

今回はsample-webという名前のセキュリティグループ名をつけました。

EC2インスタンスの作成をする

踏み台サーバー用とWebサーバー用の2つのEC2インスタンスを作成します。

踏み台サーバーを作成する

AWSマネージメントコンソールでEC2を選択します。

『EC2ダッシュボード』を開き、『インスタンス』→『インスタンスの作成』を選択します。

インスタンスを作成する際のベースとなるマシンシメージ(AMI)を選択します。今回は『Amazon Linux2 AMI』を選択します。

インスタンスタイプの選択をします。今回は『t2.nano』を選択します。

インスタンスの詳細設定をします。
設定する内容はいくつかありますが、今回は以下の項目の設定をすればOKです。

  • ネットワーク: 事前に作成したVPC名
  • サブネット: 事前に作成したパブリックサブネット名
  • 自動割り当てパブリックIP: 『有効』(インターネットで直接インスタンスを参照できるようにするため)

ストレージの追加をします。今回は設定不要です。

タグの追加をします。今回は『Name』というキーに『sample-bastion』という値を設定しました。

セキュリティグループの設定をします。『既存のセキュリティグループを選択する』を選択し、先ほど作成した踏み台サーバー用のセキュリティグループにチェックをつけます。

以上でインスタンスの設定が完了です。
インスタンスの詳細確認後、問題がなければ『起動』を選択します。

『起動』を選択するとキーペアの設定画面が表示されます。
『新しいキーペアの作成』を選択し、任意のキーペア名を設定後、『キーペアのダウンロード』を選択します。
今回はsample-bastionという名前のキーペアを作成しました。

キーペアのダウンロード完了後、『作成』を選択します。

以下のようにインスタンスが作成され、ステータスチェックが全てパスされていればOKです。

Webサーバーを作成する

踏み台サーバーと同様の手順で今度はWebサーバーを作成していきます。

『セキュリティグループ』および『サブネット』はプライベート用のものを指定します。
また、プライベートサブネットなので『自動割り当てパブリックIP』は『無効』で問題ありません。

キーペアは踏み台サーバーとは別のキーペアを作成します。今回はsample-webという名前のキーペアを作成しました。

なお、インスタンス名はsample-webとしています。

動作確認

ここまでで冒頭で紹介したAWSの環境を構築することができました。

踏み台サーバーへSSH接続できることを確認

EC2作成時にダウンロードしたキーを利用してEC2にSSH接続できるか確認してみましょう。

SSH接続をする際に必要になるパブリックIPはEC2インスタンスの詳細で確認ができます。

ダウンロードしたpemキーのパーミッションを変更し、以下のコマンドでEC2インスタンスにログインできればOKです。
なお、ec2-userは今回インスタンス作成時に利用したAmazon Linuxイメージの初期ユーザー名です。

$ cd /path/to/pemfile
$ chmod 600 sample-bastion.pem
$ ssh -i sample-bastion.pem ec2-user@[踏み台サーバーのパブリックIP]

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

https://aws.amazon.com/amazon-linux-2/

踏み台サーバー経由でWebサーバーへSSH接続できることを確認

踏み台サーバーを経由してWebサーバーへSSHする方法は以下の2通りです。

  • 踏み台サーバーにWebサーバーの秘密鍵をアップロードし、踏み台サーバーからSSH接続する
  • sshコマンドのProxyCommandオプションを利用してローカル環境からSSH接続する(多段SSH)

今回はProxyCommandオプションを利用した多段SSHを利用して、踏み台サーバー経由でWebサーバーにSSH接続してみたいと思います。

多段SSHを行う際、WebサーバーのプライベートIPが必要になります。
プライベートIPはEC2の詳細で確認できます。

実行するコマンドは下記の通りです。
なお、sample-bastion.pemは踏み台サーバーの、sample-web.pemはWebサーバーの秘密鍵です。

$ cd /path/to/pemfile
$ chmod 600 sample-bastion.pem
$ chmod 600 sample-web.pem
$ ssh -oProxyCommand='ssh -W %h:%p -i sample-bastion.pem ec2-user@[踏み台サーバーのパブリックIP]' -i sample-web.pem ec2-user@[WebサーバーのプライベートIP]

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

https://aws.amazon.com/amazon-linux-2/

~/.ssh/configファイルに下記を追加することで多段SSHをシンプルに表現することができます。

~/.ssh/config

Host sample-bastion
  Hostname [踏み台サーバーのパブリックIP]
  User ec2-user
  IdentityFile [踏み台サーバーの秘密鍵のパス]

Host sample-web
  Hostname [WebサーバーのプライベートIP]
  User ec2-user
  IdentityFile [Webサーバーの秘密鍵のパス]
  ProxyCommand ssh sample-bastion -W %h:%p

~/.ssh/configファイルが正しく設定されていれば下記のコマンドでWebサーバーに多段SSH接続できるようになります。

$ ssh sample-web

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

https://aws.amazon.com/amazon-linux-2/

Webサーバーからインターネットへアウトバウンド通信できることを確認

Webサーバーにログインしたらyumコマンドが実行できるか確認してみます。
NAT Gatewayの設定は正しくされていればコマンドが実行できるはずです。

$ ssh sample-web
$ sudo yum update
→ 結果が実行されればOK

読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
amzn2-core | 2.4 kB 00:00:00
No packages marked for update

まとめ

以上で踏み台サーバーとNAT Gatewayを利用したセキュアなAWS EC2環境の構築手順の紹介を終わります。

今回構築した環境をまとめると以下のようになります。

サブネット

名前 目的 IPv4 CIDRブロック
public-subnet インターネットと接続できる領域の確保 10.0.0.0/24
private-subnet セキュアな領域の確保 10.0.1.0/24

ルートテーブル

名前 ルール サブネット関連付け
public-route デフォルトルートをInternet Gateway public-subnet
private-route デフォルトルートをNAT Gateway private-subnet

セキュリティグループ

名前 インバウンドルール 用途
sample-bastion SSHを開発者のIPアドレスのみ許可 踏み台サーバー用
sample-web SSHを踏み台サーバーのセキュリティグループのみ許可 Webサーバー用

EC2インスタンス

名前 サブネット セキュリティグループ パブリックIP キーペア
sample-bastion public-subnet sample-bastion 有効 sample-bastion
sample-web private-subnet sample-web 無効 sample-web

なお、今回はプライベートサブネットに配置したEC2をWebサーバーと呼びましたが、プライベートサブネットへHTTP(S)接続する方法については言及していません。 ですので、Webサービスを稼働させるための環境としてはまだ不十分です。

プライベートサブネットへHTTP(S)接続する方法の1つとして、Application Load Balancer(ALB)やCLB(CLB、旧ELB)をパブリックサブネットに配置する手法などが挙げられます。
プライベートサブネットにWebサーバーを配置する際は、HTTP(S)接続の導線も忘れずに設定しておきましょう。

ALBとEC2を連携させ、プライベートサブネットに配置されたWebサーバーへHTTPアクセスを行う方法については『AWS EC2にALBを導入し、Webサーバーのロードバランシングを実現する手順』で紹介しているので参考にしていただければと思います。

なお、今回利用したNatGatewayですが、NatGatewayはAWSの無料利用枠対象外で、起動しているだけで課金(東京リージョンの場合0.062USD/h)されます。 1

ですので、勉強のために作成したNatGatewayは不要になった時点で削除することをオススメします。

この記事がいいなと思いましたらツイッター(@nishina555)のフォローもよろしくお願いします!