Turn off source NAT on a Tailscale subnet router and the tunnel keeps working while the connections through it stop. Requests arrive at the destination carrying the remote client's own overlay address, which is exactly the point of the change, and replies now need a path the LAN never had to know about. Without that path the packets land, the replies leave by the ordinary gateway, and the failure presents itself as a firewall problem that no firewall rule explains. The tunnel is healthy; the return leg is missing.

What SNAT was hiding

With SNAT enabled, the router rewrites the source address to its own LAN address before forwarding into the subnet, so the destination replies to a host it already knows how to reach and nothing else needs configuring. Disabling it preserves the original source, and the destination then sees an address inside the overlay range rather than a neighbour on its own wire. That address is real and routable across the tailnet, and it is unreachable from the LAN through the default gateway. The documented switch is --snat-subnet-routes=false, applied to the Linux subnet router itself.

It is a standing setting rather than a per-packet toggle, so the return path has to be in place for every destination network that router serves. That is what makes the change a deployment decision instead of a checkbox. Anything served by that router inherits the requirement at the same moment.

Where the return path can live

Three placements are common, and they differ in reach rather than in correctness. A static route on the destination host is the most direct and the least scalable, since every device needs its own copy. A route table in the VPC or the site router covers a whole network at once, and a DHCP option carrying classless static routes reaches clients automatically but fails quietly on devices that ignore it.

ip route add 100.64.0.0/10 via 192.168.1.10
ip route get 100.64.0.5

Whichever placement you choose, the next hop is the router's LAN address and never its tailnet address. A LAN host cannot reach the overlay until it holds this route, so a next hop inside the overlay is circular and sends the packet nowhere. That single mistake accounts for most configurations that look right and still fail, and it survives every check that reads only the router's own table. Write down which placement you used, because the next person will otherwise test the wrong one.

Reading the failure as one-way traffic

The symptom is easier to recognise than the cause: the service answers on the router itself and stays silent from a remote client. A capture on the destination shows requests arriving and replies leaving, which looks like success until you notice where those replies are headed. They are going to the default gateway, which means the inbound leg worked and the return leg did not.

Capture on the router instead, because it sees both directions of one exchange and shows whether a reply ever arrived. If the reply appears on the destination but never on the router, the route is missing or wrong on the destination side. If it appears on the router and stops there, the problem lies further along and belongs to a different investigation.

sudo tcpdump -ni any host 100.64.0.5
ip route get 100.64.0.5

Whether the real address is worth a route

Keeping SNAT remains the simpler answer whenever the destination network cannot be reconfigured, and the cost is that every client looks like the router in the destination's logs and policy. Turning it off is justified when an application needs the real source address or when network policy has to distinguish clients that share a router. Both are legitimate reasons and neither is free. The benefit has to be worth maintaining a route on every destination network, plus the firewall review described below.

For one small LAN the trade usually pays, while for a sprawl of appliances that cannot take a static route it usually does not. Record the decision and the reason beside the router configuration, so the next administrator knows which behaviour is deliberate. A default that nobody wrote down is indistinguishable from an oversight.

Firewall, logging and the doubled role

Every rule that matched the router's LAN address now matches a different source, and that includes allow rules and any log field that recorded the router as the client. Read those rules before the first test rather than after the first failure, because a rule permitting only the router's address blocks the new source outright. Narrow the replacement to the clients and ports that need it, then confirm it does not quietly admit the whole tailnet.

sudo nft list ruleset | grep -n '100\.64'
sudo iptables-save | grep -n '100\.64'

One node serving as both exit node and subnet router is a documented combination that can drop upstream traffic once subnet SNAT is disabled. Separating those roles onto different nodes removes the caveat and gives each route and firewall policy a single owner. If the roles have to stay together, expect the behaviour and test it before blaming a client. Keep the route, the switch setting and the role assignment in one note, because they get read together when the next connection fails.

Qillqakuna t'inkisqa