How to extend "Use UFW to lock down an Ubuntu server" to outbound traffic?

Tailscale says, “Your tailnet is your space. The internet cannot reach it.”

Let’s say I want some machines to be virtually situated exclusively on my tailnet, such that the Internet cannot reach them and that they cannot, without use of a Tailscale exit node, reach the Internet.

I want to provision a Linux machine, likely running Debian or a derivative on 86-64/AMD64 hardware, with networking exclusively over Tailscale, preventing any inbound or outbound traffic that is not on my tailnet. Using multiple machines configured in this manner, I hope to simulate a private network, with software on the machines able to communicate with others on the tailnet, and prevented from connecting to anything else on my physical network, thus also prevented from connecting to machines elsewhere on the Internet.

I initially assumed that this would be as simple as some firewall configuration on the machine that denies all traffic other than on the applicable port. Such is apparently not the case.

I read the Tailscale how-to guide, “Use UFW to lock down an Ubuntu server,” and I can make all of that work, but the procedure described there allows all outgoing traffic. If I prohibit outbound traffic and enable the firewall prior to tailscale up, then of course the machine cannot reach the various control plane endpoints that tailscaled needs.

I also read the Tailscale FAQ entry, “What firewall ports should I open to use Tailscale?.”

I searched but did not find related discussion on this forum.

I considered the idea that this could be accomplished by arranging for each machine’s firewall to prevent non-tailscale inbound traffic and to allow all outbound traffic (as in the aforementioned how-to guide), then to restrict outbound traffic for those machines on the gateway they use, presumably segregating them with a “Tailscale-only” subnet or VLAN, and having the applicable router restrict outbound traffic from that subnet or VLAN. But then I would be back in the position of needing to restrict traffic in a way that permits Tailscale control traffic, prohibits other traffic, and does so in a way that does not cause problems if and when the list of control plane or DERP relay servers changes.

Also, there’s DNS and likely DHCP to consider, here. Tailscale can provide DNS after it’s started, but unless I statically configure networking on these machines (I would prefer not to), they will need to reach a DHCP server before they enable their Tailscale networking.

Enabling an exit node should add the firewall rules to route all traffic over the tailnet.

I think this is implemented by setting the default route to the tailscale adapter.

sudo tailscale up --exit-node=<exit-node-ip>

An other option for doing this is to play with namespaces as described on the wireguard site: Routing & Network Namespaces - WireGuard