The client icon says connected, the interface exists, and the application still cannot reach anything. That combination is common, because a virtual interface can stay present while its remote peer, its addresses or its routes are missing. ip link is the right first tool, and it is also the easiest one to over-read. Flags and counters describe one layer, and the layers above them fail independently. It is also the tool people quote when they want to prove the tunnel is up, which is exactly the claim it cannot support on its own.

Read the interface before you read the icon

Start with ip -details link show dev tun0 as documented in the ip-link manual, substituting the interface your client actually owns rather than the conventional name. Flags, type, MTU and interface identity are useful observations. A virtual interface's state wording does not have to behave like a physical cable's carrier indication, so treat UP as a statement about the interface rather than about the tunnel.

That distinction explains the most confusing case: an interface that persists while the remote side is reconnecting or unreachable.

Persistence settings can keep the link around precisely so the reconnect does not rebuild it, which means presence is not health.

Add counters and a request that should use them

Use the supported statistics view, ip -s link show dev tun0, and note the packet and byte counts in both directions. Then generate a harmless request that should traverse the interface and compare the relevant direction. A request that took another application's direct route will not move those counters, and that is the point of the exercise.

If the transmit counter moves and the receive counter does not, the packet left and nothing came back. That is a different problem from an interface that never carried anything at all. If both counters move and the application still fails, the fault sits above the interface, which is progress rather than a dead end.

Take the reading twice, once before and once after, rather than trusting a single snapshot.

Addresses and routes are separate steps

A link can exist without the prefix, the resolver configuration or the route the application needs. Check the address with ip address show dev tun0, then check which route the destination would select with ip route get for the actual target. Those three observations answer three different questions, and only the last one is about forwarding.

For IPsec, security policy and association state may also matter, and not every IPsec design appears as a simple tun interface. Looking for a tun device that was never going to exist is a fast way to conclude the wrong thing.

Record the exact name, the namespace and the time with any output you keep, because the same-looking name in another container or a restored session represents another context entirely.

Do not delete what you have not identified

An unfamiliar interface is not automatically stale. Identify its owner before you remove anything, and use the client's documented teardown or the managed configuration when removal is genuinely intended. Deleting a live tunnel to see what happens is a test that answers a question nobody asked.

If the interface belongs to a container runtime or a network namespace you did not create, the owner is one command away and worth finding first.

That caution also applies to ip link set down, which looks reversible and often is not.

What the inspection should leave you with

A good inspection ends with four facts: the interface name and namespace, its flags and MTU, the counter delta from a real request, and the route and address the application actually needs. With those written down, the next step is obvious and belongs to a specific layer. Without them, every subsequent change is a guess with a rollback plan.

Compare those four facts against the same four from a working session. If the interface name and namespace match but the counter delta is zero, the request never reached the tunnel. If the counter delta is healthy and the route points elsewhere, the tunnel is fine and the routing is not. That comparison is what turns a pile of output into a decision.

Keep the output with the ticket, since a later comparison is only useful if you can see what changed.

Then close the loop by testing the application again, because the interface was never the thing the user cared about.

Skyldar greinar