VPC Flow Logs analysis in GCP: spotting exfiltration
Use Google Cloud VPC Flow Logs in an investigation: record fields, sampling caveats, egress per external IP, and matching audit-log attacker IPs to VM traffic.
TL;DR. VPC Flow Logs are the only Google Cloud log that shows what a compromised VM sent over the network. They exist only for subnets where they were enabled beforehand, they are sampled, and bytes are estimates. Sum bytes_sent per external destination IP where the reporter is your VM, look at the top destinations during the incident window, and, above all, match the attacker IPs from the audit logs against flow peers: an IP that called your APIs and talked to your VMs ties the control plane to the data plane.
Audit logs tell you what was done through Google Cloud APIs. Data read by a process inside a VM (a database dump, files on a disk, secrets in memory) and sent out over HTTPS never appears there. Flow logs fill that gap, with limits you must state in the report.
What a flow record contains
Flow logs are written to projects/PROJECT/logs/compute.googleapis.com%2Fvpc_flows with a jsonPayload. Google's record reference lists the fields; these carry the investigation:
| Field | Use |
|---|---|
connection.src_ip, src_port, dest_ip, dest_port, protocol | The 5-tuple |
start_time, end_time | The aggregation window of the record |
bytes_sent, packets_sent | Estimated volume from source to destination |
reporter | SRC or DEST: which side's VM reported the flow |
src_instance, dest_instance | VM name, zone, project when the endpoint is a VM |
src_location, dest_location | For public IPs: ASN, country, region, city |
Three properties from Google's VPC Flow Logs overview shape everything else:
- Sampling: the primary sampling rate is dynamic and not configurable; the secondary rate defaults to 50% for configurations made through the Compute Engine API. Bytes and packets are estimated from sampled packets.
- Aggregation: records cover an interval (5 seconds by default, configurable up to 15 minutes).
- No payload: only metadata.
And one from practice: flow logs only exist where someone enabled them (per subnet, network or organization) before the incident. Default retention in Cloud Logging is 30 days.
Direction matters: read the reporter
A flow between two of your VMs can be reported twice, once by each side. A flow between your VM and the Internet is reported by your VM only. To measure egress:
- keep records where
reporter = SRCandsrc_instanceis set (your VM is the sender), and dest_ipis a public address (not RFC 1918, not Google's Private Google Access ranges you use).
Then sum bytes_sent by dest_ip. The top of that list, restricted to the incident window, is your exfiltration candidate list. dest_location.asn and country help separate a CDN from a VPS.
Correlate with the audit logs
The strongest use of flow logs is correlation. The audit logs give you attacker IPs (requestMetadata.callerIp) from the API side. If the same IP appears in flow records:
- Inbound to port 22 after a
setMetadataaddingssh-keysand a VMreset: the attacker logged in with the key they injected. See Compute Engine abuse. - Outbound on 443 from the VM, many records, growing volume: a backdoor from a startup script phoning home, or data leaving. MITRE T1071 for command and control, T1048 for exfiltration over another protocol.
That link, API-side IP equal to network-side peer, turns two partial stories into one timeline.
Querying flow logs
Logs Explorer works for a first look:
logName:"compute.googleapis.com%2Fvpc_flows"
jsonPayload.connection.dest_ip="203.0.113.66"
For volume per destination over a month, route flow logs to BigQuery and aggregate there, or export them as JSON (see Cloud Audit Logs explained; the export paths are identical) and drop them into the analyzer together with the audit logs.
What the analyzer does with flow logs
The analyzer aggregates flow records in the browser and produces:
- VPC flows tab: total records and bytes, bytes sent to Internet addresses, and the largest flows (source, destination, port, bytes, records).
- IP entities: for each caller IP, the bytes sent to it and received from it according to flow logs.
flow_large_egress(medium, exfiltration, T1048): at least 1 GiB sent from your VMs to a single public IP.flow_ioc_match(high, command and control, T1071): an IP behind a high-severity audit finding (or a key used from a new IP) also exchanged traffic with your VMs. The target reads like203.0.113.66 ↔ etl-worker-1 (1.9 GiB out, 47.1 KiB in).
Both feed the attack-chain correlation. In the fictional walkthrough, the flow match is what shows that the startup-script backdoor actually ran.
Limits to state in the report
- No flow logs, no conclusion. If the subnet had flow logs disabled, "no large egress" means nothing.
- Estimates. Give volumes as approximate, with the sampling caveat.
- Blind spots by design. Traffic that never leaves through a logged interface (for example through a proxy, or copied through Google APIs rather than the network) needs other evidence: the GCS and BigQuery exfiltration article covers API-side copies.
- Shared infrastructure. An attacker using a cloud provider's IP range may share it with legitimate services; confirm with timing and ports.
Before the next incident
Enable flow logs on subnets hosting sensitive workloads, keep a secondary sampling rate you can afford, and route them to long-term storage together with the audit logs. Using VPC Flow Logs explains the settings.
Frequently asked questions
Do VPC Flow Logs show the content of the traffic?
No. VPC Flow Logs record flow metadata only: source and destination IPs and ports, protocol, estimated bytes and packets, the reporting side, VM and location details. There is no payload.
Are VPC Flow Logs byte counts exact?
No. Google describes bytes_sent and packets_sent as estimates based on sampled packets and recommends aggregating over longer periods or several resources for accuracy. Use them to rank destinations and size an exfiltration, not as an exact figure.
Further reading
- VPC Flow Logs overview — Google Cloud documentation.
- Flow log record format — Google Cloud documentation.
- MITRE ATT&CK T1048, Exfiltration Over Alternative Protocol.