AWS学びなおし(+TF)_セキュリティグループ

2025/02/24に公開

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

AWSにおけるセキュリティグループは、仮想ファイアウォールとして機能し、EC2インスタンス、RDSインスタンス、ElastiCacheクラスタなど、AWSリソースへのインバウンド(進入)およびアウトバウンド(退出)トラフィックを制御します。

主な特徴

  • インスタンスレベルのファイアウォール: 各インスタンスにアタッチされ、インスタンス単位でトラフィックを制御します。
  • ステートフルファイアウォール: インバウンドルールで許可されたトラフィックに対するアウトバウンドレスポンスは、明示的なアウトバウンドルールなしに自動的に許可されます。逆も同様です。
  • 許可ルールのみ: デフォルトでは全てのトラフィックが拒否され、許可するトラフィックのみをルールとして定義します。(明示的な拒否ルールは設定できません)
  • 柔軟なルール設定: プロトコル (TCP, UDP, ICMP)、ポート範囲、送信元/送信先 (IPアドレス範囲、プレフィックスリスト、セキュリティグループID) を指定できます。
  • 動的なルール変更: セキュリティグループのルールは、インスタンスを停止・再起動することなく動的に変更・適用できます。
  • 複数のセキュリティグループ: 1つのインスタンスに複数のセキュリティグループを関連付けることが可能です。(最大5つ、変更可能)
  • デフォルトセキュリティグループ: VPC作成時に自動的に作成されるセキュリティグループです。全てのアウトバウンドを許可し、同じセキュリティグループからのインバウンドを許可するルールが初期設定されています。
  • アウトバウンドルールの重要性: デフォルトでは全て許可されていますが、最小権限の原則に基づき、必要なアウトバウンドトラフィックのみを許可するように設定することが推奨されます。

セキュリティグループの構成要素

  • インバウンドルール (Inbound Rules): インスタンスへの進入トラフィックを制御します。

    • タイプ: ルールの種類 (例: HTTP, SSH, カスタムTCPルール)
    • プロトコル: 通信プロトコル (TCP, UDP, ICMP, ALL)
    • ポート範囲: 受信ポートの範囲 (単一ポート、ポート範囲、ALL)
    • 送信元: トラフィックの送信元 (IPアドレス範囲、プレフィックスリスト、別のセキュリティグループID)
    • 説明: ルールの説明 (任意)
  • アウトバウンドルール (Outbound Rules): インスタンスからの退出トラフィックを制御します。

    • タイプ: ルールの種類 (例: HTTP, HTTPS, カスタムTCPルール)
    • プロトコル: 通信プロトコル (TCP, UDP, ICMP, ALL)
    • ポート範囲: 送信ポートの範囲 (単一ポート、ポート範囲、ALL)
    • 送信先: トラフィックの送信先 (IPアドレス範囲、プレフィックスリスト、別のセキュリティグループID)
    • 説明: ルールの説明 (任意)

セキュリティグループのルール評価

  1. インバウンドルール: インスタンスへのトラフィックが到着すると、セキュリティグループのインバウンドルールが上から順に評価されます。
  2. 許可ルールに一致: いずれかの許可ルールに一致した場合、トラフィックは許可されます。
  3. 一致するルールがない場合: いずれの許可ルールにも一致しない場合、トラフィックは拒否されます。(明示的な拒否ルールは存在しません)
  4. アウトバウンドルール: インスタンスからのトラフィック送信時、アウトバウンドルールが同様に評価されます。
  5. ステートフル性: インバウンドで許可されたトラフィックに対するレスポンスは、アウトバウンドルールに関わらず自動的に許可されます。

セキュリティグループとネットワークACL (NACL) の違い

セキュリティグループとネットワークACLはどちらもAWSのネットワークセキュリティ機能ですが、以下の点で異なります。

特徴 セキュリティグループ ネットワークACL (NACL)
レイヤー インスタンスレベル (レイヤー4) サブネットレベル (レイヤー3, 4)
ステートフル性 ステートフル ステートレス
デフォルト動作 全て拒否 (許可ルールのみ設定) 全て許可 (拒否ルールも設定可能)
ルール評価 許可ルールのみ、一致したら許可、それ以外は拒否 ルール番号順に評価、許可/拒否ルールで制御
ルールの種類 許可ルールのみ 許可ルール、拒否ルール
適用対象 EC2インスタンス、RDSインスタンスなど サブネット
実務での使用頻度 非常に高い セキュリティグループほど頻繁ではない (補完的)

セキュリティグループのメリット

  • 柔軟なアクセス制御: 細かいルール設定により、必要なトラフィックのみを許可できます。
  • 容易な管理: AWS Management Console、CLI、SDK、Terraformなどで簡単に設定・管理できます。
  • セキュリティ強化: 不要なポートを閉じることで、セキュリティリスクを低減できます。
  • マイクロセグメンテーション: アプリケーションやワークロードごとにセキュリティグループを分割し、より細かいアクセス制御を実現できます。

