== How I made IPSec IKE work for a point to point GRE tunnel on Fedora 20 The basic overview of [[my IPSec needs MyIPSecRequirements]] is that I want to make my home machine (with an outside address) appear as an inside IP address on the same subnet as my work machine is on. Because of Linux proxy ARP limitations, the core mechanics of this involve a GRE tunnel, which must be encrypted and authenticated by IPSec. Previously I was doing this with a static IPSec configuration created by direct use of _setkey_, which had the drawback that it didn't automatically change encryption keys or notice if something went wrong with the IPSec stuff. The normal solution to these drawbacks is to use an [[IKE https://en.wikipedia.org/wiki/Internet_Key_Exchange]] daemon to automatically negotiate IPSec (and time it out if the other end stops), but unfortunately this is not a configuration that IKE daemons such as Fedora 20's Pluto support directly. I can't really blame them; anything involving proxy ARP is at least reasonably peculiar and most sane people either use routing on subnets or NAT the remote machines. My first step to a working configuration came about after [[I fixed my configuration to block unprotected GRE traffic IptablesBlockNonIpsec]]. Afterwards I realized this meant that I could completely ignore managing GRE in my IKE configuration and only have it deal with IPSec stuff; I'd just leave the GRE tunnel up all the time and if IPSec was down, the iptables rules would stop traffic. After I gritted my teeth and read through the [[libreswan https://libreswan.org/]] _ipsec.conf_ manpage, this turned out to be a reasonably simple configuration. The core of it is this: .pn prewrap on conn cksgre left= leftsourceip= right= ikev2=insist # what you want for always-up IPSec auto=start # I only want to use IPSec on GRE traffic leftprotoport=gre rightprotoport=gre # authentication is: authby=rsasig rightrsasigkey=[...] leftrsaksigkey=[...] The two IP addresses used here are the two endpoints of my GRE tunnel (the 'remote' and 'local' addresses in '_ip tunnel <...>_'). Note that this configuration has absolutely no reference to the local and peer IP addresses that you set on the inside of the tunnel; in my setup IPSec is completely indifferent to them. I initially attempted to do authentication via PSK aka a (pre) shared secret. This caused my setup of the Fedora 20 version of Pluto to dump core with an assertion failure ([[for what seems to be somewhat coincidental reasons https://bugzilla.redhat.com/show_bug.cgi?id=1168407]]), which turned out to be lucky because there's a better way. Pluto supports what it calls 'RSA signature authentication', which people who use SSH also know as 'public key authentication'; just as with SSH, you give each end its own keypair and then list the public key(s) in your configuration and you're done. How to create the necessary RSA keypairs and set everything up is not well documented in the Fedora 20 manpages; in fact, I didn't even realize it was possible. Fortunately I stumbled over [[this invaluable blog entry on setting up a basic IPSec connection http://mescanef.net/blog/2014/05/encrypted-network-traffic-between-two-linux-hosts-the-ipsec-way/]] which covered the magic required. This got the basic setup working, but after a while the novelty wore off and my urge to fiddle with things got the better of me so I decided to link the GRE tunnel to the IKE connection, so it would be torn down if the connection died (and brought up when the connection was made). You get your commands run on such connection events through the _leftupdown="..."_ or _rightupdown="..."_ configuration setting; your command gets information about what's going on through a pile of environment variables (which are documented in the ((ipsec_pluto)) manpage). For me this is a script that inspects (($PLUTO_VERB)) to find out what's going on and runs one of my existing scripts to set up or tear down things on _up-host_ and _down-host_ actions. As far as I can tell, my configuration does not need to run the default '((ipsec _updown))' command. (My existing scripts used to do both GRE setup and IPSec setup, but of course now they only do the GRE setup and the IPSec stuff is commented out.) This left IPSec connection initiation (and termination) itself. On my home machine I used to bring up and tear down the entire IPSec and GRE stuff when my PPPoE DSL link came up or went down. In theory one could now leave this up to a running Pluto based on its normal keying retries and timeouts; in practice this doesn't really work well and I wound up needing to do manual steps. Manual control of Pluto is done through '_ipsec whack_' and if everything is running smoothly doing the following on DSL link up or down is enough: > ipsec whack --initiate|--terminate --name cksgre >/dev/null 2>&1 Unfortunately this is not always sufficient. Pluto does not notice dynamically appearing and disappearing network links and addresses, so if it's (re)started while my DSL link is down (for example on boot) it can't find either IP address associated with the _cksgre_ connection and then refuses to try to do anything even if you explicitly ask it to initiate the connection. To make Pluto re-check the system's IP addresses and thus become willing to activate the IPSec connection, I need to do: > ipsec whack --listen Even though the IPSec connection is set to autostart, Pluto does not actually autostart it when _--listen_ causes it to notice that the necessary IP address now exists; instead I have to explicitly initiate it with '_ipsec whack --initiate --name cksgre_'. My current setup wraps this all up in a script and runs it from _/etc/ppp/ip-up.local_ and _ip-down.local_ (in the same place where I previously invoked my own IPSec and GRE setup and stop scripts). So far merely poking Pluto with _--listen_ has been sufficient to get it to behave, but I haven't extensively tested this. My script currently has a fallback that will do a '_systemctl restart ipsec_' if nothing else works. PS: Note that taking down the GRE tunnel on IPSec failure has some potential security implications in my environment. I think I'm okay with them, but that's really something for another entry. === Sidebar: What ((ipsec _updown)) is and does On Fedora 20 this is ((/usr/libexec/ipsec/_updown)), which runs one of the ((_updown.*)) scripts in that directory depending on what the kernel protocol is; on most Linux machines (and certainly on Fedora 20) this is NETKEY, so ((_updown.netkey)) is what gets run in the end. What these scripts can do for you and maybe do do for you is neither clear nor documented and they make me nervous. They certainly seem to have the potential to do any number of things, some of them interesting and some of them alarming. Having now scanned ((_updown.netkey)), it appears that the only thing it might possibly be doing for me is mangling my _/etc/resolv.conf_. So, uh, no thanks.