People ask where an AWS Site-to-Site VPN stops protecting the packet and expect a single answer: at the gateway. The useful version of that answer names which gateway, because a virtual private gateway and a transit gateway are different arrangements with different attachment objects, and the reviewer who assumes the wrong one builds the rest of the assessment on a diagram that does not exist. Work the three checks below in order. Each one either confirms the boundary or tells you that the previous answer was about a different resource.

Name the three endpoints before you assess anything

An encryption review of this path needs three named things: the customer gateway, the AWS VPN target that terminates IPsec, and the application endpoint that receives the inner packet. Write them down with their resource identifiers before opening a single console page, because everything after this point is a statement about one of those three.

The customer gateway is yours and its configuration is visible to you. The AWS target is a managed resource, and the mistake is assuming it: a VPN connection can attach to a virtual private gateway or directly to a transit gateway, and neither implies the other. The third endpoint is the one people skip, and it is the only one that answers the actual question about application data.

Check 1: which gateway actually ends the tunnel

Both arrangements are supported and the Site-to-Site VPN architecture guide describes them side by side, so ask the API rather than a diagram that is often a year old. A read-only query on one connection returns the VPN target fields:

aws ec2 describe-vpn-connections --region eu-west-1   --vpn-connection-ids vpn-0123456789abcdef0   --query 'VpnConnections[0].{VGW:VpnGatewayId,TGW:TransitGatewayId,CGW:CustomerGatewayId,Category:Category}'

The discriminator is TransitGatewayId, not VpnGatewayId. A connection with TransitGatewayId empty terminates on a standalone virtual private gateway, while a connection with that field set terminates on a transit gateway VPN attachment, and VpnGatewayId may still be populated in that case because it can name the attachment's backing gateway. Read the TGW field first, then confirm the attachment type from the attachment list rather than from a field name, because a VPC attachment on that transit gateway is not the VPN attachment. Finding the destination instance in an attached VPC tells you nothing about which VPN attachment carried the packet.

While you are there, check the tunnels. The connection carries two IPsec tunnels for redundancy, and a connection whose second tunnel has never come up is a real finding for availability even though it changes nothing about the encryption boundary:

aws ec2 describe-vpn-tunnels --region eu-west-1   --filters Name=vpn-connection-id,Values=vpn-0123456789abcdef0   --query 'VpnTunnels[].{Outside:OutsideIpAddress,State:State,Status:Status}'

Check 2: what the inner packet still carries

Once IPsec terminates, AWS forwards the decapsulated packet using the route that matched it. From that point the traffic is ordinary VPC traffic, and the VPN's protection has ended. That is not a gap in the service; it is what the boundary means, and the checklist item is to state it plainly instead of letting "the VPN is encrypted" stand in for "the data is encrypted end to end".

Now inspect what was inside. If the inner packet is a plaintext application protocol, nothing downstream adds confidentiality until something else encrypts it. If the inner packet already carries a TLS session, the outer IPsec removal changes nothing for that session: it stays protected to its own endpoint, wherever that endpoint is.

The common overcorrection is to conclude that everything behind the gateway is exposed. It is not. Service transport, storage encryption and application TLS are separate mechanisms with separate conditions, and each has to be assessed on its own terms rather than inferred from the VPN's shape. A flow log entry showing ACCEPT proves that routing worked and says nothing about confidentiality, which is exactly the mistake this checklist exists to prevent.

Check 3: what terminates TLS behind the gateway

Follow the listener, not the address. If a load balancer or proxy terminates TLS, the connection your client holds ends there, and the proxy opens a second connection to the backend that may be plaintext or may be TLS with a different trust chain. A private IP address and a matching route are not evidence about that second connection.

Test the endpoint you actually care about from inside the VPC, with the name the application uses rather than an IP you resolved once:

openssl s_client -connect internal.example:443 -servername internal.example -verify_return_error

Repeat it for each hop the request passes through. If the answer differs between the client-facing name and the backend name, you have found exactly the segment the VPN never covered, and that is the finding to write down.

Record the result as segments, not as a verdict

The output of this checklist is a small table with one row per segment: customer gateway to AWS VPN target, gateway to workload, workload to data store, and any proxy hop in between. Each row says what protects it and what that protection depends on. "Encrypted" with no mechanism and no endpoint is not a row.

Then answer the original requirement in the same terms it was asked. If the requirement is that data stays confidential until the workload receives it, the VPN satisfies the first segment only, and the remaining rows need application transport, service TLS or storage encryption configured and verified separately.

Keep the connection identifiers, the tunnel states and the certificate subjects in the record. When someone revisits the design in six months, those three artifacts answer the boundary question in minutes instead of restarting the argument from a diagram.

Lahatsoratra mifandraika