- Newest
- Most votes
- Most comments
Hello, This is a fantastic and very common question that touches on the core behavior of AWS Network Firewall's stateful rule engine. Your configuration and logging are correct; the behavior you're observing is expected and is a direct result of how stateful inspection works. The short answer is: The traffic is being "allowed" at the stateful rule layer to complete the TCP handshake, but it will ultimately be dropped by the firewall policy because no rule explicitly permits the established flow. Let's break down why this happens. The Root Cause: Stateful Inspection and TCP Handshakes The status of network connections is monitored by a stateful firewall, such as AWS Network Firewall. Before applying the majority of your content inspection rules (such as your domain list), it must wait for the initial 3-way handshake (SYN -> SYN-ACK -> ACK) to finish for any TCP traffic.
The details of what you're seeing are as follows: Outgoing SYN Packet (Port 80 -> Ephemeral Port): Your instance opens a port 80 connection to a server. The SYN flag is set on this packet.
Evaluation of Stateful Rules: Your stateful rule group is hit by the packet. Since the destination port is 80, which is outside of the 32768 – 65535 range, your "allow TCP on ephemeral ports" rule does not apply. Since there isn't a defined flow to examine, your domain list rule group hasn't been assessed yet.
In a strict rule group, the firewall's default response to a non-matching TCP SYN packet is to create an alert and then monitor the connection in a "pending" state. You can see this in your log: "action": "alert" and "verdict": { "action": "alert" }. The alert's "allowed" indicates that the stateful engine received the SYN packet for tracking.
Inbound SYN-ACK Packet (Port 80 -> Ephemeral Port): A SYN-ACK packet is sent back by the destination server. Evaluation of Stateful Rules (Again): The firewall recognizes this as a reaction to a connection it is monitoring. In order for the handshake to finish, it permits this SYN-ACK packet to reach your instance. Outbound ACK Packet: To complete the connection, your instance sends the last ACK packet.
Final Rule Evaluation & Drop: The firewall now applies your domain list rule group since the TCP connection is fully established. In the ensuing data packets, it examines the TLS SNI or HTTP Host header. The firewall drops the data packets and will eventually terminate the connection because the domain (for example, http://example.com) is not on your allow list.
Responses to Your Particular Inquiries Q1: Given that only ephemeral ports are allowed, why might outgoing HTTP (port 80) traffic appear to be "allowed"? Q2: Are TCP/80 implicitly permitted by domain list rule groups for DNS resolution or verification? A: Not at all. Groups of domain list rules operate at Layer 7 (application layer). To examine the content, they need a TCP connection that is fully established on any port, including 80 or 443. No ports are implicitly opened by them. For those domains, DNS resolution takes place on port 53, which is a different flow. Q3: Could this behavior be the result of a rule order or default policy action? A: Indirectly, yes. The last arbiter is the default action (probably "Drop") of your firewall policy. Any flow that doesn't receive an explicit "Pass" from a stateful rule (such as your domain list) eventually falls through to the default action, "Drop," after the stateful rules have processed the traffic. Q4: Do you know of any instances in which Network Firewall logs "allowed" alerts despite the packet being dropped later? A: Exactly this situation. The first packet of a flow that is being monitored but not specifically passed by a stateful rule is where the alert is recorded. A drop is still the flow's final result.
How to Verify the Entire Flow You need to compare your Alert and Flow logs in order to see the full story. Alert Logs: Display the first packet that caused the evaluation of the stateful rule (what you have already discovered). Flow logs: Display the connection's ultimate destiny. Look for a log entry with "connection_end" set to true and "flow_direction" set to "forward" for the same 5-tuple (source IP/port, destination IP/port, protocol). A final "action" verdict of "drop" is probably what you'll see.
The clearest indication that the firewall is operating properly and eventually preventing the traffic is a log entry in your Flow logs that says "action": "drop" for the same connection. In brief Your setup is operating as intended. During the TCP handshake, the alert permitted for port 80 is a temporary state for a connection that is being and will be dropped. A security bypass does not exist. You could make a stateless rule to drop TCP/80 completely in order to minimize these logs. This would instantly block the SYN packet without stateful tracking. However, because it permits the possibility of more intricate rules, the current behavior is more "correct" for a stateful firewall.
Key Takeaway: To fully comprehend the lifecycle of a network flow through AWS Network Firewall, always examine both the Alert and Flow logs jointly.
answered a year ago
Building on the existing answer, I want to clarify how Suricata's alert logging works, as the terminology can be misleading. In Suricata's alert output, action: allowed simply means an alert rule was matched — it does not mean the traffic was passed or permitted. This naming convention is ambiguous and has been acknowledged as a source of confusion. Rather than changing the existing allowed value — which would be disruptive given how widely Suricata is deployed — Suricata introduced the verdict key/value pair in version 7 to provide a clearer indication of the actual action taken on the flow. This is discussed in the following Suricata issue.
In the alert log snippet you shared, the verdict is alert and the matching rule is the "Alert all" stateful default action, which you can identify from the aws:alert_strict action in the message field.
To get a complete picture of what happened with this flow, I'd recommend the following:
- Locate the flow_id from the alert log event. Every flow through Suricata is assigned a unique flow_id that is consistent across all related flow and alert log events.
- Search your flow and alert logs using that flow_id to find all related events for the flow in question. For bidirectional communications, you'd expect two flow log events published after the flow gracefully ends or reaches idle timeout. For a unidirectional flow (e.g., a TCP SYN blocked by a rule), you'd expect a single flow log event. For long-lived flows that are still active, you may see alert log events without a corresponding flow log event, since flow logs are only published after the flow ends.
- Note that you may see multiple alert log events for the same flow as different stateful rules are evaluated and matched.
- Review the flow details (flags, packet counts, bytes, etc.) alongside the related alert logs to build a complete picture of the actions taken. From there, you can revise your rules if needed.
answered 6 months ago
Relevant content
asked a year ago
asked 4 years ago

Thank you for your detailed response. In my protected subnets , i have been seeing port 80 as ACCEPT in vpc flow logs .