• トップ
  • ブログ一覧
  • AWS Network Firewallを試してみた
  • AWS Network Firewallを試してみた

    あだっちー(エンジニア)あだっちー(エンジニア)
    2023.11.24

    IT技術

    はじめに

    今回はAWSサービスのNetwork Firewallについて触れていこうと思います。
    Network Firewallは、ネットワークトラフィックを細かく制御するためのファイアウォールルールを設定できるサービスです。通常、AWSでトラフィックを制御する際にはセキュリティグループやWAFを使用しますが、FQDNを用いたトラフィック制御やより詳細な制御が必要な場合、Network Firewallが適しています。公式サイトでのユースケースは、このように紹介されています。

    1.  インバウンドのインターネットトラフィックを検査
    2. アウトバウンドトラフィックをフィルタリングする
    3. インバウンドのインターネットトラフィックの侵入を防ぐ
    4. AWS Direct Connect と VPN のトラフィックを保護する

    AWS Network Firewallの特徴

    Network Firewallの主な特徴です。

    ステートフルおよびステートレスのルールエンジン

    • ステートフルルールエンジン: このエンジンはネットワークトラフィックのパターンを把握し、過去のトラフィックとの関連性を認識します。例えば、あるウェブサイトと安全に接続が確立された後にのみ、情報の送受信を許可するようなルールを作ることができるということです。
    • ステートレスルールエンジン: こちらは各ネットワークパケットを個別に評価し、アクセスの許可や拒否を決定します。このタイプのルールは迅速で、IPアドレスやポート番号に基づいたフィルタリングに主に用いられます。こちらは特定のアドレスからのデータのみを受け入れるようなシンプルなルールに使用されます。

    フルマネージド型のサービス

    • スケーラビリティ: AWS Network Firewallはフルマネージド型のサービスなので、ネットワークトラフィックの増減に応じて自動的にスケールアップ・ダウンします。このため、ユーザーはインフラストラクチャのスケーリングについて心配する必要がありません。
    • メンテナンスフリー: セキュリティの更新やパフォーマンスの向上に関する作業はAWSによって自動的に行われるのでメンテナンス作業に時間を割く必要がないです。

    ネットワーク構成

    AWS Network Firewallを導入する際、まず注意しなければならないのは、そのネットワーク構成が通常のものとは異なる点です!
    Network Firewallのエンドポイントはサブネットに作成する必要があります。

    通常のInternet Gateway 経由で利用する際の基本構成(Multi-AZ 構成)はこんな感じですよね。

    network_rooting_1

    Network Firewallを設置する場合は、下記のようにルーティングする必要があります。

    network_rooting_2

    引用:https://aws.amazon.com/jp/blogs/networking-and-content-delivery/deployment-models-for-aws-network-firewall/

    新しい構成では、Firewall Subnet(ファイアウォール専用のサブネット)にエンドポイントを配置し、このエンドポイントをインターネットゲートウェイに接続します。
    インターネットからの返信トラフィックは、インターネットゲートウェイに設定されたルーティングテーブルを経由して、ファイヤーウォールのElastic Network Interface(ENI)に送り返されます。

    公式ドキュメントによると AWS Network Firewall を紐づけた(エンドポイントを作成した)サブネットごとに料金が発生するので注意が必要です。

    この金額については後ほど詳しく説明しますが結構高いです。。。
    今回は個人で検証するだけなのでシングルAZで進めていきます。

    Network Firewallの基本構成要素

    Network Firewallには3つの構成要素があります。
    作成前に理解しておいた方が良いのでざっくり解説した後にそれぞれを実際に設定していきます。

    Firewall(ファイアウォール本体)

    Network Firewallの核となる部分です。サブネット内にFirewallエンドポイントが作成され、ネットワークのパケットがこのエンドポイントを通過するようになります。

    Firewall Policy(ファイアウォールポリシー)

    Rule Groupの集合体であり、特定のFirewallに適用されるポリシーです。
    同じFirewall Policyを複数のFirewallに適用することが可能です。

    Rule Group(ルールグループ)

    Stateless Rule GroupとStateful Rule Groupの2種類があります。
    複数の Rule group を Firewall policy と紐づけて利用します。
    複数のRule GroupをFirewall Policyに紐付けて使用します。各Rule Group内では複数のルールを設定でき、トラフィックの制御を細かく行うことが可能です。

    それではコンソール画面から順番に作成していきます!
    Terraformでの構築する際のコードも一緒に記載します。

    Rule Groupの作成

    今回はStateful rule groupでドメイン名でトラフィックを許可するルールを作成します。
    ステートフルルールグループで、ドメインリストを指定します。
    ルール評価の順序は、厳密な順序にします。
    厳密な順序を指定することで各ルールに優先度を決定して、優先度に従ってルールが評価されます。

    rule_group_1

    適当に名前をつけて、キャパシティーを決定します。
    このキャパシティは後から変更することができないので余裕を持って設定しましょう。
    キャパシティの詳しい計算方法は省略しますが、ドメインリストの場合は下記で計算できます。

    1キャパシティ = ( ドメイン数 + 1 ) * プロトコル数

    今回はテストなので50くらいで設定します。
    キャパシティの上限は30000となっています。

    rule_group_2

    指定したドメインの通信を許可します。
    yahooとgoogleのドメインを登録しておきます。

    rule_group_3

    これでrule groupの作成完了です。

    1## firewall rule groupの作成
    2locals {
    3  firewall_allow_fqdn_list = [
    4    ".google.com",
    5    ".yahoo.com",
    6  ]
    7}
    8
    9resource "aws_networkfirewall_rule_group" "fqdn" {
    10  name        = "test-rule-group"
    11  description = "FQDN for allowing traffic"
    12  capacity    = 100
    13  type        = "STATEFUL"
    14  rule_group {
    15    rules_source {
    16      rules_source_list {
    17        generated_rules_type = "ALLOWLIST"
    18        target_types         = ["TLS_SNI", "HTTP_HOST"]
    19        targets              = [for fqdn in local.firewall_allow_fqdn_list : fqdn]
    20      }
    21    }
    22}

    Firewall policyの作成

    Firewall policyを作成していきます。
    AWS Network Firewall を通る通信は図のように、まず設定してあるステート レス ルールグループで評価されます。

    ステートレスルールグループは設定した優先度の順に上から評価されていき、どれかのルールに一致すると、それ以降のルールは評価されません。
    どのルールにも合致しなかった場合は、デフォルトアクションが適用されます。
    今回は、特定のドメインで通信を許可したいので青矢印のポリシーを作成します。

    firewall_policy_1

    引用元:https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-rules-engines.html

    適当に名前をつけます。

    ストリーム例外ポリシーは、ネットワークの接続が途中で中断した際に、どのようにトラフィックを処理するかを指定するポリシーです。
    ドロップや拒否のポリシーはセキュリティを強化しますが、一方で通信の品質が低下する可能性があります。
    逆に、続行するポリシーは通信の途切れを最小限に抑えることができますが、セキュリティリスクが高まる可能性があります。
    今回はドロップを選択します。

    firewall_policy_2

    オプションでステートフルルールグループに転送を選択して、先ほど作成したルールグループを追加します。

    firewall_policy_3
    firewall_policy_4

    これでfirewall policyの作成完了です。

    1## firewall policyの作成
    2resource "aws_networkfirewall_firewall_policy" "default" {
    3  name = "test-firewall-policy"
    4  firewall_policy {
    5    stateless_default_actions          = ["aws:forward_to_sfe"]
    6    stateless_fragment_default_actions = ["aws:forward_to_sfe"]
    7    stateful_rule_group_reference {
    8      resource_arn = aws_networkfirewall_rule_group.fqdn.arn
    9    }
    10  }
    11}

    Network Firewall の作成

    適当な名前をつけて次へ
    firewall_1

    VPCとFirewall Endpointを設置するSubnetを選択します。
    firewall_2

    KMSは今回は使用しません。
    削除保護をつけて次へ
    firewall_3

    先ほど作成したfirewll policyを選択します。
    firewall_4

    これで作成完了です。

    1
    2## Network firewallの作成
    3resource "aws_networkfirewall_firewall" "default" {
    4  name                     = "test-firewall"
    5  vpc_id                   = aws_vpc.default.id
    6  delete_protection        = true
    7  subnet_change_protection = true
    8  firewall_policy_arn      = aws_networkfirewall_firewall_policy.default.arn
    9  subnet_mapping {
    10    subnet_id = aws_subnet.firewall.id
    11  }
    12}

    ルーティングの設定追加

    通常のルーティング箇所は省略しますが、Ingress Route Table の作成が少し難しかったので軽く解説します。
    インターネット側から入ってくる通信も、Network Firewall を経由するルーティングを設定する必要があります。
    NAT Gateway が稼働している Public Subnet 宛の通信を、Network Firewall の Endpoint に指定します。
    先ほどの画像のこの部分です。

    ingress_routing_1

    ルートテーブルを作成します。

    ingress_routing_2

    public subnetからのターゲットをfirewall endpointに指定します。

    ingress_routing_3

    Edgeの関連付けを編集でinternet gatewayを選択します。

    ingress_routing_4

    terraform で記述する際の注意点は、firewall endpoint_idはかなり深い階層に存在します。
    生成された VPC エンドポイントの情報は firewall_status[0].sync_states の set の中に一つずつ入っています。

    1
    2resource "aws_route_table" "ingress_route_table" {
    3  vpc_id = aws_vpc.default.id
    4  route {
    5    cidr_block      = local.subnet.public
    6    vpc_endpoint_id = tolist(aws_networkfirewall_firewall.default.firewall_status[0].sync_states)[0].attachment[0].endpoint_id
    7  }
    8  tags = {
    9    Name = "test-ingress-route-table"
    10  }
    11}
    12
    13resource "aws_route_table_association" "ingress_route_table" {
    14  gateway_id     = aws_internet_gateway.default.id
    15  route_table_id = aws_route_table.ingress_route_table.id
    16}

    動作確認

    設定が完了したので、Network Firewallが期待通りに機能しているかを確認していきます。

    特定ドメインへのアクセス確認

    Private Subnetに配置されたEC2インスタンスから許可したドメインにHTTPリクエストを送ります。
    今回はgoogle.comとyahoo.comです。
    両方のドメインからHTTPステータスコード「200」が返ってきました。
    期待通りの結果です。

    1[ec2-user@ip-10-1-0-245 ~]$ curl -v https://www.google.com/ 2>&1 | grep '< HTTP/'
    2< HTTP/2 200
    3[ec2-user@ip-10-1-0-245 ~]$ curl -v https://www.yahoo.com/ 2>&1 | grep '< HTTP/'
    4< HTTP/2 200

    許可されていないドメインへのアクセス確認

    許可していないドメインと通信が遮断されているか確認します。
    EC2インスタンスからのHTTPリクエストに対するレスポンスは返ってこないはずです。
    youtube.comにリクエストしてもレスポンスが返ってきませんね。

    1[ec2-user@ip-10-1-0-245 ~]$ curl -v http://www.youtube.com
    2*   Trying 172.217.31.174:80...
    3* Connected to www.youtube.com (172.217.31.174) port 80
    4> GET / HTTP/1.1
    5> Host: www.youtube.com
    6> User-Agent: curl/8.3.0
    7> Accept: */*
    8>

    Firewall Subnetからのアクセス確認

    Firewall SubnetにEC2を作成してyoutube.comにHTTPリクエストを送るとどうなるでしょう?

    1[ec2-user@ip-10-1-2-11 .ssh]$ curl -v https://www.youtube.com/ 2>&1 | grep '< HTTP/'
    2< HTTP/2 200

    HTTPステータスコード「200」が返ってきました。
    Firewall Subnetからエンドポイントを通らずにインターネットゲートウェイにトラフィックが流れているからです。
    つまり、Firewallはエンドポイント配下のリソースに適用されるということです。

    Cloud Watchでログ確認

    Cloud Watchでログを確認するために設定を追加します。
    Cloud Watchロググループを作成してALERTとFLOWのログをfirewallの変更画面からログ記録を設定します。

    log_1

    Cloud Watchのログを見てみると、youtube.comへのアクセスがNetwork Firewall によっってブロックされていることが分かります。actionがblockedになっていて、hostname にリクエストヘッダーに含まれるドメインが記録されています。

    1
    2{
    3    "firewall_name": "test-firewall",
    4    "availability_zone": "ap-northeast-1a",
    5    "event_timestamp": "1699774612",
    6    "event": {
    7        "tx_id": 0,
    8        "app_proto": "http",
    9        "src_ip": "10.1.0.245",
    10        "src_port": 54898,
    11        "event_type": "alert",
    12        "alert": {
    13            "severity": 1,
    14            "signature_id": 3,
    15            "rev": 1,
    16            "signature": "not matching any HTTP allowlisted FQDNs",
    17            "action": "blocked",
    18            "category": ""
    19        },
    20        "flow_id": 229950411303581,
    21        "dest_ip": "172.217.175.238",
    22        "proto": "TCP",
    23        "http": {
    24            "hostname": "www.youtube.com",
    25            "url": "/",
    26            "http_user_agent": "curl/8.3.0",
    27            "http_method": "GET",
    28            "protocol": "HTTP/1.1",
    29            "length": 0
    30        },
    31        "dest_port": 80,
    32        "timestamp": "2023-11-12T07:36:52.652134+0000"
    33    }
    34}

    Network Firewallの料金

    network_firewall_money

    引用元:https://aws.amazon.com/jp/network-firewall/pricing/

    前半部分で少し触れましたが、Network Firewallの料金は1つのアベイラビリティゾーン(AZ)ごとに発生します。
    例として、アジアリージョンで3つのAZにVPCエンドポイントを作成した場合の1ヶ月の運用料金を計算してみましょう。

    1つのNetwork Firewallエンドポイントは1時間あたり0.395USDのコストがかかります。
    そのため、1日のコストは以下のようになります。
    0.395 USD/時間 × 24時間 = 9.48 USD/日

    この金額に3つのAZを乗じると、1ヶ月の合計コストは次のようになります。
    9.48 USD/日 × 3AZ × 30日 = 853.2 USD/月(約127,800円/月)

    なかなか高いですね。
    個人で試す場合は、必要ない時は忘れずに削除するようにしましょう。
    消し忘れてたら死にます。

    まとめ

    今回、AWSサービスの一つであるNetwork Firewallに焦点を当ててみました。個人での利用機会は少ないかもしれませんが、WAFやセキュリティグループでは制御できないトラフィックを制御できるため、非常に便利なツールです。今回は取り上げませんでしたが、Suricata互換性ルールを使用すれば、さらに細かいトラフィック制御が可能になります。
    今後もAWSサービスに関するさまざまな情報をブログで共有していきたいと思います。

    あだっちー(エンジニア)

    あだっちー(エンジニア)

    おすすめ記事