Linux kernel would allow me to add routes with gateways that were merely reachable, since there's no issue with them in practice. But nowadays i get "Error: Nexthop has invalid gateway" which is fine to follow specs and make adhoc testing of things a pain.
Is there any way to bypass this check and force my route?
And yes, I do want to fire my private lan routed packages over a public interface, the reasons are valid, low volume and harmless :)
To use a gateway that is on the same local network (e.g. the same Ethernet as you), but merely outside your IP address range so the OS doesn't realize it's locally reachable:
With recent kernels: Specify the
onlink
parameter to the command.With older kernels the option was only honored for a single IP version (I don't remember which). The alternative is to first add a 'device' route for the gateway as a /32 or /128, which will make the OS consider it reachable:
This is functionally identical to the automatically-added "local subnet" route that you already have from your own IP address. Indeed you can define a whole address range/subnet as 'local' this way, if you wish.
Often, even if the ethernet uses several disjoint IPv4 subnets, it's likely that all devices will be in a single IPv6 subnet, so if you happen to know the gateway's IPv6 address (global or link-local), you can route IPv4 through that:
(This doesn't use tunneling or address translation – just a different way of resolving the gateway's MAC address.)
Note that ISPs can easily prevent all of this by blocking direct ARP between customers and doing ARP-proxying so that all packets end up going through the gateway even if the destination seems like it would be local subnet-wise.
Most home gateways nowadays also come with predefined firewall rules that block packets from WAN to their internal network, specifically to prevent such hacks.
To use a gateway that is not physically on the same local network (Ethernet, etc) as you:
Can't be done. The gateway IP address is really a stand-in for the gateway's local network MAC address (i.e. it's not an IP header field but a lower layer thing), so if the gateway is not on the same local network as you, then you can't send packets to its MAC address, thus you cannot route through it.
IPv4 used to support a 'Source Route' header at some point (likewise 'RH0' in IPv6), which could be used to ask gateway A to please route via gateway B next, but it was universally deprecated and removed decades ago.
This can be interpreted in two ways, but only really works if the OS actually ignores the "reachable by 0.0.0.0 route" part and treats the gateway as reachable directly on link (as in the first part of the answer).
The other interpretation of the OS following the 0.0.0.0 route (i.e. treating your route as "recursive") wouldn't work, as per second part of the answer – it would only result in the packets going through your regular gateway, which you cannot control any further.
(Linux actually has a
pervasive
flag for routes which seems like it was once meant to perform recursive gateway lookup, but it is nonfunctional and seems to have had its (two lines worth of) supporting code removed in 2010. In practice usually recursive lookups would be done by a routing daemon anyway.)