--snat-subnet-routes flag vs iptables -t nat

Hi there.
I am unsure what the --snat-subnet-routes flag actually does on linux and its relation to iptables. The document for setting up a subnet router (which assumes snat) mentions setting up firewalld: firewall-cmd --permanent --add-masquerade. This actually enables an ipables rule.

the site-to-site doc suggests disabling snat using the --snat-subnet-routes=false.

Now, I undersdand snat, and am currently running a node without firewalld, where I set up my own MASQUERADE rule:

iptables -t nat -A POSTROUTING -o eth0 -s ! -d -j MASQUERADE

Notice how I am omitting a particular subnet above.

Now, this just works and seems to work whether I set the --snat-subnet-routes to true or false so I am a bit confused as to what the flag is actually supposed to do on linux. Is it safe to just leave it at “false” and manually do all my snat/masquerade via iptables?

1 Like

--snat-subnet-routes defaults to enabled and will make connections via the subnet router use the subnet router’s IP address when passing connections along to that subnet.

If it is disabled, devices on that subnet will see the Tailscale IP address of the device that made the connection. That will typically work fine if the subnet router is also that device’s default gateway but otherwise will require extra configuration to set up routes for to the subnet router. If that configuration is not added, the device on the subnet will send its responses to the Internet and will be dropped by the ISP, rather than going back through Tailscale.

But that is normally the domain of iptables -t nat tables. I understand the purpose, my question is specifically, what is the tailscale daemon doing with this flag, which is not already being done by setting the appropriate POSTROUTING rule in iptables.

Oh, the flag determines if it creates the POSTROUTING rule or not.

1 Like

If you want the full technical details:

It creates a MASQUERADE rule in ts-postrouting if the SNAT subnet routes flag is set, otherwise it doesn’t.


A-ha. So it is essentially the same as manually adding the same iptable rule via the iptables command. This is good, and should be clarified in the documentation. Also, I should have had the good sense to look at the source :slight_smile:

What is confusing, is that the documentation for subnet routers (Subnet routers and traffic relay nodes · Tailscale), suggests that the user adds the following for firewalld:

firewall-cmd --permanent --add-masquerade

But all this does is to also add a similar iptables entry. This then looks redundant. Could the reason for this be clarified?

In short, then, the conclusion is:

  1. tailscale automatically adds a MASQUERADE rule unless --snat-subnet-routes is set to false
  2. If you want to do not masquerade, or do your own fancy masquerade rules, set --snat-subnet-routes to false and modify the iptables yourself.

Thanks for the clarification.

1 Like

In that situation you might want to set netfilter mode to no-divert or off. No-divert will avoid modifying POSTROUTING and similar but will create the ts-* chains that you can configure your firewall to use; off won’t even create those. Keep in mind that the other iptables things being done includes packet markers to prevent routing loops which you may lose if managing the firewall rules yourself.


Thanks. I wasn’t aware of all the netfilter stuff that Tailscale was setting up, and hadn’t come across the --netfilter flag.

Can you clarify why the subnet router documentation requires the abovementioned firewall-cmd to be issued, if tailscale is already configuring the netfilter tables directly?

1 Like