Routing tables get misread as broken whenever the gateway column comes up empty, when the line is usually complete on its own. The via field appears only when the kernel hands the packet to a next-hop address; a route attached to an interface reaches its destinations through link-layer resolution or through a point-to-point peer instead. Reading the columns left to right tells you which case you are in, and that reading should happen before anyone edits a default route. Most tickets about a missing gateway end at this distinction.

Read a route line column by column

Every entry opens with the destination and its prefix length, then adds modifiers in a fixed vocabulary: via, dev, proto, scope, src and metric. A line such as 198.51.100.0/24 dev tun0 proto kernel scope link src 198.51.100.2 is dense but fully specified. Nothing is missing from it, and no router address is implied.

The absence of via is the interesting part. Without a next hop, the kernel resolves the destination directly on the named interface, which for a tunnel means handing the frame to the tunnel device and letting the encapsulation take it from there. proto kernel records that the entry was installed automatically when an address was assigned, not typed by an administrator. scope link says the destination is reachable on that link without passing through a router, and src names the address the kernel will prefer as the source for traffic that matches.

Now read a default route the same way: default via 192.0.2.254 dev eth0 proto static metric 100. Here via is present because the packet does need a next hop, and that next hop must itself be reachable on eth0. The two lines are not variants of one another; they answer different questions about where traffic goes.

Two route shapes that get confused with each other

A tunnel subnet route and a default route look similar in a screenshot and behave nothing alike. Use the table below as a reading aid for the fields, then confirm the actual numbers on the machine you are debugging rather than trusting a sample from a guide.

Piece of the lineWhat it settlesWhat it says nothing about
The destination and maskWhich packets are eligible to matchWhere those packets leave the host
via plus its addressWhich next hop receives them, and therefore that a router is involvedWhether that router is reachable or sane
devWhich interface carries the encapsulated or raw packetWhether the interface is up or has a carrier
proto and scopeWho installed the entry and how far the destination is considered to beWhether a firewall later drops the traffic

What the table cannot tell you is intent. A direct route to a private range through a tunnel is a deliberate split-tunnel design; the same shape appearing on a host that should send everything through the VPN is a symptom. Intent lives in the configuration that produced the entry, so look at the tool that installed it before you conclude the kernel got something wrong.

Equally, a missing gateway is not permission to invent one. If a route genuinely needs a next hop, the next hop has to be reachable on the interface that carries it, and for a point-to-point tunnel the peer address is not the same object as the local address. Treating the local tunnel address as an Ethernet router is a common way to produce a route that looks correct and forwards nothing.

Ask the kernel which line it will actually use

Reading the table is not the same as performing the lookup, because the kernel consults policy rules, several tables and cached entries before it answers. The verb that performs the real lookup is ip route get, and it prints the route that a packet with those properties would take.

ip route get 203.0.113.37 from 198.51.100.2 iif tun0

Swap in the destination you actually care about, then add from or iif when the traffic is source-selected or forwarded, because an ordinary local lookup can pick a different path than a forwarded client does. The reply names the interface, the source address chosen, and any next hop, which is the same information a packet would be routed with at that moment.

If the answer surprises you, print the rules before editing anything: ip -4 rule show lists them in priority order, and a VPN client that installs its own table or a rule for marked packets will not appear in the main table at all. Listing every table closes that gap.

ip -4 route show table all | grep -E 'tun|default'

Check the underlay before you replace the default

The tunnel's own packets have to reach the remote endpoint, and they do that through the physical interface using the route that existed before the VPN came up. Replacing the whole default route without pinning that endpoint sends the encapsulated packets into the tunnel they are supposed to build, and the connection collapses. Confirm the endpoint path first with a lookup for the endpoint address alone.

Keep three things separate when you make the change: the endpoint route that must stay on the physical interface, the private ranges that should enter the tunnel, and the default that decides everything else. Break them apart in that order, apply one at a time, and re-run the lookup after each step. A failed ping afterwards proves very little on its own, since permissions, reply routing, DNS and the service itself all sit downstream of a correct route.

Write down the four values the line gave you before the edit: destination, next hop or its absence, device, and chosen source. If a later change moves any of them, you know which decision was actually altered, and you can restore one entry instead of guessing at the whole table.

Ngaahi tokoni fekau'aki