Set Up VPC Flow Logs
Set up VPC flow logs for discovery — Cloud security essentials tutorial, lesson 14.
Focus: set up vpc flow logs for discovery
Your VPC is humming along, workloads are passing traffic, and then — one day — something feels off. An unusual API call, a spike in outbound traffic, a connection to an IP you don't recognize. Without visibility into the network flows inside your VPC, you're flying blind. You could spend hours tracing through logs, or you could set up VPC flow logs and get a clear, queryable record of every connection attempt happening inside your cloud environment. This lesson will give you the exact steps to turn on that visibility and make it a cornerstone of your cloud security discovery process.
The problem this lesson solves
Cloud security isn't just about preventing attacks; it's about detecting them early and understanding their footprint. Traditional security tools monitor host-level activity, but they miss the network layer. A compromised container, a misconfigured security group, or an attacker pivoting through your VPC — none of these leave obvious traces on disk. They do leave network traces.
Without VPC flow logs, you have no answer to questions like: - Who is connecting to my database server on port 5432? - Why is my web server sending traffic to an IP in a sanctioned region? - Which security group rule is allowing unexpected traffic?
Enabling VPC flow logs gives you a per-connection record — source, destination, port, protocol, and whether the connection was accepted or rejected. This is your first line of discovery for anything that moves across your network.
Pro tip: Flow logs are not a security control that blocks malicious traffic. They are a detection mechanism — they log, they don't block. Pair them with network ACLs and security groups for actual enforcement.
Core concept / mental model
Think of VPC flow logs as a flight recorder for your VPC. Like the black box on an airplane, it continuously records what's happening in the network — every takeoff (connection start) and landing (connection end) — without interfering with the flight itself.
When you enable flow logs for a VPC, subnet, or network interface, the service captures metadata about each traffic flow: source IP, destination IP, source port, destination port, protocol, and actions (ACCEPT or REJECT). The logs are published to a destination — typically Amazon S3 or CloudWatch Logs — and you can query them later with tools like Athena or CloudWatch Logs Insights.
Key definitions
- Flow log: A record of network traffic metadata (not payload).
- Traffic flow: A unidirectional stream of IP packets that share source, destination, and port.
- Aggregation interval: The window (1 minute or 10 minutes) over which flows are captured and logged.
- Capture window: The period between when data is captured and when it appears in the destination — usually a few minutes.
Visualizing the flow
VPC
├─ Subnet A (public)
│ └─ EC2 instance (web server)
│ └─ ENI (elastic network interface) — flow logs attached
├─ Subnet B (private)
│ └─ RDS database — flow logs attached at VPC level
└─ Flow logs → S3 bucket → Athena queries
This mental model scales: you start with a single VPC, then extend flow logging to all VPCs in your organization as you mature.
How it works step by step
Setting up VPC flow logs for discovery follows a predictable sequence. Here's the high-level flow, and then we'll get into hands-on details.
- Choose the scope: VPC, subnet, or a specific network interface. VPC-level captures everything inside that VPC.
- Pick the destination: S3 bucket (best for long-term storage & analytics) or CloudWatch Logs (good for real-time monitoring).
- Set the format: Choose the fields you want to include — full format includes all fields like
srcaddr,dstaddr,srcport,dstport,protocol,action. - Enable the log through the AWS console, CLI, or Infrastructure as Code (like Terraform/CloudFormation).
- Query your logs: Once logs are flowing, use Athena (on S3) or Logs Insights to search for anomalies.
Cause and effect
- Enable flow logs → AWS starts publishing log records every minute (if you choose 1-minute aggregation) into your S3 bucket.
- Missing IAM permissions → Log delivery fails silently — you'll see no logs and no error in the console unless you check the flow log's
Status. - Adding more fields → Bigger log records, slightly higher S3 costs, but richer data for security analysis.
Hands-on walkthrough
Let's get practical. I'll show you how to set up VPC flow logs for discovery using two approaches: the AWS CLI (for scriptable control) and Terraform (for infrastructure as code).
Prerequisites
- AWS account with an existing VPC.
- AWS CLI configured (
aws configure) with sufficient permissions (ec2:CreateFlowLogs,s3:PutObject, etc.). - Basic familiarity with JSON and command line.
Step 1: Create an S3 bucket for logs
aws s3 mb s3://my-vpc-flow-logs-bucket --region us-east-1
Step 2: Enable flow logs via AWS CLI
Get the VPC ID first:
aws ec2 describe-vpcs --region us-east-1
Then create the flow log:
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-id vpc-0abc123def4567890 \
--traffic-type ALL \
--log-destination-type s3 \
--log-destination arn:aws:s3:::my-vpc-flow-logs-bucket \
--max-aggregation-interval 60 \
--log-destination-format '{"FieldNames":["version","account-id","interface-id","srcaddr","dstaddr","srcport","dstport","protocol","packets","bytes","start","end","action","log-status"]}'
Expected output:
{
"FlowLogIds": [
"fl-0abc123def4567890"
]
}
Step 3: Verify logs are being delivered
List your flow logs:
aws ec2 describe-flow-logs --region us-east-1 --filter "Name=flow-log-id,Values=fl-0abc123def4567890"
Check the Status field — it should be ACTIVE. After a few minutes, query S3:
aws s3 ls s3://my-vpc-flow-logs-bucket/ --recursive | head
You should see files with a path like AWSLogs/<account-id>/vpcflowlogs/us-east-1/YYYY/MM/DD/.
Step 4: Query with Athena (optional but powerful)
Once logs are in S3, you can run SQL-like queries. Create a table in Athena pointing to the S3 prefix, then run:
SELECT srcaddr, dstaddr, dstport, action, COUNT(*) AS attempts
FROM vpc_flow_logs
WHERE dstport = 3306
GROUP BY srcaddr, dstaddr, dstport, action
ORDER BY attempts DESC;
This reveals all attempts to connect to MySQL (port 3306) and whether they were accepted or rejected.
Hands-on with Terraform
If you manage infrastructure as code, here's the Terraform equivalent:
resource "aws_vpc_flow_log" "example" {
iam_role_arn = aws_iam_role.flow_logs.arn
log_destination = aws_s3_bucket.flow_logs.arn
traffic_type = "ALL"
vpc_id = aws_vpc.main.id
}
Compare options / when to choose what
| Feature | S3 destination | CloudWatch Logs destination |
|---|---|---|
| Cost | Lower per GB stored | Higher per GB ingested and stored |
| Query | Athena (SQL) — best for historical analysis | Logs Insights — great for real-time, but limited retention unless you extend |
| Data format | Structured files (gzip) | JSON logs in log groups |
| Security | Integrates with S3 bucket policies, encryption | Integrates with IAM, CloudWatch alarms |
| Use case | Long-term compliance, security discovery | Reactive alerting, live troubleshooting |
When to choose what?
- Security discovery at scale → S3 + Athena (cheap, flexible).
- Responding to live incidents → CloudWatch Logs (fast search) + CloudWatch Alarms.
- Both? You can even send to both! AWS supports two destinations per flow log.
Variations
- Subnet-level flow logs: More granular than VPC-level — good for isolating noisy subnets.
- Custom fields: Include
tcp-flagsto detect connection open/close patterns — useful for port scanning detection. - Third-party tools: Ship flow logs to tools like Splunk, Datadog, or Sumo Logic via S3/CloudWatch integrations.
Troubleshooting & edge cases
-
No logs appearing after hours → Check the flow log status:
aws ec2 describe-flow-logsand look forStatus=ERROR. Common cause: bucket policy missing. Your S3 bucket must have a policy allowingaws-logsservice to write.json { "Effect": "Allow", "Principal": {"Service": "delivery.logs.amazonaws.com"}, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::my-vpc-flow-logs-bucket/AWSLogs/*" } -
Logs are delayed by more than 5 minutes → Flow log capture is asynchronous; delays up to 10-15 minutes are normal. If it exceeds 15, check for network connectivity to the destination region.
-
Empty
srcaddr/dstaddrfields → These appear when the flow log captures traffic that doesn't have an IP (e.g., certain AWS-internal services). Filter them out when querying. -
Cost shock → Flow logs can generate large volumes. Use the 10-minute aggregation interval (instead of 1-minute) for less granular but cheaper capture, and set S3 lifecycle rules to expire old logs.
-
Permissions issue when using CloudWatch → Ensure your IAM role has
logs:CreateLogGroup,logs:CreateLogStream, andlogs:PutLogEvents. Also, the role trust policy must allowvpc-flow-logs.amazonaws.com.
What you learned & what's next
You now understand the core concept of VPC flow logs for discovery — what they are, how they work, and how to set them up using the CLI and Terraform. You learned how to choose between S3 and CloudWatch destinations, and you know how to troubleshoot common issues like missing bucket policies or silent permission failures.
You've met these learning objectives: - Explain the core idea behind setting up VPC flow logs for discovery. - Complete a practical exercise (CLI or Terraform) to enable flow logs in your environment.
Now that you have network visibility, you're ready for the next lesson in the Cloud security essentials track. You'll likely dive into analyzing these logs for threat hunting, or automating alerts based on suspicious traffic patterns. Stay sharp — the data is now flowing, but without proper analysis, it's just noise.
Happy hunting!
Practice recap
Practice exercise: If you have an AWS account, enable VPC flow logs for your default VPC using the CLI, choose 1-minute aggregation and S3 destination. Then, run a simple Athena query to list all traffic sent to port 22 (SSH). If you don't have an account, write the Terraform configuration for flow logs on a VPC with an S3 bucket and practice writing an Athena query to identify top talkers.
Common mistakes
- Forgetting to add the S3 bucket policy that allows the AWS logs delivery service to write — the flow log status shows ACTIVE but no data lands.
- Choosing 1-minute aggregation for all VPCs without monitoring cost — this can inflate S3 bills significantly on busy VPCs.
- Not including
tcp-flagsin the custom format — you lose the ability to detect port scans and connection state anomalies. - Creating flow logs at the VPC level, then widening the capture scope later requires duplicating setup — plan both VPC and subnet logs from the start.
Variations
- Use CloudWatch Logs destination with metric filters and alarms to trigger real-time responses (e.g., Lambda) when specific ports appear.
- Implement flow logs with Terraform modules (like Terragrunt) for multi-account setups, ensuring logs for all VPCs are centralized in a security account.
- Integrate flow logs (via S3 or CloudWatch) with open-source SIEMs like OpenSearch/Elasticsearch to correlate across multiple data sources.
Real-world use cases
- Detecting a data exfiltration attempt: an EC2 instance sending large amounts of data to an external IP on port 443, detected via Athena query on
bytesfield. - Troubleshooting a security group misconfiguration: users complain they cannot connect to an application; flow logs show
REJECTevents on port 8080, pinpointing a faulty rule. - Compliance auditing: enabling flow logs on all production VPCs and storing in S3 with lifecycle rules to meet CIS benchmark requirements for network monitoring.
Key takeaways
- VPC flow logs provide network-level visibility for discovery — they log metadata, not payloads, and are critical for detecting anomalies.
- Enable flow logs at VPC, subnet, or ENI level; choose 1-minute aggregation for closer to real-time detection, 10-minute for cost savings.
- Choose S3 destination for durable, queryable logs with Athena; CloudWatch for real-time scanning and alerting.
- Always configure proper permissions (IAM role for CloudWatch, bucket policy for S3) or logs silently fail.
- Query flow logs regularly — for example, for unexpected ports or rejected traffic — to turn raw data into security insight.
- The next step is automated analysis — building alerting and threat-hunting rules on top of your flow logs.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.