前回の記事では、VPCとサブネットの基本概念について解説しました。本記事では、VPCのセキュリティを強化するための2つの重要なコンポーネントである「セキュリティグループ」と「ネットワークACL(NACL)」について詳しく解説します。両者の違いを正しく理解し、適切に組み合わせることで、AWSリソースを保護する多層防御を実現できます。
VPCにおけるトラフィック制御の全体像
VPCでは、複数のレイヤーでトラフィックを制御できます。セキュリティグループとネットワークACLは、その中核を担う2つのファイアウォール機能です。
graph TB
subgraph "VPC トラフィック制御の階層"
Internet((インターネット))
IGW[インターネットゲートウェイ]
subgraph "サブネット"
NACL[ネットワークACL<br/>サブネットレベル]
subgraph "EC2インスタンス"
SG[セキュリティグループ<br/>インスタンスレベル]
EC2[アプリケーション]
end
end
end
Internet --> IGW
IGW --> NACL
NACL --> SG
SG --> EC2トラフィックは外側から内側へ、インターネットゲートウェイ、ネットワークACL、セキュリティグループの順に評価されます。戻りのトラフィックは逆順で評価されます。
セキュリティグループの基本
セキュリティグループは、EC2インスタンスやRDSインスタンス、Lambda関数(VPC接続時)などのAWSリソースに対する仮想ファイアウォールです。インスタンスレベルで動作し、インバウンド(受信)およびアウトバウンド(送信)トラフィックを制御します。
セキュリティグループの特徴
セキュリティグループには以下の重要な特徴があります。
| 特徴 | 説明 |
|---|---|
| ステートフル | 許可されたインバウンド通信の戻りトラフィックは自動的に許可される |
| 許可ルールのみ | 明示的な拒否ルールは設定できない(許可されていない通信はすべて拒否) |
| ENIに適用 | インスタンスではなくElastic Network Interface(ENI)に関連付けられる |
| 複数適用可能 | 1つのインスタンスに最大5つのセキュリティグループを適用できる |
| VPCスコープ | セキュリティグループは作成したVPC内でのみ使用可能 |
デフォルトの動作
セキュリティグループを作成した際のデフォルト動作を理解することは重要です。
インバウンドルール(デフォルト)
- すべてのインバウンドトラフィックを拒否
- ルールを追加することで特定の通信を許可
アウトバウンドルール(デフォルト)
- すべてのアウトバウンドトラフィックを許可
- 必要に応じてルールを削除/変更して制限可能
graph LR
subgraph "セキュリティグループのデフォルト動作"
IN[インバウンド] -->|すべて拒否| SG[セキュリティグループ]
SG -->|すべて許可| OUT[アウトバウンド]
endステートフルの動作原理
セキュリティグループの最も重要な特徴は「ステートフル」であることです。これは、許可されたインバウンド通信に対する戻りのトラフィックが、アウトバウンドルールに関係なく自動的に許可されることを意味します。
sequenceDiagram
participant Client as クライアント
participant SG as セキュリティグループ
participant Server as Webサーバー
Client->>SG: HTTPリクエスト (ポート80)
Note over SG: インバウンドルールで<br/>ポート80を許可
SG->>Server: リクエスト転送
Server->>SG: HTTPレスポンス
Note over SG: ステートフル:<br/>戻りトラフィックは<br/>自動的に許可
SG->>Client: レスポンス転送例えば、インバウンドルールでHTTP(ポート80)を許可している場合、クライアントからのHTTPリクエストに対するサーバーからのレスポンスは、アウトバウンドルールを明示的に設定しなくても自動的に許可されます。
セキュリティグループルールの構成要素
セキュリティグループのルールは以下の要素で構成されます。
| 要素 | 説明 | 例 |
|---|---|---|
| タイプ | プロトコルとポートの組み合わせ | HTTP、SSH、カスタムTCPなど |
| プロトコル | 通信プロトコル | TCP、UDP、ICMP、すべて |
| ポート範囲 | 許可するポート番号 | 80、443、22、1024-65535 |
| ソース/宛先 | 通信元/通信先の指定 | IPアドレス、CIDRブロック、セキュリティグループID |
| 説明 | ルールの説明(任意) | Web access from ALB |
セキュリティグループの参照機能
セキュリティグループの強力な機能の1つが「セキュリティグループの参照」です。ソースや宛先にIPアドレスではなく、別のセキュリティグループIDを指定できます。
graph LR
subgraph "パブリックサブネット"
ALB[ALB<br/>sg-alb]
end
subgraph "プライベートサブネット"
Web[Webサーバー<br/>sg-web]
App[アプリサーバー<br/>sg-app]
DB[(RDS<br/>sg-db)]
end
ALB -->|ソース: sg-alb| Web
Web -->|ソース: sg-web| App
App -->|ソース: sg-app| DBこの機能には以下のメリットがあります。
動的なIPアドレス対応
Auto Scalingでインスタンスが増減しても、同じセキュリティグループに属していれば通信が許可されます。IPアドレスの変更を気にする必要がありません。
明確なアクセス制御
「ALBからのみWebサーバーへのアクセスを許可」「Webサーバーからのみアプリサーバーへのアクセスを許可」といった論理的なアクセス制御を実現できます。
管理の簡素化
IPアドレスの追加・削除が不要になり、セキュリティグループの管理が大幅に簡素化されます。
セキュリティグループの設計パターン
実際のシステムでよく使用されるセキュリティグループの設計パターンを紹介します。
3層アーキテクチャのセキュリティグループ設計
Webアプリケーションの典型的な3層構成(Web層、アプリ層、DB層)におけるセキュリティグループ設計例を示します。
graph TB
subgraph "インターネット"
Users((ユーザー))
end
subgraph "パブリックサブネット"
ALB[ALB<br/>sg-alb]
end
subgraph "プライベートサブネット - Web層"
Web1[Webサーバー1]
Web2[Webサーバー2]
end
subgraph "プライベートサブネット - App層"
App1[アプリサーバー1]
App2[アプリサーバー2]
end
subgraph "プライベートサブネット - DB層"
DB[(RDS)]
end
Users -->|HTTPS 443| ALB
ALB -->|HTTP 80| Web1
ALB -->|HTTP 80| Web2
Web1 -->|TCP 8080| App1
Web1 -->|TCP 8080| App2
Web2 -->|TCP 8080| App1
Web2 -->|TCP 8080| App2
App1 -->|TCP 3306| DB
App2 -->|TCP 3306| DBALB用セキュリティグループ(sg-alb)
| 方向 | タイプ | ポート | ソース/宛先 | 説明 |
|---|---|---|---|---|
| インバウンド | HTTPS | 443 | 0.0.0.0/0 | インターネットからのHTTPS |
| インバウンド | HTTP | 80 | 0.0.0.0/0 | インターネットからのHTTP(リダイレクト用) |
| アウトバウンド | HTTP | 80 | sg-web | Webサーバーへの転送 |
Webサーバー用セキュリティグループ(sg-web)
| 方向 | タイプ | ポート | ソース/宛先 | 説明 |
|---|---|---|---|---|
| インバウンド | HTTP | 80 | sg-alb | ALBからのトラフィック |
| アウトバウンド | カスタムTCP | 8080 | sg-app | アプリサーバーへの通信 |
| アウトバウンド | HTTPS | 443 | 0.0.0.0/0 | 外部APIへのアクセス |
アプリサーバー用セキュリティグループ(sg-app)
| 方向 | タイプ | ポート | ソース/宛先 | 説明 |
|---|---|---|---|---|
| インバウンド | カスタムTCP | 8080 | sg-web | Webサーバーからのリクエスト |
| アウトバウンド | MySQL/Aurora | 3306 | sg-db | データベースへの接続 |
| アウトバウンド | HTTPS | 443 | 0.0.0.0/0 | 外部サービスへのアクセス |
データベース用セキュリティグループ(sg-db)
| 方向 | タイプ | ポート | ソース/宛先 | 説明 |
|---|---|---|---|---|
| インバウンド | MySQL/Aurora | 3306 | sg-app | アプリサーバーからの接続 |
踏み台サーバー(Bastion Host)のセキュリティグループ
プライベートサブネット内のリソースにSSH接続するための踏み台サーバーのセキュリティグループ設計例です。
踏み台サーバー用セキュリティグループ(sg-bastion)
| 方向 | タイプ | ポート | ソース/宛先 | 説明 |
|---|---|---|---|---|
| インバウンド | SSH | 22 | 会社のグローバルIP/32 | 管理者からのSSH接続 |
| アウトバウンド | SSH | 22 | sg-web, sg-app | 内部サーバーへのSSH |
プライベートサブネットのサーバー(既存ルールに追加)
| 方向 | タイプ | ポート | ソース/宛先 | 説明 |
|---|---|---|---|---|
| インバウンド | SSH | 22 | sg-bastion | 踏み台サーバーからのSSH |
ネットワークACL(NACL)の基本
ネットワークACL(Network Access Control List)は、サブネットレベルで動作するファイアウォールです。セキュリティグループとは異なる特徴を持ち、補完的なセキュリティレイヤーとして機能します。
ネットワークACLの特徴
ネットワークACLの主要な特徴を以下に示します。
| 特徴 | 説明 |
|---|---|
| ステートレス | インバウンドとアウトバウンドの両方に明示的なルールが必要 |
| 許可/拒否ルール | 許可と拒否の両方のルールを設定可能 |
| サブネットに適用 | サブネット内のすべてのリソースに適用される |
| ルール番号による評価 | ルール番号の小さい順に評価され、最初にマッチしたルールが適用 |
| VPCごとにデフォルトACL | VPC作成時にデフォルトのネットワークACLが自動作成される |
デフォルトネットワークACLとカスタムネットワークACL
デフォルトネットワークACL
VPC作成時に自動的に作成されるデフォルトネットワークACLは、すべてのインバウンドおよびアウトバウンドトラフィックを許可します。
デフォルトネットワークACL - インバウンドルール:
| ルール番号 | タイプ | プロトコル | ポート | ソース | 許可/拒否 |
|-----------|---------|----------|---------|------------|---------|
| 100 | すべて | すべて | すべて | 0.0.0.0/0 | 許可 |
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 |
デフォルトネットワークACL - アウトバウンドルール:
| ルール番号 | タイプ | プロトコル | ポート | 宛先 | 許可/拒否 |
|-----------|---------|----------|---------|------------|---------|
| 100 | すべて | すべて | すべて | 0.0.0.0/0 | 許可 |
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 |
カスタムネットワークACL
新規作成したカスタムネットワークACLは、デフォルトですべてのトラフィックを拒否します。必要なルールを明示的に追加する必要があります。
カスタムネットワークACL(作成直後):
| ルール番号 | タイプ | プロトコル | ポート | ソース/宛先 | 許可/拒否 |
|-----------|---------|----------|---------|-------------|---------|
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 |
ステートレスの動作原理
ネットワークACLは「ステートレス」であるため、リクエストとレスポンスそれぞれに対してルールを設定する必要があります。
sequenceDiagram
participant Client as クライアント
participant NACL as ネットワークACL
participant Server as Webサーバー
Client->>NACL: HTTPリクエスト (宛先ポート80)
Note over NACL: インバウンドルールで<br/>ポート80を許可
NACL->>Server: リクエスト転送
Server->>NACL: HTTPレスポンス (送信元ポート80, 宛先ポート:エフェメラル)
Note over NACL: アウトバウンドルールで<br/>エフェメラルポートを許可<br/>(明示的に必要)
NACL->>Client: レスポンス転送ここで重要なのが「エフェメラルポート(一時ポート)」です。クライアントがサーバーに接続する際、クライアント側では1024-65535の範囲で動的にポートが割り当てられます。サーバーからのレスポンスはこのエフェメラルポート宛に送信されるため、アウトバウンドルールでエフェメラルポート範囲を許可する必要があります。
エフェメラルポートの範囲
エフェメラルポートの範囲はOSによって異なります。
| OS | エフェメラルポート範囲 |
|---|---|
| Linux | 32768-60999 |
| Windows Server | 49152-65535 |
| Amazon Linux / NAT Gateway | 1024-65535 |
AWSでは、1024-65535の範囲を許可することが推奨されています。
ネットワークACLルールの評価順序
ネットワークACLのルールは、ルール番号の小さい順に評価されます。最初にマッチしたルールが適用され、以降のルールは評価されません。
ルール評価の例:
| ルール番号 | タイプ | ポート | ソース | 許可/拒否 |
|-----------|---------|---------|-----------------|---------|
| 100 | SSH | 22 | 10.0.0.0/8 | 許可 |
| 110 | SSH | 22 | 0.0.0.0/0 | 拒否 |
| 120 | HTTP | 80 | 0.0.0.0/0 | 許可 |
| * | すべて | すべて | 0.0.0.0/0 | 拒否 |
この例では以下のように評価されます。
- 10.0.0.0/8からのSSH(ポート22)→ ルール100にマッチ → 許可
- その他のIPからのSSH → ルール110にマッチ → 拒否
- どこからでもHTTP(ポート80)→ ルール120にマッチ → 許可
- その他すべて → ルール*にマッチ → 拒否
ルール番号は100、110、120のように間隔を空けて設定することが推奨されます。これにより、後から新しいルールを挿入しやすくなります。
セキュリティグループとNACLの比較
両者の違いを理解することは、適切なセキュリティ設計に不可欠です。
機能比較表
| 比較項目 | セキュリティグループ | ネットワークACL |
|---|---|---|
| 適用レベル | インスタンス(ENI) | サブネット |
| ステート | ステートフル | ステートレス |
| ルールタイプ | 許可のみ | 許可と拒否 |
| デフォルト(インバウンド) | すべて拒否 | すべて許可(デフォルトACL) |
| デフォルト(アウトバウンド) | すべて許可 | すべて許可(デフォルトACL) |
| ルール評価 | すべてのルールを評価 | 番号順に評価、最初のマッチで終了 |
| 適用タイミング | インスタンス起動時に指定 | サブネットに自動適用 |
動作の違いを図解
graph TB
subgraph "セキュリティグループ(ステートフル)"
direction LR
SG_IN[インバウンド許可] --> SG_AUTO[戻りトラフィック<br/>自動許可]
end
subgraph "ネットワークACL(ステートレス)"
direction LR
NACL_IN[インバウンド許可] --> NACL_OUT[アウトバウンドも<br/>明示的に許可が必要]
endユースケースの使い分け
セキュリティグループが適している場面
- アプリケーション固有のアクセス制御(例:WebサーバーへのHTTPアクセス許可)
- インスタンス間の通信制御
- 動的に変化するリソース(Auto Scaling)のアクセス制御
- 日常的なセキュリティ管理
ネットワークACLが適している場面
- サブネット全体に対するベースラインポリシーの適用
- 特定のIPアドレスからのアクセスを完全にブロック
- DDoS攻撃への緊急対応(悪意のあるIPを即座にブロック)
- コンプライアンス要件による追加の防御層
多層防御の実装
セキュリティグループとネットワークACLを組み合わせた多層防御(Defense in Depth)の実装例を紹介します。
多層防御のアーキテクチャ
graph TB
subgraph "インターネット"
Internet((悪意のあるIP<br/>203.0.113.0/24))
Users((正規ユーザー))
end
subgraph "VPC"
subgraph "パブリックサブネット"
NACL_PUB[NACL<br/>悪意のあるIPを拒否]
subgraph "ALB"
SG_ALB[SG<br/>HTTPS許可]
end
end
subgraph "プライベートサブネット"
NACL_PRI[NACL<br/>VPC内通信のみ許可]
subgraph "Webサーバー"
SG_WEB[SG<br/>ALBからのみ許可]
end
end
end
Internet -->|ブロック| NACL_PUB
Users --> NACL_PUB
NACL_PUB --> SG_ALB
SG_ALB --> NACL_PRI
NACL_PRI --> SG_WEBパブリックサブネット用ネットワークACL設計
パブリックサブネットでは、インターネットからのアクセスを許可しつつ、必要なトラフィックのみに制限します。
パブリックサブネット用NACL - インバウンドルール:
| ルール番号 | タイプ | プロトコル | ポート | ソース | 許可/拒否 | 説明 |
|-----------|---------|----------|------------|-----------------|---------|------|
| 50 | すべて | すべて | すべて | 203.0.113.0/24 | 拒否 | 悪意のあるIPをブロック |
| 100 | HTTPS | TCP | 443 | 0.0.0.0/0 | 許可 | インターネットからのHTTPS |
| 110 | HTTP | TCP | 80 | 0.0.0.0/0 | 許可 | インターネットからのHTTP |
| 120 | カスタム | TCP | 1024-65535 | 0.0.0.0/0 | 許可 | 戻りトラフィック(エフェメラル) |
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 | それ以外を拒否 |
パブリックサブネット用NACL - アウトバウンドルール:
| ルール番号 | タイプ | プロトコル | ポート | 宛先 | 許可/拒否 | 説明 |
|-----------|---------|----------|------------|-----------------|---------|------|
| 100 | HTTPS | TCP | 443 | 0.0.0.0/0 | 許可 | 外部APIへのアクセス |
| 110 | HTTP | TCP | 80 | 10.0.0.0/16 | 許可 | VPC内Webサーバーへ |
| 120 | カスタム | TCP | 1024-65535 | 0.0.0.0/0 | 許可 | レスポンス(エフェメラル) |
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 | それ以外を拒否 |
プライベートサブネット用ネットワークACL設計
プライベートサブネットでは、VPC内部からの通信に限定し、より厳格なアクセス制御を適用します。
プライベートサブネット用NACL - インバウンドルール:
| ルール番号 | タイプ | プロトコル | ポート | ソース | 許可/拒否 | 説明 |
|-----------|---------|----------|------------|-----------------|---------|------|
| 100 | HTTP | TCP | 80 | 10.0.1.0/24 | 許可 | パブリックサブネットからのHTTP |
| 110 | HTTP | TCP | 80 | 10.0.2.0/24 | 許可 | パブリックサブネット(AZ-c)から |
| 120 | カスタム | TCP | 1024-65535 | 0.0.0.0/0 | 許可 | 戻りトラフィック |
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 | それ以外を拒否 |
プライベートサブネット用NACL - アウトバウンドルール:
| ルール番号 | タイプ | プロトコル | ポート | 宛先 | 許可/拒否 | 説明 |
|-----------|---------|----------|------------|-----------------|---------|------|
| 100 | MySQL | TCP | 3306 | 10.0.21.0/24 | 許可 | DBサブネットへの接続 |
| 110 | HTTPS | TCP | 443 | 0.0.0.0/0 | 許可 | NAT経由で外部アクセス |
| 120 | カスタム | TCP | 1024-65535 | 10.0.0.0/16 | 許可 | VPC内レスポンス |
| * | すべて | すべて | すべて | 0.0.0.0/0 | 拒否 | それ以外を拒否 |
セキュリティグループとNACLの設定手順
AWSマネジメントコンソールおよびAWS CLIを使用した設定手順を紹介します。
コンソールでのセキュリティグループ作成
- VPCダッシュボードで「セキュリティグループ」を選択
- 「セキュリティグループを作成」をクリック
- 以下の情報を入力
| 設定項目 | 設定値の例 |
|---|---|
| セキュリティグループ名 | web-server-sg |
| 説明 | Security group for web servers |
| VPC | 対象のVPCを選択 |
- インバウンドルールを追加
- 必要に応じてアウトバウンドルールを編集
- 「セキュリティグループを作成」をクリック
AWS CLIでのセキュリティグループ作成
|
|
AWS CLIでのネットワークACL作成
|
|
トラブルシューティング
セキュリティグループとNACLに関連する一般的な問題と解決方法を紹介します。
通信できない場合のチェックポイント
通信が確立できない場合、以下の順序で確認します。
graph TD
A[通信エラー発生] --> B{ネットワークACL<br/>インバウンド許可?}
B -->|No| C[NACLルール追加]
B -->|Yes| D{セキュリティグループ<br/>インバウンド許可?}
D -->|No| E[SGルール追加]
D -->|Yes| F{ネットワークACL<br/>アウトバウンド許可?}
F -->|No| G[NACLアウトバウンド<br/>ルール追加]
F -->|Yes| H{エフェメラルポート<br/>許可?}
H -->|No| I[1024-65535を許可]
H -->|Yes| J[他の原因を調査]よくある問題と解決策
問題1: SSH接続ができない
| チェック項目 | 確認内容 |
|---|---|
| セキュリティグループ | インバウンドでポート22が許可されているか |
| ソースIPアドレス | 接続元のIPアドレスが正しく指定されているか |
| ネットワークACL | インバウンドでポート22、アウトバウンドでエフェメラルポートが許可されているか |
| ルートテーブル | インターネットゲートウェイへのルートがあるか(パブリックサブネットの場合) |
問題2: Webサーバーにアクセスできるが、レスポンスが返らない
この問題は、NACLのアウトバウンドルールでエフェメラルポートが許可されていない場合に発生します。アウトバウンドルールに1024-65535を許可するルールを追加してください。
問題3: RDSに接続できない
| チェック項目 | 確認内容 |
|---|---|
| セキュリティグループ | RDSのSGで、接続元のSGまたはIPからの3306(MySQL)/5432(PostgreSQL)が許可されているか |
| サブネット | RDSと接続元が通信可能なサブネットにあるか |
| ネットワークACL | 該当ポートがインバウンド/アウトバウンドで許可されているか |
VPCフローログを使用したトラブルシューティング
VPCフローログを有効にすると、ネットワークインターフェイスを通過するIPトラフィックの情報をキャプチャできます。これは通信問題のトラブルシューティングに非常に有効です。
フローログレコードの例:
2 123456789012 eni-abc123de 10.0.1.5 10.0.2.10 443 49152 6 25 20000 1620000000 1620000060 ACCEPT OK
2 123456789012 eni-abc123de 203.0.113.5 10.0.1.5 22 22 6 1 40 1620000000 1620000060 REJECT OK
| フィールド | 説明 |
|---|---|
| ACCEPT | トラフィックが許可された |
| REJECT | トラフィックが拒否された |
REJECTが記録されている場合、セキュリティグループまたはNACLでブロックされています。ソースIP、宛先IP、ポート番号を確認し、適切なルールを追加してください。
ベストプラクティス
セキュリティグループとNACLを運用する際のベストプラクティスをまとめます。
セキュリティグループのベストプラクティス
最小権限の原則を適用する
- 必要な通信のみを許可し、それ以外はすべて拒否する
- 0.0.0.0/0からのアクセスは本当に必要な場合のみ許可する
- 可能な限りセキュリティグループの参照を使用する
用途ごとにセキュリティグループを分ける
- Web層、アプリ層、DB層など、役割ごとにセキュリティグループを作成する
- 共通のルールは別のセキュリティグループにまとめ、複数適用する
説明を必ず記載する
- すべてのルールに説明を追加し、なぜそのルールが必要なのかを記録する
- セキュリティグループ自体にも明確な説明を付ける
定期的な棚卸しを行う
- 使用されていないセキュリティグループを削除する
- 不要になったルールを削除する
- 過剰に広い許可(0.0.0.0/0など)を見直す
ネットワークACLのベストプラクティス
デフォルトACLに依存しない
- カスタムACLを作成し、明示的なルールを設定する
- デフォルトACLはすべて許可のため、セキュリティ上のリスクがある
ルール番号に余裕を持たせる
- ルール番号は100、200、300のように間隔を空ける
- 後からルールを挿入しやすくなる
セキュリティグループをメインに使う
- 日常的なアクセス制御はセキュリティグループで行う
- NACLはサブネット全体のベースラインポリシーや緊急時のIPブロックに使用する
ステートレスを忘れない
- インバウンドを許可したら、対応するアウトバウンド(エフェメラルポート)も許可する
- アウトバウンドを許可したら、対応するインバウンド(エフェメラルポート)も許可する
まとめ
本記事では、AWSのセキュリティグループとネットワークACLについて詳しく解説しました。
- セキュリティグループはインスタンスレベルで動作するステートフルファイアウォール
- ネットワークACLはサブネットレベルで動作するステートレスファイアウォール
- セキュリティグループは許可ルールのみ、NACLは許可/拒否の両方を設定可能
- ステートレスのNACLではエフェメラルポートの許可が必要
- 両者を組み合わせた多層防御でセキュリティを強化する
次回の記事では、インターネットゲートウェイとNATゲートウェイを使用したインターネット接続の設計について解説します。