An annoying limitation of Linux IPSec
I just got IPSec doing exactly what I need it to do. Unfortunately it turns out not to do me any good.
The problem is with tunnel mode IPSec, which has a cascade of issues. First, IPSec tunnels don't create actual network devices. This sounds harmless, except that you need a network device to establish routes and thus say things like 'network foo/24 is reachable over this IPSec tunnel'.
IPSec deals with this with black magic involving Security Policy Descriptors. If you add an SPD for a tunnel mode IPSec connection, IPSec magically starts routing packets for the target of the SPD, without any sort of routing table entry being created.
Which creates my real problem: proxy ARP. The core kernel proxy ARP stuff only responds to ARP queries for things it knows it routes to, ie things that are in the routing table. No routing table entry, no answer to the ARP query for the IP address at the far end of the IPSec tunnel.
(And there seems to be no proxy ARP stuff apart from the core kernel
stuff; I haven't found a working way to manually publish an ARP entry or
the like. Both
ip sort of have options for it, but neither
appears to do anything in practice.)
The net result is that although my IPSec connection works great between the two machines directly involved (and the SPDs involved were trivial to write and worked the first time), it doesn't do me any good because I can't get any other machine to send packets for the far end of the IPSec connection to the near end.
So, in summary: Linux IPSec tunnels are incompatible with proxy ARP, which means that you can't use simple IPSec to push a single IP address on your subnet off to a remote machine. Presumably this hasn't been fixed before now because most people use IPSec tunnels to shuffle around full subnets that get routed explicitly.
(GRE over IPSec is clearly in my future. GRE works fine for this because GRE tunnels are real network devices, with all the resulting benefits.)