【実務レベルの内容と重要事項】

  • 最小権限の原則の徹底:

    • 必要最低限のポート、プロトコル、送信元/送信先のみを許可するルールを設定します。
    • 「ALL Traffic」「0.0.0.0/0」のような広すぎるルールは極力避けるべきです。
    • 例:SSH (ポート22) アクセスは、特定のIPアドレス範囲 (例: 社内ネットワーク) または踏み台サーバーのセキュリティグループからのアクセスのみに限定する。
    • 例:Webサーバー (ポート80, 443) は、ロードバランサーのセキュリティグループまたは特定のプレフィックスリストからのアクセスのみ許可する。
  • セキュリティグループの見直しと定期的なメンテナンス:

    • 不要になったルールや過剰なルールは定期的に見直し、削除または修正します。
    • セキュリティ要件の変更に合わせて、ルールを適切に更新します。
    • 例:プロジェクト終了時に、関連するセキュリティグループのルールを再評価し、不要なルールを削除する。
  • ポート番号とプロトコルの適切な選択:

    • よく使用されるポート番号 (80, 443, 22, 3389, 5432 など) の意味とセキュリティリスクを理解し、必要なポートのみを開放します。
    • プロトコル (TCP, UDP, ICMP) の違いを理解し、適切なプロトコルを選択します。
    • 例:RDP (ポート3389) は、必要な場合に限り、かつアクセス元を限定して許可する。
  • 送信元/送信先の指定方法の考慮:

    • IPアドレス範囲 (CIDR): 特定のIPアドレス範囲からのアクセスを許可する場合に使用します。
    • プレフィックスリスト: AWSが管理するIPアドレス範囲のリスト (例: AWSサービス、リージョン) を利用できます。動的に変化するAWSサービスのIP範囲を管理するのに便利です。
    • セキュリティグループID: 別のセキュリティグループからのアクセスを許可する場合に使用します。VPC内で柔軟なアクセス制御を実現できます。
  • セキュリティグループの設計における考慮事項:

    • アプリケーションの構成: 3層構成 (Web, App, DB) など、アプリケーションの構成に応じて適切なセキュリティグループを設計します。
    • ネットワーク構成: VPCの構成 (パブリックサブネット、プライベートサブネット) やルーティングを考慮して、セキュリティグループを設計します。
    • マイクロサービスアーキテクチャ: サービス間の通信をセキュリティグループで制御することで、マイクロセグメンテーションを実現できます。
  • セキュリティグループの名前付け規則:

    • セキュリティグループの役割や対象リソースが分かりやすい名前を付けます。
    • 例: sg-web-servers, sg-db-servers, sg-bastion-host など
    • タグも活用して、セキュリティグループの管理を容易にします。
  • トラブルシューティング:

    • インスタンスに接続できない場合、まずセキュリティグループの設定 (インバウンドルール、アウトバウンドルール) を確認します。
    • VPC Flow Logs を有効にすることで、セキュリティグループで許可/拒否されたトラフィックのログを確認できます。
    • telnet, nc, traceroute などのネットワークツールを使って、接続性を確認します。
  • デフォルトセキュリティグループの扱い:

    • デフォルトセキュリティグループは初期設定が緩いため、本番環境ではカスタムセキュリティグループを作成して利用することを強く推奨します。
    • デフォルトセキュリティグループは、テスト環境や一時的な利用に限定することを検討してください。
  • セキュリティグループの制限事項:

    • セキュリティグループごとに設定できるルールの数には上限があります。(インバウンド/アウトバウンドそれぞれ60ルール、変更可能)
    • 1つのインスタンスにアタッチできるセキュリティグループの数にも上限があります。(5つ、変更可能)
    • 大規模な環境では、これらの制限事項を考慮した設計が必要です。

【実務でどの程度使用されるのか】

セキュリティグループは、AWS環境において非常に高い頻度で使用されます。ほぼ全てのAWSリソース (EC2, RDS, ElastiCache, Lambda (VPC内), ECS, EKS など) で利用され、AWSにおける基本的なネットワークセキュリティ対策として不可欠な存在です。

