My Linux IPSec/VPN setup and requirements

November 25, 2014

In response to my entry mentioning perhaps writing my own daemon to rekey my IPSec tunnel, a number of people made suggestions in comments. Rather than write a long response, I've decided to write up how my current IPSec tunnel works and what my requirements are for it or any equivalent. As far as I know these requirements rule out most VPN software, at least in its normal setup.

My IPSec based GRE tunnel runs between my home machine and my work machine and its fundamental purpose is to cause my home machine to appear on the work network as just another distinct host with its own IP address. Importantly this IP address is publicly visible, not just an internal one. My home machine routes some but not all of its traffic over the IPSec tunnel and for various reasons I need full dual identity routing for it; traffic to or from the internal IP must flow over the IPSec tunnel while traffic to or from the external IP must not. My work machine also has additional interfaces that I need to isolate, which can get a bit complicated.

(The actual setup of this turns out to be kind of tangled, with some side effects.)

This tunnel is normally up all of the time, although under special circumstances it needs to be pulled down locally on my work machine (and independently on my home machine). Both home and work machines have static IPs. All of this works today; the only thing that my IPSec setup lacks is periodic automatic rekeying of the IPSec symmetric keys used for encryption and authentication.

Most VPN software that I've seen wants to either masquerade your traffic as coming from the VPN IP itself or to make clients appear on a (virtual) subnet behind the VPN server with explicit routing. Neither is what I want. Some VPNs will bridge networks together; this is not appropriate either because I have no desire to funnel all of the broadcast traffic running around on the work subnet over my DSL PPPoE link. Nor can I use pure IPSec alone, due to a Linux proxy ARP limitation (unless this has been fixed since then).

I suspect that there is no way to tell IKE daemons 'I don't need you to set things up, just to rekey this periodically'; this would be the minimally intrusive change. There is probably a way to configure a pair of IKE daemons to do everything, so that they fully control the whole IPSec and GRE tunnel setup; there is probably even a way to tell them to kick off the setup of policy based routing when a connection is negotiated. However for obvious reasons my motivation for learning enough about IKE configuration to recreate my whole setup is somewhat low, as much of the work is pure overhead that's required just to get me to where I already am now. On the other hand, if a working IKE based configuration for all of this fell out of the sky I would probably be perfectly happy to use it; I'm not intrinsically opposed to IKE, just far from convinced that investing a bunch of effort into decoding how I need to set it up will get me much or be interesting.

(It would be different if documentation for IKE daemons was clear and easy to follow, but so far I haven't found any that is. Any time I skim any of it I can see a great deal of annoyance in my future.)

PS: It's possible that my hardcoded IPSec setup is not the most modern in terms of security, since it dates from many years ago. Switching to a fully IKE-mediated setup would in theory give me a free ride on future best practices for IPSec algorithm choices so I don't have to worry about this.

Sidebar: why I feel that writing my own rekeying daemon is safe

The short version is that the daemon would not involved in setting up the secure tunnel itself, just getting new keys from /dev/urandom, telling the authenticated other end about them, writing them to a setkey script file, and running the necessary commands to (re)load them. I'd completely agree with everyone who is telling me to use IKE if I was attempting to actively negotiate a full IPSec setup, but I'm not. The IPSec setup is very firmly fixed; the only thing that varies is the keys. There are ways to lose badly here, but they're almost entirely covered by using a transport protocol with strong encryption and authentication and then insisting on fixed IP addresses on top of it.

(Note that I won't be negotiating keys with the other end as such. Whichever end initiates a rekey will contact the other end to say more or less 'here are my new keys, now use them'. And I don't intend to give the daemon the ability to report on the current keys. If I need to know them I can go look outside of the daemon. If the keys are out of sync or broken, well, the easy thing is to force an immediate rekey to fix it, not to read out current keys to try to resync each end.)

Comments on this page:

By Ewen McNeill at 2014-11-25 03:37:52:

As best I can tell from your various notes you:

  1. have a GRE tunnel secured by transport-mode IPSEC now (rather than tunnel mode IPSEC); transport mode IPSEC might be The Future (tm), but has been The Future (tm) for some time now (almost all IPSEC I encounter is still tunnel mode, and some of it is GRE-in-IPSEC-tunnel-mode in order to get around the "baked in" routing limitations of IPSEC); and

  2. it sounds like what you're trying to achieve is basically a proxy-arp bridge between the LAN interface of your work machine and an internal logical interface (not the LAN interface) of your home machine. A proxy-arp "bridge" is routed, rather than actually bridged, so it basically only gets unicast traffic -- and ARP replies for the address are handled on its behalf (by the machine that is the "proxy" ARP).

In which case:

  1. a GRE tunnel secured by anything should work fine, give or take packet overhead: AFAICT GRE over IPSEC Transport mode is 55 bytes overhead; OpenVPN seems to be 69 bytes in TUN mode, plus another 24 bytes for GRE + IPv4 headers is 93 bytes -- so 38 bytes/packet more, which may be tolerable.

  2. you could run OpenVPN in bridge mode ("tap"), which also transports ethernet headers, another 26 bytes -- but you wouldn't need GRE. So it'd be 40 bytes more/packet AFAICT (69+26 = 95 - 55 = 40). To achieve the filtering that you want, you don't want to bridge the LAN inteface into the tunnel at your work end (or your home end -- given its only one machine). You probably want an isolated Linux bridge interface at each end, and then to proxy ARP for an address at your work end, and route that address over the tunnel at your work end (off the top of my head you probably need a linknet on the two isolated bridge interfaces to route at; IIRC you can only route at an interface if it's a point to point one, and a bridge/tap is not)

  3. if you were willing to switch to GRE inside IPSEC tunnel mode, then you could let the IKE daemon handle setting up the tunnel, and then just leave the GRE up all the time with addresses only reachable via the IPSEC (eg, again dummy linknets on internal bridges; using firewall rules to stop it leaking out unencrypted). This is a pretty common approach to "dynamic routing over IPSEC" AFAICT (certainly, eg, Amazon AWS works like that if you want BGP over the link).

