[アップデート] AWS Network Firewall のファイアウォールポリシーで Suricata IPS互換ルールの HOME_NET をオーバーライドできるようになりました
マネージドルールグループのHOME_NETを設定するためにマネージドルールグループをコピーするの面倒だな
こんにちは、のんピ(@non____97)です。
皆さんはAmazon Network FirewallでマネージドルールグループのHOME_NET
を設定するために、マネージドルールグループをコピーするの面倒だなと思ったことはありますか? 私はあります。
Network FirewallでSuricata互換のIPSルールを一から自分で定義するのは中々大変です。そのような場合は、マネージドのSuricata互換のIPSルールであるAWS Managed Threat Signaturesを使うことで負荷の軽減ができます。
ただし、こちらのマネージドなルールグループはルール変数を自ら定義することができません。
ルールグループ内で使用される、自ネットワークを示す時に使用される変数HOME_NET
はデフォルトではNetwork Firewallが配置されているVPCのCIDRとなります。
To use domain name filtering for traffic from outside the VPC where you've deployed Network Firewall, you must manually set the HOME_NET variable for the rule group. The most common use case for this is a central firewall VPC with traffic coming from other VPCs through a transit gateway.
By default, domain list inspection uses a HOME_NET that is set to the CIDR range of the VPC where Network Firewall is deployed. Only traffic from that range is passed through the domain list filtering. To filter traffic from outside the deployment VPC, you must provide a HOME_NET setting that includes the other CIDR ranges that you want to inspect, along with the CIDR range of the VPC where Network Firewall is deployed.
(以下機械翻訳)
Network Firewall を導入した VPC の外部からのトラフィックに対してドメイン名フィルタリングを使用するには、ルールグループの HOME_NET 変数を手動で設定する必要があります。最も一般的な使用例は、セントラルファイアウォールのVPCで、他のVPCからトランジットゲートウェイを経由してくるトラフィックです。
デフォルトでは、ドメインリスト検査は、Network Firewallが配置されているVPCのCIDR範囲に設定されたHOME_NETを使用します。その範囲からのトラフィックのみが、ドメインリスト検査に通過します。展開VPC外からのトラフィックをフィルタリングするには、Network Firewallが展開されているVPCのCIDR範囲に加えて、検査したい他のCIDR範囲を含むHOME_NET設定を提供する必要があります。
Stateful domain list rule groups in AWS Network Firewall - AWS Network Firewall
Network Firewallを以下AWS公式ブログで紹介しているような1つのVPCに集約している場合はHOME_NET
をNetwork FirewallのVPCと接続しているVPCのCIDRを設定したいところです。
しかし、先述の制限があるためマネージドルールグループを使うためには、マネージドルールグループをコピーしてHOME_NET
を設定してあげる必要がありました。
今回、アップデートによりAWS Network Firewall のファイアウォールポリシーで Suricata IPS互換ルールのHOME_NET
をオーバーライドできるようになりました
API Referenceを確認すると、PolicyVariables
というData Typeも増えていました。
これにより先述の問題が解消されました。
試してみたので紹介します。
いきなりまとめ
- ポリシー変数で
HOME_NET
をオーバーライドできるようになった- マネージドルールの
HOME_NET
をカスタマイズしたいがために、マネージドルールのコピーを行う必要がなくなった
- マネージドルールの
- ポリシー変数とルール変数どちらも
HOME_NET
をオーバーライドしている場合、ルール変数の値が優先される - ポリシー変数のオーバーライドをするタイミングでダウンタイムが発生する
やってみた
検証環境
検証環境は以下の通りです。
Network FirewallではHOME_NET
からdev.classmethod.jp
へのHTTPの通信をドロップするようなSuricata互換IPSルールを定義しています。
drop http $HOME_NET any -> $EXTERNAL_NET 80 (http.host; dotprefix; content:"dev.classmethod.jp"; endswith; msg:"Allowed HTTP domain"; sid:892120; rev:1;)
Spoke VPC上のEC2インスタンスにSSMセッションマネージャーで接続し、curl でdev.classmethod.jp
へのHTTPの通信をしてみます。そして、ルール変数やポリシー変数の設定に応じてドロップされるのかを確認します。
全てのリソースはAWS CDKでデプロイしています。使用したコードは以下リポジトリに保存しています。
ルール変数でHOME_NETをオーバーライド
まず、本題のアップデートを紹介する前に、ルール変数であってもHOME_NET
をオーバーライドできることを確認します。
と、その前にHOME_NET
はデフォルトではNetwork Firewallが配置されているVPCのCIDRであることを確認します。
EC2インスタンスからdev.classmethod.jp
へHTTPの通信をしようとしてみます。
$ curl -I -m5 http://dev.classmethod.jp HTTP/1.1 301 Moved Permanently Server: awselb/2.0 Date: Mon, 08 May 2023 04:40:04 GMT Content-Type: text/html Content-Length: 134 Connection: keep-alive Location: https://dev.classmethod.jp:443/
Suricata互換のIPSルールにマッチするのであればタイムアウトするところが、タイムアウトせずにステータスコード301が返ってきましたね。
このことから、確かにNetwork Firewallを1つのVPCに集約している場合はHOME_NET
をNetwork FirewallのVPCと接続しているVPCのCIDRを設定する必要があることが分かります。
それではルール変数の設定を行い、通信がドロップされることを確認します。
ルールグループのルール変数の編集
をクリックします。
IPセット変数でHOME_NET
が10.0.0.0/8
となるように定義します。
この状態でEC2インスタンスからdev.classmethod.jp
へHTTPの通信をしようとしてみます。
$ curl -I -m5 http://dev.classmethod.jp curl: (28) Operation timed out after 5000 milliseconds with 0 bytes received
今度はタイムアウトになりましたね。
Network Firewallのログを確認すると、確かに設定したSuricata互換のIPSルールでドロップしていることが分かります。
{ "firewall_name": "network-firewall", "availability_zone": "us-east-1a", "event_timestamp": "1683521005", "event": { "tx_id": 0, "app_proto": "http", "src_ip": "10.0.2.7", "src_port": 35508, "event_type": "alert", "alert": { "severity": 3, "signature_id": 892120, "rev": 1, "signature": "Allowed HTTP domain", "action": "blocked", "category": "" }, "flow_id": 460961625234767, "dest_ip": "13.248.175.13", "proto": "TCP", "http": { "hostname": "dev.classmethod.jp", "url": "/", "http_user_agent": "curl/7.88.1", "http_method": "HEAD", "protocol": "HTTP/1.1", "length": 0 }, "dest_port": 80, "timestamp": "2023-05-08T04:43:25.231126+0000" } }
ルール変数でHOME_NETをオーバーライド × ポリシー変数でHOME_NETをオーバーライド
加えてポリシー変数でもHOME_NET
をオーバーライドします。
ポリシー変数でHOME_NET
をオーバーライドする際はファイアウォールポリシーの詳細
タブからPolicy variablesの編集
から行います。
HOME_NET
をオーバーライドしたい値を入力して保存
をクリックします。今回は10.0.1.0/24
としました。
設定が完了したことを確認します。
この後、EC2インスタンスからdev.classmethod.jp
へHTTPの通信をしようとしてみます。
$ curl -I -m5 http://dev.classmethod.jp curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
タイムアウトしてしまいました。
時間を置いてチャレンジしてみましたが、結果は変わらずでした。
ルール変数とポリシー変数の両方を指定している場合ルール変数が優先されるようですね。
ポリシー変数でHOME_NETをオーバーライド
次にポリシー変数でのみHOME_NET
をオーバーライドするパターンを試します。
ルール変数は削除しておきます。
ポリシー変数の設定が反映されたことが分かりやすいよう、このタイミングでもEC2インスタンスからdev.classmethod.jp
へHTTPの通信をしようとしてみます。
$ curl -I -m5 http://dev.classmethod.jp HTTP/1.1 301 Moved Permanently Server: awselb/2.0 Date: Mon, 08 May 2023 04:55:00 GMT Content-Type: text/html Content-Length: 134 Connection: keep-alive Location: https://dev.classmethod.jp:443/
通信できるようになりましたね。
それでは、ポリシー変数を設定します。ポリシー変数は10.0.0.0/8
としました。
ポリシー変数を設定変更すると、3分弱ほどSSMセッションマネージャーからEC2インスタンスの操作を受け付けなくなりました。
もしかすると、ポリシー変数変更時にはダウンタイムがあるのかも知れません。
最初にポリシー変数を設定した際にはこちらの事象は発生しませんでした。しかし、その時は10.0.1.0/24
とNetwork Firewallが存在するVPCと同じCIDRを指定しました。そのため、内部的にポリシー変数をオーバーライドする必要がないと判断し、ダウンタイムが発生しなかったのではと推測します。
しばらくするとSSMセッションマネージャーでEC2インスタンスに接続できるようになりました。
この状態でEC2インスタンスからdev.classmethod.jp
へHTTPの通信をしようとしてみます。
$ curl -I -m5 http://dev.classmethod.jp curl: (28) Operation timed out after 5000 milliseconds with 0 bytes received
タイムアウトとなりました。ポリシー変数によるHOME_NET
のオーバーライドがしっかり効いていることが分かります。
ポリシー変数でHOME_NETをオーバーライドするタイミングで本当にダウンタイムが発生するのか確認
最後にポリシー変数でHOME_NETをオーバーライドするタイミングで本当にダウンタイムが発生するのかを確認します。
5秒間隔でpingを叩くsystemd-timerを作成し、ポリシー変数でHOME_NETをオーバーライドするタイミングで通診断が発生しているのかチェックします。
# serviceの作成 $ sudo tee /etc/systemd/system/ping-test.service << EOF > /dev/null [Unit] Description=ping test [Service] User=ec2-user Group=ec2-user Type=oneshot ExecStart=/usr/bin/ping -c 1 -q 1.1.1.1 [Install] WantedBy=multi-user.target EOF # timerの作成 $ sudo tee /etc/systemd/system/ping-test.timer << EOF > /dev/null [Unit] Description=Runs every 5 seconds [Timer] OnBootSec=10s OnUnitActiveSec=10s AccuracySec=100ms [Install] WantedBy=timers.target EOF # timerの起動 $ sudo systemctl start ping-test.timer # timserが起動していることを確認 $ systemctl status ping-test.timer ● ping-test.timer - Runs every 5 seconds Loaded: loaded (/etc/systemd/system/ping-test.timer; disabled; preset: disabled) Active: active (running) since Mon 2023-05-08 06:14:17 UTC; 27ms ago Until: Mon 2023-05-08 06:14:17 UTC; 27ms ago Trigger: n/a Triggers: ● ping-test.service May 08 06:14:17 ip-10-0-2-7.ec2.internal systemd[1]: Started ping-test.timer - Runs every 5 seconds.
この状態でポリシー変数を10.0.2.0/24
に変更します。
$ journalctl -u ping-test -n 30 -S "May 08 06:14:49" May 08 06:14:58 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8911]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8911]: --- 1.1.1.1 ping statistics --- May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8911]: 1 packets transmitted, 0 received, 100% packet loss, time 0ms May 08 06:15:08 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Main process exited, code=exited, status=1/FAILURE May 08 06:15:08 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Failed with result 'exit-code'. May 08 06:15:08 ip-10-0-2-7.ec2.internal systemd[1]: Failed to start ping-test.service - ping test. May 08 06:15:08 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8915]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8915]: --- 1.1.1.1 ping statistics --- May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8915]: 1 packets transmitted, 1 received, 0% packet loss, time 0ms May 08 06:15:08 ip-10-0-2-7.ec2.internal ping[8915]: rtt min/avg/max/mdev = 4.004/4.004/4.004/0.000 ms May 08 06:15:08 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Deactivated successfully. May 08 06:15:08 ip-10-0-2-7.ec2.internal systemd[1]: Finished ping-test.service - ping test. May 08 06:15:18 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 06:15:18 ip-10-0-2-7.ec2.internal ping[8917]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 06:15:18 ip-10-0-2-7.ec2.internal ping[8917]: --- 1.1.1.1 ping statistics --- May 08 06:15:18 ip-10-0-2-7.ec2.internal ping[8917]: 1 packets transmitted, 1 received, 0% packet loss, time 0ms May 08 06:15:18 ip-10-0-2-7.ec2.internal ping[8917]: rtt min/avg/max/mdev = 4.408/4.408/4.408/0.000 ms May 08 06:15:18 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Deactivated successfully. May 08 06:15:18 ip-10-0-2-7.ec2.internal systemd[1]: Finished ping-test.service - ping test. May 08 06:15:28 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 06:15:28 ip-10-0-2-7.ec2.internal ping[8972]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 06:15:28 ip-10-0-2-7.ec2.internal ping[8972]: --- 1.1.1.1 ping statistics --- May 08 06:15:28 ip-10-0-2-7.ec2.internal ping[8972]: 1 packets transmitted, 1 received, 0% packet loss, time 0ms May 08 06:15:28 ip-10-0-2-7.ec2.internal ping[8972]: rtt min/avg/max/mdev = 4.369/4.369/4.369/0.000 ms May 08 06:15:28 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Deactivated successfully. May 08 06:15:28 ip-10-0-2-7.ec2.internal systemd[1]: Finished ping-test.service - ping test. May 08 06:15:38 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 06:15:38 ip-10-0-2-7.ec2.internal ping[8974]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
ポリシー変数を変更して10秒後に一回だけ到達しなかったようです。
たまたまかな? と思い、ポリシー変数を10.0.2.0/24
から10.0.1.0/24
に変更しましたが、やはり到達できないタイミングがありました。
$ journalctl -u ping-test -n 30 -S "May 08 07:21:22" May 08 07:21:30 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 07:21:30 ip-10-0-2-7.ec2.internal ping[12853]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 07:21:30 ip-10-0-2-7.ec2.internal ping[12853]: --- 1.1.1.1 ping statistics --- May 08 07:21:30 ip-10-0-2-7.ec2.internal ping[12853]: 1 packets transmitted, 1 received, 0% packet loss, time 0ms May 08 07:21:30 ip-10-0-2-7.ec2.internal ping[12853]: rtt min/avg/max/mdev = 4.529/4.529/4.529/0.000 ms May 08 07:21:30 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Deactivated successfully. May 08 07:21:30 ip-10-0-2-7.ec2.internal systemd[1]: Finished ping-test.service - ping test. May 08 07:21:40 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12854]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12854]: --- 1.1.1.1 ping statistics --- May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12854]: 1 packets transmitted, 0 received, 100% packet loss, time 0ms May 08 07:21:50 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Main process exited, code=exited, status=1/FAILURE May 08 07:21:50 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Failed with result 'exit-code'. May 08 07:21:50 ip-10-0-2-7.ec2.internal systemd[1]: Failed to start ping-test.service - ping test. May 08 07:21:50 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12855]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12855]: --- 1.1.1.1 ping statistics --- May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12855]: 1 packets transmitted, 1 received, 0% packet loss, time 0ms May 08 07:21:50 ip-10-0-2-7.ec2.internal ping[12855]: rtt min/avg/max/mdev = 4.472/4.472/4.472/0.000 ms May 08 07:21:50 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Deactivated successfully. May 08 07:21:50 ip-10-0-2-7.ec2.internal systemd[1]: Finished ping-test.service - ping test. May 08 07:22:00 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 07:22:00 ip-10-0-2-7.ec2.internal ping[12856]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. May 08 07:22:00 ip-10-0-2-7.ec2.internal ping[12856]: --- 1.1.1.1 ping statistics --- May 08 07:22:00 ip-10-0-2-7.ec2.internal ping[12856]: 1 packets transmitted, 1 received, 0% packet loss, time 0ms May 08 07:22:00 ip-10-0-2-7.ec2.internal ping[12856]: rtt min/avg/max/mdev = 11.568/11.568/11.568/0.000 ms May 08 07:22:00 ip-10-0-2-7.ec2.internal systemd[1]: ping-test.service: Deactivated successfully. May 08 07:22:00 ip-10-0-2-7.ec2.internal systemd[1]: Finished ping-test.service - ping test. May 08 07:22:10 ip-10-0-2-7.ec2.internal systemd[1]: Starting ping-test.service - ping test... May 08 07:22:10 ip-10-0-2-7.ec2.internal ping[12858]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
ダウンタイムはありそうですね。
ポリシー変数を変更する場合はネットワークトラフィックが控えめなタイミングで行うのが吉ですね。
具体的にはCloudWatchでReceivedPackets
の値が低いタイミングを確認することになります。
マネージドルールが使いやすくなりました
AWS Network Firewall のファイアウォールポリシーで Suricata IPS互換ルールのHOME_NET
をオーバーライドできるようになったアップデートを紹介しました。
これでまた一つマネージドルールが使いやすくなりましたね。
また、マネージドルールを使っていない場面でも、複数のSuricata互換のルールグループがある時に各ルールグループでHOME_NET
を定義する必要がなくなりそうです。
この記事が誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!