Security Group はステートフル、NACL はステートレス - この違いが生まれた設計判断
Security Group が接続追跡でステートフルに動作する仕組み、NACL がステートレスである理由、エフェメラルポートの落とし穴、両者を組み合わせた多層防御の設計パターンを解説します。
ステートフルとステートレスの違い
Security Group はステートフルなファイアウォールです。インバウンドルールで許可されたリクエストに対するレスポンスは、アウトバウンドルールに関係なく自動的に許可されます。逆に、アウトバウンドルールで許可されたリクエストに対するレスポンスも、インバウンドルールに関係なく自動的に許可されます。NACL (Network Access Control List) はステートレスなファイアウォールです。インバウンドとアウトバウンドのルールが独立して評価されます。インバウンドで許可されたリクエストに対するレスポンスであっても、アウトバウンドルールで明示的に許可されていなければブロックされます。この違いは、実装レベルでの根本的な差異に起因します。Security Group は接続追跡 (Connection Tracking) テーブルを維持しており、各接続の状態 (送信元 IP、送信先 IP、ポート、プロトコル) を記録しています。レスポンスパケットが到着すると、接続追跡テーブルと照合し、既存の接続に属するパケットであれば自動的に許可します。NACL は接続追跡テーブルを持たず、各パケットを独立して評価します。
なぜ 2 種類のファイアウォールが存在するのか
Security Group だけで十分に見えますが、NACL が存在する理由は多層防御 (Defense in Depth) の原則です。Security Group はインスタンスレベル (ENI レベル) で動作し、NACL はサブネットレベルで動作します。この 2 つのレイヤーが異なるレベルで防御を提供します。Security Group が侵害された場合 (たとえば、IAM 権限を持つ攻撃者が Security Group のルールを変更した場合)、NACL がバックアップとして機能します。NACL はサブネット全体に適用されるため、個々のインスタンスの Security Group が変更されても、NACL のルールが防御を維持します。もう一つの理由は、明示的な Deny の必要性です。Security Group は許可ルールのみを定義でき、拒否ルールを定義できません。特定の IP アドレスからのアクセスを明示的にブロックしたい場合、Security Group では実現できません。NACL は許可ルールと拒否ルールの両方を定義でき、ルール番号の順序で評価されるため、特定の IP アドレスを明示的にブロックできます。
NACL のエフェメラルポートの落とし穴
NACL がステートレスであることに起因する最も多い設定ミスは、エフェメラルポート (一時ポート) の許可漏れです。クライアントがサーバーに接続する際、クライアント側のソースポートはオペレーティングシステムが動的に割り当てるエフェメラルポートを使用します。Linux では 32768〜60999、Windows では 49152〜65535 の範囲です。NACL のアウトバウンドルールで HTTP (ポート 80) を許可しても、レスポンスはクライアントのエフェメラルポートに返されます。NACL のインバウンドルールでエフェメラルポートの範囲を許可していなければ、レスポンスがブロックされます。Security Group ではこの問題は発生しません。ステートフルであるため、アウトバウンドで許可されたリクエストに対するレスポンスは自動的に許可されます。NACL を使用する場合は、インバウンドとアウトバウンドの両方でエフェメラルポートの範囲 (1024〜65535) を許可するのが一般的です。この広い範囲の許可に抵抗がある場合は、NACL ではなく Security Group で細かい制御を行い、NACL はサブネットレベルの粗い制御に留めるのが実用的です。
Security Group の接続追跡の詳細
Security Group の接続追跡には、追跡される接続と追跡されない接続があります。すべてのトラフィック (0.0.0.0/0) を許可するルールがインバウンドとアウトバウンドの両方に設定されている場合、接続追跡は行われません。追跡が不要なためです。この場合、接続追跡のオーバーヘッドがなくなり、パフォーマンスが向上します。接続追跡テーブルにはサイズの上限があります。デフォルトでは、ENI あたり最大 65,535 の追跡接続を保持できます。この上限に達すると、新しい接続が確立できなくなります。大量の短命な接続を処理するワークロード (ロードバランサーの背後のインスタンスなど) では、接続追跡テーブルの枯渇に注意が必要です。CloudWatch メトリクスの ConnTrackAllowanceExceeded で、接続追跡テーブルの枯渇を監視できます。接続追跡のタイムアウトは、TCP の確立済み接続で 5 日間、UDP で 180 秒、ICMP で 30 秒です。タイムアウトした接続はテーブルから削除されます。
実践的な多層防御の設計パターン
Security Group と NACL を組み合わせた実践的な設計パターンを紹介します。パブリックサブネットの ALB には、Security Group でインバウンド HTTP/HTTPS (0.0.0.0/0) を許可し、NACL はデフォルト (すべて許可) のままにします。ALB は公開サービスであるため、NACL で制限する必要はありません。プライベートサブネットのアプリケーションサーバーには、Security Group でインバウンドを ALB の Security Group からのみ許可し、NACL でインバウンドを ALB のサブネットの CIDR からのみ許可します。Security Group が ALB からのトラフィックのみを許可し、NACL がサブネットレベルでバックアップの防御を提供します。データベースサブネットには、Security Group でインバウンドをアプリケーションサーバーの Security Group からのみ許可し、NACL でインバウンドをアプリケーションサブネットの CIDR からのみ許可します。特定の IP アドレスからの攻撃を検知した場合は、NACL の拒否ルールで即座にブロックできます。Security Group の変更はインスタンスごとですが、NACL の変更はサブネット全体に即座に適用されるため、緊急対応に適しています。ネットワークセキュリティの設計を体系的に学ぶには、専門書籍 (Amazon)が参考になります。