I have configured two Linux boxes so they automatically use a transport-level IPSec connection whenever they need to communicate. The configuration is based on Racoon with X509 authentication and the bundle_complex
option set to on
, as well as policies that require both ESP and AH between the two boxes.
While the configuration works, generally speaking, the first few packets are always lost, e.g.:
$ ping -c 3 A.B.C.D
PING A.B.C.D (A.B.C.D) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
64 bytes from A.B.C.D: icmp_req=3 ttl=64 time=0.497 ms
Is there any way to prevent this, for example by "delaying" the packets until the IPSec transport has been negotiated?
The first packet (and all others until negotiation is completed) is always discarded.
This is true of every ISAKMP implementation that I've dealt with. I don't believe that there's necessarily any reason that it couldn't buffer the packets that are being discarded; rather, it shouldn't.
This is an extension of a conscious design decision that's used throughout the internet's routing infrastructure: Don't hold packets.
Routing systems on the internet will always discard a packet instead of delaying it, when they aren't able to (nearly) immediately route it. Packet loss on the internet as a whole could easily be reduced to far lower levels by simply keeping a packet buffered until there's room for it. But, therein lies the problem; an overloaded router running 200ms behind on a first-in, first-out queue would delay every single packet by that 200ms.
Bringing this back to the ISAKMP situation; holding a couple of pings until the path is ready to carry them is great, but what if it's a constant stream of hundreds of thousands of UDP packets? And what if the remote system is inaccessible, so the ISAKMP sits there waiting for an ISAKMP negotiation message 2 for 60 seconds?
While these are not insurmountable engineering problems, the conventional wisdom in the internet engineering community is that it's far simpler and easier to have client systems deal with packet loss issues themselves, primarily through the use of loss-tolerant protocols like TCP.
You could auto-start IPSEC tunnel before any traffic starts to flow (usually those first dropped packets initiate the IKE negotiation). Here is how to do that with StrongSwan:
Though I still haven't figured out how to do the same thing with racoon, but I guess there should be something similar as well.