記念すべき初投稿です!
いつも業務ではQuiitaに大変お世話になっている私です。
自分のような未熟者が投稿しても需要があるのか謎ですが
備忘録的に書き留めていこうかなと思い始めました。
投稿内容はAWSオンリーになりそうですがよろしくお願いします。
では前置きはそこそこに、さっそくタイトルにある通り本記事で
以下の図のような一般的なEC2によるサーバーの構築をやっていき、
セキュリティ面での注意すべきポイントの解説をメインに書き連ねていきます。
※記事が結構長いです、読みにくくてすいません
【構築するもの】
・プライベートサブネットにWebサーバー(2台)を配置し、
外部から直接アクセスできないようにする。
・アクセス負荷の分散とSSL処理のためのロードバランサーを設置し、
HTTPとHTTPSしかアクセスできないようにする。
・パブリックサブネットに踏み台サーバーを配置し、
管理者がSSH接続でWebサーバーにアクセスできるように設定する。
【手順の流れ】
①VPCを構築する。
②パブリックサブネットとプライベートサブネットを各アベイラビリティゾーンに
1つずつ構築し、直接インターネットからアクセスされる範囲と
アクセスさせない範囲を分ける。
③VPCにインターネットゲートウェイをアタッチし、インターネットの通り道を作る。
④NATゲートウェイをパブリックサブネットにアタッチし、
プライベートサブネットから外部のインターネットのみにアクセスできるようにする。
⑤ルートテーブルを作成し、パブリックサブネットとプライベートサブネットから
それぞれ外部のインターネットにアクセスする経路を作成する。
パブリックサブネットの向き先はインターネットゲートウェイに、
プライベートサブネットの向き先はNATゲートウェイに設定する。
⑥セキュリティグループを作成し、踏み台サーバー用のインバウンドルールには
SSH接続のみ許可し、ロードバランサー用にはHTTP、HTTPS通信のみ
許可するよう設定する。
⑦EC2で踏み台サーバー、Webサーバー2つの計3つのインスタンスを作成する。
踏み台サーバーはパブリックサブネット、Webサーバーは
プライベートサブネットに配置し、踏み台サーバーにはSSH接続のみ
許可したセキュリティグループを適応する。
踏み台サーバーへのアクセスのためにキーペアを作成し、
キーペアでローカルPCからSSH接続する。
webサーバーはロードバランサー側で通信を制限するため
セキュリティグループはデフォルトを設定してすべてのアクセスを許可する。
⑧ロードバランサーを作成する。ターゲットにはプライベートサブネット内に配置した
Webサーバー2台を指定する。
HTTP/HTTPSのみ許可したセキュリティグループを適応させる。
少し長くなりましたが手順のポイントとしては、以下になります。
・ロードバランサーで外部からのアクセスはHTTPかHTTPSに限定する。
・Webサーバーは直接アクセスできないようプライベートサブネットに配置し、
ロードバランサーで制御された通信しか通さないようにする。
・踏み台サーバーはSSH接続でキーペアをもつ端末からしかアクセスできないよう制御する。
ではさっそく実際にAWSコンソールから構築していきます!
①VPCの構築
コンソールからVPCにアクセスし、「VPCを作成」を選択します。
VPCに付ける名前とIPv4 CIDRを入力して「VPCを作成」ボタンをクリック。
これで仮想ネットワークを構築できたのでこの後VPC内に
ネットワーク機器に該当するリソースを追加していきます!
②サブネットの追加
コンソールのVPC < サブネットを押下し、「サブネットを作成」ボタンを押下。
アベイラビリティゾーン:ap-notheast-1a内に
my-sample-subnet-public1とmy-sample-subnet-private1を、
アベイラビリティゾーン:ap-notheast-1c内に
my-sample-subnet-public2とmy-sample-subnet-private2を
分割していることを頭の隅に意識しておきます。
作成されたサブネットはこんな感じです。
③インターネットゲートウェイをVPCにアタッチする
コンソールのVPC < インターネットゲートウェイを押下し、
「インターネットゲートウェイの作成」ボタンを押下。
VPCに作成したインターネットゲートウェイをアタッチします。
これでVPC内のリソースとインターネットをつなぐ出入口ができました。
④NATゲートウエイをパブリックサブネットにアタッチする。
コンソールのVPC < NATゲートウェイを押下し、「NATゲートウェイを作成」を押下する。
サブネットはパブリックサブネットを選択するので、my-sample-subnet-public1と
my-sample-subnet-public2に対してそれぞれNATゲートウェイを作成します。
「Elastic IPの割り当て」を選択し、NATゲートウェイに割り当てるElastic IPアドレスを
生成します。
NATゲートウェイがあることで、プライベートサブネットからパブリックサブネットへの
一方通行なアクセスが可能になります。
つまりプライベートサブネット内のリソースからは外部インターネットへ
アクセスできるが、インターネットからはプライベートサブネット内のリソースに
アクセスできないようにしたい、を可能にするのがNATゲートウエイです。
⑤ルートテーブルを作成し、パブリックサブネットとプライベートサブネットから
インターネットへアクセスする経路の制御を行う。
インターネットゲートウェイでVPCからインターネットへの出入り口を、
NATゲートウェイでプライベートサブネットから外部インターネットへの経路を
作成しましたがこれだけでは通信はできません。
ルートテーブルで通信経路を作ることでようやく通信できるようになります。
コンソールのVPC < ルートテーブルを押下し、「ルートテーブルを作成」を押下する。
まずはパブリックサブネット用のルートテーブルから作成します。
VPCを選択し、作成後に「ルート」タブを押し、「ルートを編集」ボタンを押下します。
「ターゲット」に作成済みのインターネットゲートウェイ、
「送信先」にすべてのIPアドレスを示す0.0.0.0/0を選択し「変更を保存」ボタンを押下します。
これでパブリックサブネットからインターネットゲートウェイへの経路が作成できました。
ちなみにデフォルトで「ターゲット」が「local」のルートがすでにありますが
これはVPC内の全てのリソースへのアクセス経路を意味しています。
次にプライベートサブネット用のルートテーブルを作成していきます。
パブリックサブネット同様にルートタブからルートを編集しますが、
プライベートサブネットの場合は通信の向き先がNATゲートウェイになります。
プライベートサブネットはそれぞれのアベイラビリティゾーンにある
パブリックサブネット内にNATゲートウェイを作成してあるので、
my-sample-rt-private1はmy-sample-subnet-private1のプライベートサブネットから
my-sample-subnet-public1にあるNATゲートウェイを向き先用に、
my-sample-rt-private2はmy-sample-subnet-private2のプライベートサブネットから
my-sample-subnet-public2にあるNATゲートウェイを向き先用に、2つ作成します。
ルートテーブルが3つ作成できたら、サブネットと関連付けます。
パブリックサブネット用に作成したルートテーブルで「サブネットの関連付け」タブを押し、
「サブネットの関連付けを編集」ボタンを押下します。
my-sample-subnet-public1とmy-sample-subnet-public2をチェックし、
「関連付けを保存」ボタンを押下します。
これでインターネットゲートウェイからパブリックサブネットへの
アクセス経路が確保できました。
続いてプライベートサブネットとNATゲートウェイの関連付けも行っていきます。
これでプライベートサブネット:my-sample-subnet-private1から
NATゲートウェイ:my-sample-ng1へのアクセス経路ができました。
プライベートサブネット:my-sample-subnet-private2から
NATゲートウェイ:my-sample-ng2へのアクセス経路も同様にできました。
⑥セキュリティグループを作成して通信を制御する
次にセキュリティグループを作成してリソース(今回は踏み台サーバーとロードバランサー)の
通信を制御します。今回セキュリティの話がメインなのでセキュリティグループの設定は
非常に重要な話になってきます。現場でセキュリティチェックをした時も
セキュリティグループが正しく設定されているか確認していました。
今回VPC < セキュリティグループを押し、「セキュリティグループを作成」ボタンを
押下します。
まずは踏み台サーバー用のセキュリティグループを作成します。
「インバウンドルール」で「SSH」を選択し、「ソース」に「Anywhere-IPv4」を選択します。
IPアドレスは念のため自分のローカルの端末を設定しておいた方がいいかもしれません。
次にロードバランサー用のセキュリティグループも作成します。
「インバウンドルール」に「HTTP」と「HTTPS」からのアクセスのみ許可します。
「ソース」は「Anywhere-IPv4」を選択します。
こちらも社内システムなど利用者が制限されている場合はIPアドレスを制限した方がいいです。
⑦踏み台サーバーとWebサーバー2台を作成する
サーバーを立てていきます。
まずは踏み台サーバーから。
EC2 < インスタンスで「インスタンスを起動」ボタンを押下します。
サブネットはmy-sample-subnet-public1を選択してパブリックサブネットに配置します。
パブリックサブネットに配置するため外部からアクセスするための
パブリックIPアドレスが必要なため「パブリックIPの自動割り当て」は「有効化」を選択。
「既存のセキュリティグループを選択する」を選択し、踏み台サーバー用に作成した
セキュリティグループを選択します。
あと、画像では選択し忘れていたのですが踏み台サーバーのセキュリティグループは
デフォルトも必要なので追加します。
(追加忘れてこのあと出てくるSSHの多段認証に詰まりました・・・
デフォルトのセキュリティグループはVPC内のリソースへのアクセスを許可しているため
これがないと踏み台サーバーからWebサーバーにアクセスできません)
安全にSSH接続するために「キーペア」は「新しいキーペアの作成」を押下し、作成します。
作成したキーペアを選択して「インスタンスを起動」ボタンを押下します。
しばらくすると踏み台サーバーが立ち上がりました。
では早速ローカルPCからアクセスしてみます。
インスタンスのパブリックIPアドレスを確認します。
ローカルPCのダウンロードフォルダに先ほど作成した時キーペアがあるので
.ssh配下に移動させます。
コマンドプロンプトを開いてSSH接続を行う。
ユーザー名はデフォルトで「ec2-user」になっています。
踏み台サーバーにアクセスできました。
次にそれぞれのプライベートサブネットにWebサーバーを1台ずつ立てます。
まずはmy-sample-subnet-private1に立てるWebサーバーから。
パブリックサブネットに立てた踏み台サーバーとは違い、
パブリックIPは不要なため(直接インターネットからアクセスさせないため)
設定しません。
セキュリティグループはデフォルトを選択します。
my-sample-subnet-private2に立てるWebサーバーも同様の設定で立てます。
踏み台サーバーを経由してプライベートサブネット内に作成した
インスタンスにもアクセスしてみます。
.ssh配下にconfigファイルを作成して上記のように記載します。
踏み台サーバーのホスト名はパブリックIPアドレスですがWebサーバーのホスト名は
プライベートIPアドレスなので注意です。
多段認証を用いる理由ですが、プライベートサブネット内のインスタンスに
キーペアを配置するのはセキュリティ的に良くないのと、
Webサーバーに入るたびに踏み台を経由して2回SSH接続するのが面倒だからです。
WebサーバーにもSSHでアクセスできました。
⑧ロードバランサーを作成し、WebサーバーへのアクセスはHTTP/HTTPSからのみに制限する
最後にロードバランサーで外部からの通信をHTTPとHTTPSに制限し、
アクセス負荷を2つのWebサーバーへ分散させます。
踏み台サーバーは管理者がSSH接続でWebサーバーへアクセスするために作成しましたが、
ロードバランサーはユーザーのアクセスを制御するために作成します。
コンソールのEC2 < ロードバランサーを押下し、「ロードバランサーの作成」を押下します。
Application Load Blancerを選択します。
ロードバランサーはHTTPのポート:80でリクエストを待ち受けます。
(本記事では一旦HTTPS:443の設定はスキップします)
「マッピング」にサブネットを作成したアベイラビリティゾーンと
パブリックサブネットを選択し、セキュリティグループは
デフォルトと作成したHTTP/HTTPSのみにアクセス制御しているものを選択します。
「リスナーとルーティング」はWebサーバー内でロードバランサーから来た
リクエストを受け付けるプロトコルを指定します。
「デフォルトアクション」のターゲットグループを指定したいので
「ターゲットグループの作成」リンクをクリックします。
「ターゲット」にWebサーバー2台を選択し、
「ターゲットグループの作成」ボタンを押下します。
これでロードバランサーがリクエストを分散させる対象の
Webサーバーをグルーピングできました。
インスタンスのポートは3000番を指定し、ロードバランサーから
受け取ったリクエストを3000番で受け付けます。
ロードバランサーの作成画面に戻って、今作成したターゲットグループを選択し、
「ロードバランサーの作成」ボタンを押下します。
ロードバランサーによってリクエストが分散できているか確認します。
コマンドプロンプトで各Webサーバーにログインし、適当なindex.htmlファイルを作成します。
ロードバランサーのリクエストがどちらのWebサーバーに飛んだか確認するために
Webサーバーごとに文言を変更してみました。
各Webサーバーで以下のコマンドを実行してHTTPサーバーを起動します。
python3 -m http.server 3000
ターゲットグループのヘルスステータスが「healthy」になればリクエストの
ルーティングに成功です。
ロードバランサーのDNS名をブラウザに入力すると、
ブラウザからindex.htmlを表示できました。