AWSのセキュリティグループの許可ソースにセキュリティグループを設定するパターンとは

みなさん、AWSのセキュリティグループはご存じでしょうか?

こんにちは。エンジニアの中井です。

AWSのサービスを利用する上で、避けては通れないのがセキュリティグループの設定です。
このセキュリティグループですが、改めてドキュメントを読み返すと色々と発見がありました。

そこで今回は、セキュリティグループの基本的な部分をおさらいしつつ、インスタンスへの設定パターンなどについて説明していきたいと思います。

セキュリティグループのおさらい

一言でいうと

  • セキュリティグループは「ステートフルなファイアウォール」で、インスタンスレベルで動作。
  • ネットワークACLは「ステートレスなファイアウォール」で、サブネットレベルで動作。

です。

セキュリティグループとは

まず、セキュリティグループとは?についてAWSのドキュメントを見てみると、次のとおり記載されています。

セキュリティグループは、EC2 インスタンスの仮想ファイアウォールとして機能し、受信トラフィックと送信トラフィックを制御します。インバウンドルールはインスタンスへの受信トラフィックを制御し、アウトバウンドルールはインスタンスからの送信トラフィックをコントロールします。インスタンスの起動時に 1 つ以上のセキュリティグループを指定できます。セキュリティグループを指定しない場合、Amazon EC2 はデフォルトのセキュリティグループを使用します。各セキュリティグループに対してルールを追加し、関連付けられたインスタンスに対するトラフィックを許可できます。セキュリティグループのルールはいつでも変更することができます。新規または変更したルールは、セキュリティグループに関連付けられたすべてのインスタンスに自動的に適用されます。トラフィックがインスタンスに到達することを許可するかどうかを Amazon EC2 が判断するとき、インスタンスに関連付けられているすべてのセキュリティグループのすべてのルールを評価します。

(参考)Amazon EC2 Linux インスタンス用ユーザーガイド「Linux インスタンスの Amazon EC2 セキュリティグループ」

上記はEC2のドキュメントですが、VPCのドキュメントにも、ほぼ同じ内容が記載されています。

セキュリティグループは、インスタンスの仮想ファイアウォールとして機能し、インバウンドトラフィックとアウトバウンドトラフィックをコントロールします。VPC 内でインスタンスを起動した場合、そのインスタンスには最大 5 つのセキュリティグループを割り当てることができます。セキュリティグループは、サブネットレベルでなくインスタンスレベルで動作します。このため、VPC 内のサブネット内のインスタンスごとに異なるセキュリティグループのセットに割り当てることができます。

(参考)Amazon VPC ユーザーガイド「VPC のセキュリティグループ」

箇条書きでピックアップすると、こんな感じでしょうか。

  • インスタンスの仮想ファイアウォールとして機能する。
  • インバウンドトラフィックとアウトバウンドトラフィックをコントロールする。
  • インスタンスの起動時に1つ以上のセキュリティグループを指定できる。
  • セキュリティグループを指定しない場合、Amazon EC2 はデフォルトのセキュリティグループを使用する。
  • セキュリティグループは、サブネットレベルでなくインスタンスレベルで動作する。

セキュリティグループはステートフルなので、例えば外部からのSSHを許可する際には、インバウンドにだけルールを記載すれば良いです。

また、セキュリティグループとは別に、ネットワークACLというものもあります。
こちらはVPCのドキュメントに次のとおり記載されています。

ネットワークアクセスコントロールリスト (ACL) は、1 つ以上のサブネットのインバウンドトラフィックとアウトバウンドトラフィックを制御するファイアウォールとして動作する、VPC 用のセキュリティのオプションレイヤーです。セキュリティの追加レイヤーを VPC に追加するには、セキュリティグループと同様のルールを指定したネットワーク ACL をセットアップできます。セキュリティグループとネットワーク ACL の違いの詳細については、「セキュリティグループとネットワーク ACL の比較」を参照してください。

(参考)Amazon VPC ユーザーガイド「ネットワーク ACL」

セキュリティグループとは違って、サブネットレベルで動作するものです。
リンク先のドキュメントに記載のとおり、ネットワークACLはステートレスなので、インとアウトにそれぞれルールを記載する必要があります。

AWSでよくある使い方としては、ネットワークACLはデフォルト設定の「全て許可」のままにしておき、セキュリティグループでインスタンスへのアクセス制御を行うことが多いです。

セキュリティグループのソースにセキュリティグループ

