The site loads from a laptop on the same network and times out from everywhere else, and the host is also running a VPN client for its own outbound traffic. That combination produces a specific failure: the inbound connection arrives, the reply leaves by the wrong path, and the client outside never sees an answer. Both halves show up in the same packet capture, so the order of events is the part worth reading.

A source-based routing rule often fixes the symptom. It also usually exempts more traffic than the site that motivated it, which is the part worth understanding before you save the rule.

The Symptom: It Answers Locally and Not From Outside

Inside the network the reply does not have to cross the tunnel, so the page loads and the service looks healthy. From outside, the request reaches the host and the response is routed into the VPN, where the remote end has no reason to accept it. The browser sees a timeout rather than a refusal, which is the signature of a one-way path rather than a closed port.

Confirm the shape before you change routing: the listener is up, the local request succeeds, and the external request produces no reply at all. Those three observations together point at the return path instead of at the web server configuration. An asymmetry that clean is more useful than any log line, because it rules out the listener before you read a single error message.

Keep an independent administration path open while you work. A rule that breaks your own SSH session turns a ten-minute fix into a physical visit.

What a Source Selector Actually Matches

In Linux policy routing, a rule such as from 192.168.50.2 matches packets whose source is that address. It does not encode the fact that the packet continues a conversation which entered through the home router, and it does not know which process created it. The address in that example is illustrative; substitute the address your host actually uses. Treat the line as a statement about addresses and nothing more.

If the selected table supplies an ordinary default route, every packet carrying that source can take the same exception. Another service bound to the same address inherits it, and an application that deliberately binds to that address inherits it too. The policy rule reference lists source, destination, protocol, port, mark and priority as separate selectors, which is a reminder that the source alone is the bluntest one available.

Priority decides the outcome. Lookups run in order and the first table that produces a result can end the search, so a rule placed too early can hide a more specific route that a later table would have supplied. Read the whole ordered list rather than the single line you added. A rule that never matches costs nothing, while one that matches too early silently changes everything behind it.

Check the Reply Path and the Traffic You Did Not Intend

Read the rules and the tables, then ask the kernel which route a specific source and destination pair would take. Testing from the host itself is not the same as testing from outside, so do both.

ip rule show
ip route show table 100
ip route get 203.0.113.44 from 192.168.50.2
ss -ltnp '( sport = :443 )'

Then accept a fresh external connection and, separately, a request that must still leave through the VPN. If the second one now exits directly, the exception is wider than the problem you were solving, and the test that matters is the one you did not intend to change.

A public address check in a browser only reports the requests that browser made. It says nothing about the web server's replies, about another local application's source selection, or about what happens to management traffic after the next VPN reconnect.

Decide How Narrow the Exception Can Be

Two designs are defensible and they should be chosen deliberately. If the host exists to publish this service and its outbound traffic is unimportant, a dedicated local address with a WAN-only policy is a reasonable arrangement provided you accept the whole scope. If only particular inbound connections should qualify, address selection is too coarse and a connection-aware design belongs in front of it.

Record the contract you are relying on: the public mapping, the host address the request is delivered to, and the path the reply is expected to take. An inbound service published through a VPN provider is a different contract from one published through a home router, and an exception copied from one example is often wrong for the other.

Persist the policy in the component that owns routing rather than pasting a command into a startup file. Rule order, cleanup after a network change and replay after a reboot all have to survive, and an untested startup file usually fails at the moment you are not watching. Finish with the acceptance result you can defend: one published site restored and one unrelated flow unchanged.

Qillqakuna t'inkisqa