The VPN terminates on an EC2 instance, you can reach that instance's tunnel address, and traffic meant to pass through it toward another private host disappears. Those are two different tests, and mixing them wastes hours. The first asks whether you can reach the instance; the second asks it to forward traffic for a destination that is not its own, which needs Linux forwarding, a firewall policy, a route on the far side, and an AWS-level permission that has nothing to do with the guest operating system. Nothing in the console calls attention to that difference. The symptom looks like a routing fault, and it usually is not.

Separate the two tests before you change anything

Reaching the gateway proves the tunnel, the route to its address, and the security group that permits the exchange. Forwarding for another host proves none of those things: it exercises a different source address, a different destination, and an instance acting in a role it was not necessarily built for. Write the two tests separately and note which one fails, because the correction for each lives in a different console. A gateway instance built only to terminate tunnels has no reason to forward for anything else, and its defaults reflect that. Which is why the second test needs its own setup rather than a small tweak to the first.

A ping that works to the gateway and a ping that fails to the host beyond it is not an intermittent problem. It is the expected behaviour of an instance that has not been told it may forward.

Write the path down before touching a setting

Record the client prefix, the forwarding instance or network interface, the target subnet, and the reply route. A VPC route table entry pointing at an instance does not configure the instance's operating system to forward, and a guest kernel with forwarding enabled does not create a VPC route. Both ends of that relationship have to exist, and they are edited in different places by people with different access.

Then inspect the source/destination check setting on the actual forwarding component, not on every instance in the VPC. AWS documents why an instance that forwards traffic for others needs that check disabled, and also why the setting is a per-instance decision rather than a VPC-wide default.

Four boundaries, and the check is only one of them

Treat the path as four questions and answer them in order. The first failing answer is where the work is, and none of the others will compensate for it.

BoundaryQuestion it answers
VPC route tablesDo the destinations and replies select the intended gateway?
Forwarding instanceDo the AWS check and the guest OS both permit forwarding?
Access policyDo security groups, ACLs and host rules allow the exchange?
DestinationCan the service accept that source and return a reply?

The order matters because it is cheap to cheap: routes are visible in one page, the check is a single attribute, and the destination's opinion is usually the last thing anyone asks for.

Translation changes which source the destination sees

A routed design preserves the client's source address, so the destination needs a return route to the client prefix. A translated design presents the gateway's address instead, which removes that requirement and replaces it with a state table on the gateway. Decide according to the architecture you intend, rather than adding translation because an unrelated example used it and appeared to work.

If you translate, scope the rule to the client prefix and the intended destination. If you preserve, confirm the far side actually knows the route rather than assuming it will learn one.

Test from the original client, then keep the change

A request generated on the gateway can succeed while a forwarded request fails, because it is a different source and a different forwarding case. After a targeted correction, repeat the exact client-to-resource test that failed, from the same client, and confirm the reply comes back rather than only that the request arrived.

Finally, put the setting into the gateway's managed configuration so a replacement instance receives it. A successful test that depends on a manual exception is a test that expires at the next rebuild, and the person who discovered it will not be there to remember why.

Nuŋlɔɖi siwo ku ɖe eŋu