実務での使用例

  • EC2インスタンスの保護: Webサーバー、アプリケーションサーバー、データベースサーバーなどのEC2インスタンスへのアクセス制御に利用されます。
  • RDSインスタンスの保護: データベースへのアクセスを、アプリケーションサーバーやBastionホストからのアクセスのみに限定するために利用されます。
  • ElastiCacheクラスタの保護: キャッシュクラスタへのアクセスを、アプリケーションサーバーからのアクセスのみに限定するために利用されます。
  • Lambda関数の保護 (VPC内): VPC内のLambda関数へのアクセス制御に利用されます。
  • ECS/EKSクラスターの保護: コンテナ化されたアプリケーションへのアクセス制御に利用されます。
  • マイクロサービス環境におけるマイクロセグメンテーション: サービス間の通信をセキュリティグループで制御し、セキュリティ境界を明確化するために利用されます。
  • 踏み台サーバー (Bastion Host) の構築: 踏み台サーバーを経由したインスタンスへのアクセス制御に利用されます。

セキュリティグループは、ネットワークセキュリティの最初の防衛線として非常に重要であり、AWS環境のセキュリティを確保する上で欠かせないコンポーネントです。クラウドエンジニアとして、セキュリティグループの設計、設定、運用に関する深い知識は必須スキルと言えるでしょう。

【terraformのコードで記述する場合の基本的内容と実務レベルの内容】

Terraform コード (基本)

resource "aws_security_group" "example" {
  name        = "example-sg"
  description = "Example Security Group"
  vpc_id      = aws_vpc.main.id # VPC ID を指定

  ingress { # インバウンドルール
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"] # アクセス元IPアドレス範囲
    description = "SSH access from internal network"
  }

  egress { # アウトバウンドルール
    from_port   = 0
    to_port     = 0
    protocol    = "-1" # ALL protocols
    cidr_blocks = ["0.0.0.0/0"] # 全ての送信先を許可
    description = "Allow all outbound traffic"
  }

  tags = {
    Name = "example-security-group"
  }
}

Terraform コード (実務レベル)

resource "aws_security_group" "web_sg" {
  name        = "web-sg"
  description = "Security Group for Web Servers"
  vpc_id      = var.vpc_id # 変数で VPC ID を指定

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = var.public_cidr_blocks # 変数で公開CIDR範囲を指定
    description = "HTTP access from public"
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = var.public_cidr_blocks # 変数で公開CIDR範囲を指定
    description = "HTTPS access from public"
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    security_groups = [aws_security_group.bastion_sg.id] # Bastion SG からの SSH アクセス
    description = "SSH access from Bastion SG"
  }

  egress { # アウトバウンドは必要最低限に絞る (例: HTTPS のみ許可)
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "HTTPS outbound"
  }

  egress { # DNS (53/UDP)
    from_port   = 53
    to_port     = 53
    protocol    = "udp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "DNS outbound"
  }


  tags = local.common_tags # ローカル変数でタグを管理
}

実務レベルでのポイント

  • 変数の活用: VPC ID、CIDRブロック、ポート番号などを変数化することで、コードの再利用性と可読性を高めます。
  • モジュールの利用: セキュリティグループの設定をモジュール化することで、共通化と管理性を向上させます。
  • locals ブロックの利用: タグなど、複数のリソースで共通して利用する値を locals ブロックで定義することで、DRY原則 (Don't Repeat Yourself) を守ります。
  • データソースの利用: 既存のセキュリティグループIDやプレフィックスリストなどを data ブロックで参照することで、動的な設定や外部参照を実現します。
  • セキュリティグループルールの可読性: description 属性を適切に記述し、ルールの意図を明確にします。
  • 最小権限のアウトバウンド設定: アウトバウンドルールはデフォルトの ALL を避け、必要なトラフィックのみを許可するように設定します。(例: HTTPS, DNS など)
  • セキュリティグループ間の参照: security_groups 属性を利用して、セキュリティグループ間でアクセスを許可することで、柔軟なアクセス制御を実現します。(例: WebサーバーからAppサーバーへのアクセス許可)
  • Terraform fmt, validate の実行: コードのフォーマットとバリデーションを自動化することで、コード品質を維持します。
  • Terraform Cloud/Enterprise の利用: 状態管理、コラボレーション、バージョン管理などを効率化するために、Terraform Cloud や Terraform Enterprise の利用を検討します。

Terraform を利用するメリット

  • Infrastructure as Code (IaC): インフラ構成をコードとして管理することで、バージョン管理、再現性、自動化が容易になります。
  • 構成管理の効率化: 大規模な環境でも、セキュリティグループの設定を効率的に管理できます。
  • 変更管理の容易化: 変更履歴がコードとして追跡可能になり、変更のレビューやロールバックが容易になります。
  • 自動化: CI/CDパイプラインに組み込むことで、セキュリティグループのデプロイや変更を自動化できます。

Terraform を活用することで、セキュリティグループの管理を効率化し、インフラ全体のセキュリティレベルを向上させることができます。実務においては、Terraform などの IaC ツールを利用したセキュリティグループの管理が標準的なプラクティスとなっています。

Discussion