Connected, green tray icon, and an address-echo page still reporting the provider's address does not automatically mean a fault. A client does two separate jobs: it builds a tunnel, and it edits the routing table. Either can happen without the other, and selective routing is the configuration where the second is deliberately skipped.

What the client actually installed

Ask which interface would carry a packet to a real destination rather than asking whether the tunnel is up. A tunnel with no route for that destination is a private road nobody is using.

ip route get 9.9.9.9
Find-NetRoute -RemoteIPAddress 9.9.9.9
route print -4

The first command answers on Linux and macOS, and the other two are the Windows equivalents where one is enough. If the answer names the physical adapter, the tunnel is up and the default route never moved. Repeat the lookup for a destination that should use the tunnel, because two lookups, one remote and one ordinary, tell you which design is deployed.

Three shapes of selective routing

A full-tunnel profile typically writes a default route pointing at the interface, or writes the pair of half-range prefixes that win on prefix length while the original default stays in the table. Selective routing is the other choice, and it comes in several forms. One profile routes a single host such as an RDP server, another routes a public range that must be reached from a particular location, and a third deliberately excludes one application. All three are legitimate, and none of them changes the address a general website sees.

grep -nE "redirect-gateway|route-nopull|route " /etc/openvpn/client/*.conf
ip route show table main | head -20

Read the profile for the directive that decides, then read the table for what it produced. A pushed directive can also be suppressed on the client, which is why the profile and the table have to agree before you blame the server.

The far side must rewrite the source address

There is a second failure that looks identical from the browser. The route points into the tunnel, the server receives the packets, and then forwards them with the client's private address intact. The next hop has no return path for that address, so replies vanish and pages hang. The server has to forward at all, and it has to translate the source into something the internet can route back.

sysctl net.ipv4.ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -S | grep MASQUERADE

Name the interface that actually faces the internet, which is not always eth0 on a modern distribution. A hosted server with a fixed address can translate to that address explicitly instead of using masquerade. Both halves matter, since forwarding without translation leaks unroutable sources while translation without forwarding never sees the packet.

Name resolution takes its own path

Traffic can exit through the tunnel while the lookup that found the name went to a resolver on the local network. The visible address stays the same, the queries do not, and that gap is exactly what a split-DNS design is choosing.

resolvectl status | head -20
resolvectl query example.org

Note which server answered and whether it differs from the pre-tunnel baseline. On a split tunnel this is usually the setting people wanted to change when they complained about the address, and it is the one they never looked at.

Four observations that settle it

Capture the exit address with the tunnel down, then with it up. Run the destination lookup in both states and note the interface each time.

curl -sS https://ifconfig.me/ip
ip route get 9.9.9.9

When the lookup lands inside the tunnel and the echo still reports the provider's address, translation at the exit is missing. When the lookup lands on the physical adapter, the profile is selective and the public address was never in scope. Substitute an echo service you trust and record the four observations together, because separately they are anecdotes. Together they identify which of the two jobs the client actually performed.

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