The server says it pushed the route, the client says it is connected, and the destination is still unreachable. Three causes produce that exact picture. The route add ran before the device existed, the client lacked the rights to change the table, or a policy told the client to ignore pushed options.

They look identical from the outside and need different fixes. Read the client log at the point where the route decision is made.

Prove the route is absent, not just broken

Start by proving the route is absent rather than broken. On Linux, ip route show dev tun0 lists what the client installed on the tunnel device. On Windows, route print or Get-NetRoute shows the same thing in table form.

A route that exists but does not forward traffic is a different problem. That moves the investigation to forwarding and firewall rules, not to route installation.

Timing: the add ran before the device existed

The client parses the server's PUSH_REPLY after the control channel is up and after it has configured the interface. Only then does it touch the routing table, using whatever mechanism the platform provides. Linux goes through netlink; Windows uses an API that needs an elevated token. A script or a client that adds routes as soon as it reads the configuration can run before the TUN/TAP device exists, and the kernel rejects the add.

The same race explains why a hand-typed route works while the automatic one does not: by the time you type it, the interface is up.

route-delay exists for this case, and route-up names a script that runs after the interface and routes are configured. Put routes that depend on the tunnel address in that hook rather than in an early stage.

Rights: who may change the table

Changing the Windows routing table needs an elevated token. A GUI started by a standard user may set the adapter address through the service and still be unable to add a route. The log then shows an access-denied style error rather than a missing push.

Starting the GUI as administrator, or using the service-based client, changes that outcome. A scheduled task that launches the client without the required token does not.

Check which account the client actually runs as before changing anything. The version and the service mode decide which causes are even possible, so record both next to the route output.

Policy: pushed routes can be discarded on purpose

route-nopull makes the client ignore routes the server pushes, including a pushed default route, while the tunnel address is still accepted. Pushed DNS and DHCP options are dropped by the same directive. Such a client is not faulty; it expects explicit route lines in its own configuration.

route-noexec is a different control: it stops the client from executing route changes at all. A topology the client cannot map can produce a similar result, with the route logged as rejected rather than added. Read the log line that reports the decision instead of guessing which of the three applies. Then check the effective profile, because an importer or management tool can add options the user never edited.

A profile that looks clean in a text editor can still carry an added directive at runtime.

Compare the push list with the table

After connecting, put the server's push list next to the client's table. On Linux that is ip route show dev tun0; on Windows, route print or Get-NetRoute. If the route is absent, fix installation first. If it is present and traffic fails, move on to forwarding and firewall policy.

Record the client version, the account it runs as and whether it is service-based. Those three facts tell the next person which causes were ruled out.

Lahatsoratra mifandraika