Reading VPC Flow Logs
How to read VPC Flow Logs to confirm what the network did — the default record format field by field, ACCEPT versus REJECT, NODATA and SKIPDATA, delivery delay, and the custom fields that answer specific questions (NAT translation, TCP flags, traffic path, Block Public Access and encryption rejects, ECS task).
markdownreferencev4XC9F-XK6Hstage: operatetrust: officialservice: vpcinterface: anyVPC Flow Logsflow log record formatREJECTACCEPTNODATASKIPDATAaggregation intervalpkt-srcaddrtcp-flagsflow-directiontraffic-pathreject-reason BPAVPC Encryption Controlsecs-task-arncreate-flow-logs
A flow log record says that traffic between two addresses and ports was ACCEPTed or REJECTed at a network interface during a capture window. A REJECT means a security group or network ACL dropped it, or packets arrived after the connection had closed. Here is how to read one, and what flow logs can't tell you.
Default format (version 2), in order
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status
| Field | Meaning |
|---|---|
interface-id | The network interface the flow was recorded on (- for a regional NAT gateway's flows) |
srcaddr / dstaddr | For incoming traffic, the source; for outgoing traffic, the interface's private IPv4 or IPv6 address. Not the original address when NAT is in the path (use pkt-srcaddr/pkt-dstaddr) |
protocol | IANA number: 6 TCP, 17 UDP, 1 ICMP |
start / end | Unix seconds of the first and last packet in the window (±60 s) |
action | ACCEPT or REJECT |
log-status | OK; NODATA (no traffic in the window); SKIPDATA (records skipped for internal capacity reasons) |
A field that doesn't apply shows -. Fields like account-id can show unknown for interfaces AWS services create.
Timing
- Aggregation window: up to 10 minutes by default, or 1 minute if chosen. Interfaces on Nitro instances are always ≤1 minute.
- Delivery: typically about 5 minutes to CloudWatch Logs and about 10 minutes to S3. Best effort, so a fresh test may not appear yet.
Reading a failed connection
To find the REJECT lines in a flow log's log group, use the Logs Insights queries in reference/cloudwatch/logs-insights-queries.md.
| You see | It means |
|---|---|
Client → server REJECT on the server's interface | The server's security group or the subnet's NACL dropped the request |
Request ACCEPT, the reply REJECT | Almost always a NACL blocking the return on ephemeral ports (security groups are stateful) |
| Nothing at the destination interface | The traffic never arrived: routes, gateways, or VPC Block Public Access upstream. Check the source interface's records |
ACCEPT both ways, but the app still fails | The network is fine; look at the application, TLS or DNS |
Late REJECTs on an old connection | Packets after the connection closed, for example after an NLB or NAT idle timeout |
Custom fields worth adding
Specify a custom format to include them (at least one field):
| Field (version) | Answers |
|---|---|
pkt-srcaddr, pkt-dstaddr (v3) | The original addresses behind a NAT gateway, or an EKS pod behind its node |
tcp-flags (v3) | SYN 2, SYN-ACK 18, FIN 1, RST 4 (flags are OR-ed within a window). SYNs with no SYN-ACK mean the server never answered |
vpc-id, subnet-id, instance-id (v3) | Where the interface lives |
flow-direction (v5) | ingress or egress at this interface |
traffic-path (v5) | Egress via 1 same VPC, 2 IGW or gateway endpoint, 3 VGW, 4 intra-Region peering, 5 inter-Region peering, 6 Local or Wavelength Zone, 7 gateway endpoint, 8 IGW |
pkt-src-aws-service, pkt-dst-aws-service (v5) | The AWS service range of the address (e.g. S3, CLOUDFRONT_ORIGIN_FACING, ROUTE53_RESOLVER) |
ecs-cluster-name, ecs-service-name, ecs-task-arn (v7) | Which ECS task produced the flow (the flow log's role needs ecs:List* permissions) |
reject-reason (v8) | BPA (VPC Block Public Access) or EC (rejected by VPC Encryption Controls); - for other rejects such as SG or NACL |
resource-id (v9) | The regional NAT gateway |
encryption-status (v10) | 0 not encrypted, 1 Nitro-encrypted, 2 application-encrypted (inferred from port 443 for endpoints), 3 both |
interface-type, next-hop-* (v11) | What the interface belongs to (nat_gateway, network_load_balancer, vpc_endpoint…) and the next hop |
Limits of what it shows
- Packets aren't captured, only per-flow summaries.
- Traffic that security groups and NACLs can't see, such as DNS to the Route 53 Resolver and IMDS, isn't a firewall question (
reference/vpc/security-groups-and-nacls.md). - Flow logs record what happened. To learn why a path is blocked before sending traffic, use Reachability Analyzer (
guides/vpc/diagnose-connection-timeout.md). - Turning on flow logs is
aws ec2 create-flow-logswith a resource (VPC, subnet or network interface), traffic type and destination (CloudWatch Logs with a delivery role, or S3) (UNVERIFIED parameter names in the collected sources).