Laptops behind a home router with no port forward still accept SSH connections that arrive over the VPN. That is not a contradiction, because two different devices are judging two different packets. The router forwards the encrypted transport, and the host decides what to do with the decrypted packet that reaches its tunnel interface. Keeping those two decisions apart is the whole exercise.

The router forwards the tunnel, the host judges the packet

Sketch the path from the remote source to the service before you look at a single rule. The outer leg is the VPN transport, handled by the router and the gateway. The inner leg starts once the endpoint strips the tunnel layer and the host receives a packet addressed to its VPN address.

Merge those two legs and the router gets credit for a decision the host makes. A port-forward page or a router log describes outer conversations only, and neither says which decrypted traffic the host will accept. The host applies its own inbound policy to the inner packet, in the same way it would to any packet arriving on an interface. That policy is where the exposure question is actually settled.

A wildcard listener is not a public service

On Linux, binding to INADDR_ANY means every local address, so a service can answer on a tunnel interface it never named. The IP socket reference describes that binding, and it is worth reading before drawing conclusions from a listener list. A wildcard entry is a fact about the socket, not a statement about reachability.

The two lines below are the same service in two different bindings, and the difference is the whole answer to whether the interface matters. Read which address the socket sits on before anything else.

ss -lntp "sport = :22"
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3))
LISTEN 0 4096 10.8.0.6:22 0.0.0.0:* users:(("sshd",pid=812,fd=4))

Name the arrangement that could reach the port

Three arrangements put a packet on that interface, and they have different owners. Naming the right one decides who has to change a policy.

ArrangementWhat reaches the portWhere the decision lives
Another permitted VPN peerA packet from the same tunnel subnetGateway forwarding policy and host input rules
A deliberate public forwardTraffic the gateway publishes on purposeGateway service definition
A subnet routed behind the gatewayClient traffic from the far sideGateway route and host input rules

A browser result showing a public exit address tells you nothing about any of the three, because it describes how outbound traffic leaves rather than what inbound traffic is allowed in. Work backwards from the listener and the source address in the service log instead. If the source is another tunnel peer, the gateway policy is the interesting document. If it is a translated address, find the translation before you change a rule.

Scope the service to the path you intended

If SSH is only needed from a management path, write that path down as a source range plus an interface. Then scope the host inbound rules by interface, destination and source rather than by network name, since a name that looks private can stand for any address. Keep a route in for the person who will fix the next problem.

nft add rule inet filter input iifname "tun0" ip saddr 10.8.0.0/24 tcp dport 22 accept
nft list chain inet filter input

A rule that names the tunnel interface and the management range states the intent in one place. Compare it with a rule written for the Wi-Fi network, which says nothing about decrypted tunnel traffic. When the two layers disagree, the host policy is the one the packet meets.

Leave logins and patching exactly where they are; reaching a port was never the same as being allowed to use it. Record the address family and time for any unfamiliar source, and investigate before blaming a feature or a vulnerability. A rule that admits every tunnel peer is a different design from one that admits a management subnet, and no log line will tell you which was intended.

Accept the fix with one success and one refusal

Prove both halves: one approved connection succeeds and one excluded path is refused. The refusal is the half people skip, and it is the one that shows the rule is doing work rather than sitting beside a permissive default. Test from the excluded side rather than reasoning about it.

Repeat the pair after a reconnect, because a tunnel that returns with a different interface name can quietly bypass a rule scoped to the old one. The boundary that matters is the one the host applies to packets it actually receives.

Lahatsoratra mifandraika