FWIW I've never tried transport mode IPSEC with an IKE daemon. I know that FreeSWAN/OpenSWAN had a bunch of work on doing that sort of thing (for opportunistic encryption), but I have a strong impression it saw minimal use in the field. I've also never tried the OpenVPN-tap-mode-into-Linux-bridge thing, but off hand I can't think of a reason it wouldn't work.

At this point it seems to me you have a trade off between "a few more bytes overhead per packet, but with a canned solution" or "writing software -- to make your own rekeying solution" (or for completeness: sticking with what you have, or trying to make an IKE daemon do transport mode rekeying -- but keep in mind that you could still do the GRE yourself). Personally I'd go with one of the canned solutions -- probably GRE-over-OpenVPN or GRE-over-IPSEC-tunnel-mode-with-IKE-keying, but then I'm at least as much a "network" person as a sysadmin/developer these days.


By cks at 2014-11-25 07:44:24:

Whoops, my lack of clarity. So let me cover two bits.

First, at the low level my link is actually a GRE tunnel inside tunnel mode IPSec. I initially tried transport mode IPSec but then discovered TTL issues that forced a switch to tunnel mode IPSec. As for packet overhead, the exact packet overhead isn't a particularly strong consideration. I'm actually using a very conservative MTU on the tunnel today because I couldn't be bothered to work out (or find out) the theoretical maximum MTU that fit inside my PPPoE MTU. This probably slows down bulk transfers slightly, but I rarely do them over the link and so far I don't care enough to do better.

Second, for me the real tradeoff is between 'design and configure something else using an IKE daemon or VPN software' and 'maybe write a rekeying daemon'. I already have this GRE over tunnel mode IPSec setup working with standard software (although it's low-level stuff; I directly create SPDs and SADs via Linux's setkey).

(I went with the direct setup at the time I set it up because while I managed some sort of proper configuration with IKE, rekeying didn't seem to work in that having it happen broke things. I assume that it works now. The IKE setup was before I worked out the policy based routing I needed and so on and I don't think I saved the actual daemon configuration or even remember what daemon I tried to use back then. There was a relatively extended learning process necessary at the time.)

By Ewen McNeill at 2014-11-25 21:58:53:

Since you're already using IPSEC Tunnel Mode, you could have IKE setup/rekey that, and just set up the GRE yourself (or have it set up in an on-up style script you write yourself -- {Open,Free}SWAN have those at minimum).

IKE rekeying certainly used to have a bunch of timing-related fragility issues in the past (especially if one end rekeyed/timed out, and the other end didn't either allow both keys in parallel for a while or process the delete of the old key). But off hand I don't recall seeing IKE rekeying breaking things in years (aside from a Cisco ASA, where the problem wasn't the rekeying causing the wrong key to be used, but their reapplication of firewall rules on rekeying which appeared to have its own races, sometimes leading to all ESP traffic being blocked :-( ).

So maybe it'd be worth re-investigating IKE keying (just with a shared passphrase as the keying authenticator, for simplicity) at some point.


Written on 25 November 2014.
« Delays on bad passwords considered harmful, accidental reboot edition
Using go get alone is a bad way to keep track of interesting packages »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Nov 25 00:25:56 2014
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.