Solved Route default traffic to one interface, then another?

I am trying to get tailscale exit node functionality working from within a FreeBSD jail. Currently it doesn't work because tailscale attempts to add a second default route. This works on Mac, using (what I think is) a mechanism called route interface scopes.

Anyway, the tailscale device is a tun(4) device called tailscale0 and doesn't have a direct link to my gateway 192.168.2.1/24. The gateway link is via an interface called elink which is one end of an epair with IP 192.168.2.2/24.

Essentially I want a default route like 0.0.0.0/0 -> tailscale0 -> 192.168.2.1. All traffic should go to tailscale0, and if it doesn't have an explicit route for the destination, then it should forward to 192.168.2.1.

Is that possible?
 
There can be only one default gateway. It's even in the name. I like Cisco's description of it, "gateway of last resort", because that's exactly what it is. Routes have a 'weight' assigned to them, but the standard routing doesn't take this into account. You need a dynamic routing protocol for that (OSPF, BGP, etc).
 
its not clear what you want to achieve. do you want all traffic originating on the tailscale0 iface to go out thru it even if the routing table says otherwise ?
 
It was based on a lack of understanding on my part... the tunnel device needs to send traffic to one of a list of specific IPs. There's a client app that maintains the list of possible IPs to send to, and updates the tunnel device as needed. I determined that list of possible IPs, added routes for them through the gateway, and all works.

Which makes sense... that is what I was trying to do, without fully realizing / understanding it - have a small list of fixed routes go through the gateway, and then default everything else through tunnel device.

MacOS, on the other hand, does something that I think is strange, which is have multiple default routes:

Code:
% netstat -rn -f inet
Routing tables

Internet:
Destination        Gateway            Flags           Netif Expire
default            192.168.1.1        UGScg             en0
default            link#19            UCSIg           utun5

That I flag is the one that changes when defaulting to the utun5. According to the man page: I RTF_IFSCOPE Route is associated with an interface scope

The FreeBSD way is straightforward.
 
The macos way as far as I know allows a default per interface (as you pointed out with RTF_IFSCOPE), and the selection of a system default is based on the ordering of the network "services", ie ethernet/wifi/vpn/etc. This allows osx for example to select the default associated with a tun when the tun is active, overriding the default specified for the wifi IF the tun has a higher service priority. This is why, for example, when you are using wifi on a mac, and plug in ethernet, the ethernet default gateway overrides the wifi, by default macos gives the ethernet a higher service priority than the wifi.

Btw patmaddox, the way I handled a similar problem in the past with selective routing to a tunnel was to create a route-to rule in pf which was activated based on a set of ips in a pf table that were dynamically added/removed elsewhere. I liked doing it that way because it contained the additional dynamic routes in a pf table keeping the routing table actual clean. Either way works, just thought I would throw it out there.
 
Cool, thanks for that info about MacOS.

Yeah I tried route-to in pf as well... but failed because I was still missing the principle that specific IPs needed to be routed. I may try it just to understand how that approach works... but I'm also prepared for SirDice to remind us all that a firewall is not a router ;)
 
I'm not entirely sure what the your goal is here, but you could use different routing tables (FIBs) and use PF to route specific (or all) traffic between them.

But from what I understand from the first post, if tailscale0 is a tun device, it should have an endpoint and you use the router at the other end of the tunnel as your default gateway.
If you need a different default route to establish the tunnel, put that in its own routing table (usually the primary one) and all the traffic that should go through that tunnel in another table, e.g. by putting the whole interface(s) that are connected to the client network in fib 2. This routing table also holds the router at the other end of the tunnel (or the tunnel IP itself if its a routed tunnel instead of L2) as the default route.
You can always use PF to route between different FIBs via rtable N if necessary.
 
Back
Top