Skip to main content
idle · aws

Site-to-Site VPN connections billing hourly with no tunnel ever up

resource types
1
rule IDs covered
1
severity
medium

What does ZopNight detect here?

AWS Site-to-Site VPN bills a fixed connection-hour rate from the moment a connection exists, tunnels up or not. ZopNight requires 3 fully-covered CloudWatch axes over 30 days (TunnelState peaking at zero plus combined tunnel bytes under 1 MiB) before calling a connection idle and claiming its full measured cost.

Signal and threshold

How ZopNight evaluates Site-to-Site VPN connections billing hourly with no tunnel ever up.
Field Value
Rule IDsRC-162
Categoryidle
Severitymedium
Metricnone — pure configuration read
Sourcevpc_unused_vpn.go

Dead on both ends, billed in the middle

A Site-to-Site VPN whose customer gateway was decommissioned (the office closed, the appliance replaced, the migration finished) keeps billing its connection-hour fee indefinitely. Nothing on the AWS side notices that the far end no longer exists. These connections are common leftovers of network migrations, and the fee runs until someone deletes the connection object itself.

Three axes, all mandatory

Idleness here is corroborated across the AWS/VPN metrics a connection publishes, and any one of them can veto. TunnelState is the health gauge: the rule requires its window peak to be zero, meaning no tunnel was up at any moment in 30 days. One minute of connectivity anywhere in the window disqualifies. TunnelDataIn and TunnelDataOut are the traffic axes: their combined peak must sit at or below a 1 MiB floor, tolerating the keep-alive and dead-peer-detection chatter an up-but-unused tunnel emits while any real transfer disqualifies. Each axis must be present with a full 30 days of coverage; a missing or thin series abstains, because a connection you failed to measure is not a connection proven dead.

The cost side has the same discipline

The saving is the connection’s measured monthly fixed fee from the pricing pipeline, never a published-rate guess, and an unpriced connection abstains. Only connections in the available state are considered at all; anything mid-provisioning or deleting is in a different lifecycle and out of scope.

Reproduce the tunnel check

Terminal window
aws cloudwatch get-metric-statistics \
--namespace AWS/VPN --metric-name TunnelState \
--dimensions Name=VpnId,Value=vpn-0123456789abcdef0 \
--start-time "$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--period 3600 --statistics Maximum

Every datapoint at 0 is the no-tunnel-ever-up condition; repeat with TunnelDataIn and TunnelDataOut for the traffic axes.

Deleting the whole chain

The connection is only part of the bill of materials. After deleting it, check whether the virtual private gateway it attached to serves any other connection (an orphaned VGW is the next cleanup), and remove static routes referencing the VPN from your route tables. If the link is meant to come back someday, the honest comparison is redeploying the connection when needed versus paying the hourly fee to keep a dead one warm.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·