How I made IPSec IKE work for a point to point GRE tunnel on Fedora 20
The basic overview of my IPSec needs 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 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.
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 ipsec.conf
manpage,
this turned out to be a reasonably simple configuration. The core of it
is this:
conn cksgre left=<work IP alias> leftsourceip=<work IP alias> right=<home public IP> 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), 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 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.
|
|