¶ What's Going On
The routing table you see when you type
ip route show
isn't the only routing table the kernel uses. In fact, there are three routing tables by default, and they are searched in the order shown by theip rule
command:# ip rule show 0: from all lookup local 32766: from all lookup main 32767: from all lookup default
The table you're most familiar with is main, but the highest-priority routing table is local. This table is managed by the kernel to keep track of local and broadcast routes: in other words, the local table tells the kernel how to route to the addresses of its own interfaces. It looks something like this:
# ip route show table local broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 broadcast 192.168.1.0 dev eth0 proto kernel scope link src 192.168.1.2 local 192.168.1.1 dev tun0 proto kernel scope host src 192.168.1.1 local 192.168.1.2 dev eth0 proto kernel scope host src 192.168.1.2 broadcast 192.168.1.255 dev eth0 proto kernel scope link src 192.168.1.2
Check out that line referencing
tun0
. That's what's causing your strange results from route get. It says 192.168.1.1 is a local address, which means if we want to send an ARP reply to 192.168.1.1, it's easy; we send it to ourself. And since we found a route in the local table, we stop searching for a route, and don't bother checking the main or default tables.¶ Why multiple tables?
At a minimum, it's nice to be able to type
ip route
and not see all those "obvious" routes cluttering the display. It can also serve as some minimal protection against misconfiguration: even if the main routing table has gotten mixed up, the kernel still knows how to talk to itself.(Why keep local routes in the first place? So the kernel can use the same lookup code for local addresses as it does for everything else. It makes things simpler internally.)
There are other interesting things you can do with this multiple-table scheme. In particular, you can add your own tables, and specify rules for when they are searched. This is called "policy routing", and if you've ever wanted to route a packet based on its source address, this is how to do it in Linux.
If you're doing especially tricky or experimental things, you can add or remove local routes yourself by specifying table local in the ip route command. Unless you know what you're doing, though, you're likely to confuse the kernel. And of course, the kernel will still continue to add and remove its own routes, so you have to watch to make sure yours don't get overwritten.
Finally, if you want to see all of the routing tables at once:
ip route show table all