セキュリティグループのルールでは、ソースに特定のCIDRブロックが記載できるほかに、「セキュリティグループそのもの」を送信元として記載できます。

VPCを作成した時のデフォルトのセキュリティグループはソースに「自分自身のセキュリティグループ」が記載されています。
これはAWSならではのもので、ちょっと初めは理解が難しいかと思います。

デフォルトセキュリティグループの例

例えば、このセキュリティグループを同じVPC内の複数のインスタンスに設定すると、インスタンス間の通信がすべて許可されることになります。デフォルトのセキュリティグループは「すべてのトラフィック」がインバウンドルールで許可されているためです。

なんか、不思議ですよね?ドキュメントをよく読んでみると、次のような記載があります。

  • セキュリティグループはネットワークインターフェイスに関連付けられます。
  • 送信元は、他のセキュリティグループ、IPv4/IPv6 CIDR ブロック、単一の IPv4/IPv6 アドレス、プレフィックスリスト ID のいずれかです。
  • ルールの送信元として CIDR ブロックを指定すると、指定したプロトコルとポートの指定したアドレスからのトラフィックが許可されます。
  • セキュリティグループをルールの送信元として指定すると、指定したプロトコルとポートの送信元セキュリティグループに関連付けられたネットワークインターフェイスからのトラフィックが許可されます。

(参考)Amazon VPC ユーザーガイド「VPC のセキュリティグループ/セキュリティグループのルール」

はい。ネットワークインターフェイスに関連付けられ、ネットワークインターフェイスからのトラフィックが許可される。という大事なことが書いてありました。
セキュリティグループはインスタンスレベルで動作するものなんだけど、さらにその中でネットワークインターフェイスに関連付けられている。
ソースとして関連付けられた(複数の)ネットワークインターフェイスが許可される。とイメージできると、少しはわかったような気がします。

デフォルトセキュリティグループの設定イメージ

ソースを他のセキュリティグループで指定するパターン

セキュリティグループの指定方法には色々とありますが、ソースをCIDRブロックではなく、セキュリティグループで指定すると何が良いのでしょうか?

例えばこれまでは、AP-DB間の通信に必要なポートを開ける際、DB側はAPのIPアドレスを指定しておけば良かったです。
が、AWSではIPアドレスが可変であることを前提に考えなければいけません。

EC2であればオートスケールの際に、手動でセキュリティグループのIPを変更するなんてことが必要になっては困りますからね。
そこでセキュリティグループで指定しておけば、IPが変わってもセキュリティグループに関連付けられているネットワークインターフェイスが許可されるので大丈夫、ということになります。

次に例として、AP(EC2)側に、インバウンドに何も記載していないセキュリティグループを設定してみます。

AP側へ設定するセキュリティグループ:no-rule-sg

DB側には、そのセキュリティグループ名をソースとして許可します。

DB側へ設定するセキュリティグループ:***-mysql

イメージとしては次のような設定状況になります。

※インバウンドルールを記載。アウトバウンドはすべて許可です。

設定イメージ

これで、AP(EC2)からDBへのアクセスを試してみます。

EC2

# mysql -h ****************.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 8.0.17 Source distribution
 
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MySQL [(none)]>

つながりました。
DB側は、上記で記載された「送信元セキュリティグループに関連付けられたネットワークインターフェイス(この場合AP)からのトラフィックが許可」されているからですね。

他のパターンとしては、セキュリティグループのソースを自分のセキュリティグループにして、それをAPとDBどちらにも設定してもつながります。
ただ、この場合はAP側もMySQL用のポートが許可されているので、なんとなく気持ちが悪いですね。

APとDBに同じセキュリティグループを設定する例

まとめ

セキュリティグループはなんとなくでも使えるものですが、ドキュメントを改めて読み「ネットワークインターフェイスに関連付けられる」ということを初めて知りました。
ドキュメントはちゃんと読まないといけませんね・・・。

ソースをセキュリティグループで指定するパターンは、私がAWSを触り始めた頃によく理解しておらず、複数のインスタンスに複数のセキュリティグループを設定し、結果的に非常に分かりづらいことになってしまいました。。
今やり直せるなら、許可ソースに許可したいインスタンスに紐づいているセキュリティグループを設定するパターンをうまく活用して、シンプルな実装ができそうな気がします。

というわけで、セキュリティグループの基本と、ソースをセキュリティグループで指定するパターンについての説明でした。