In the previous section, encryption was configured using simple shared secrets. In other words, to remain secure, we need to transfer our encryption configuration over a trusted channel. If we were to configure the remote host over telnet, any third party would know our shared secret and the setup would not be secure.
Furthermore, because the secret is shared, it is not a secret. The remote can't do a lot with our secret, but we do need to make sure that we use a different secret for communicating with all our partners. This requires a large number of keys, if there are 10 parties, this needs at least 50 different secrets.
Besides the symmetric key problem, there is also the need for key rollover. If a third party manages to sniff enough traffic, it may be in a position to reverse engineer the key. This is prevented by moving to a new key every once in a while but that is a process that needs to be automated.
Another problem is that with manual keying as described above we exactly define the algorithms and key lengths used, something that requires a lot of coordination with the remote party. It is desirable to be able to have the ability to describe a broader key policy such as 'We can do 3DES and Blowfish with at least the following key lengths'.
To solve these isses, IPSEC provides Internet Key Exchange to automatically exchange randomly generated keys which are transmitted using asymmetric encryption technology, according to negotiated algorithm details.
The Linux 2.5 IPSEC implementation works with the KAME 'racoon' IKE daemon. As of 9 November, the racoon version in Alexey's iptools distribution can be compiled, although you may need to remove #include <net/route.h> in two files. Alternatively, I've supplied a precompiled version.
IKE needs access to UDP port 500, be sure that iptables does not block it. |
As explained before, automatic keying does a lot of the work for us. Specifically, it creates Security Associations on the fly. It does not however set policy for us, which is as it should be.
So, to benefit from IKE, setup a policy, but do not supply any SAs. If the kernel discovers that there is an IPSEC policy, but no Security Association, it will notify the IKE daemon, which then goes to work on trying to negotiate one.
Reiterating, a Security Policy specifies WHAT we want; a Security Association describes HOW we want it. Using automatic keying lets us get away with only specifying what we want.
Kame racoon comes with a grand host of options, most of which have very fine default values, so we don't need to touch them. As described above, the operator needs to define a Security Policy, but no Security Associations. We leave their negotiation to the IKE daemon.
In this example, 10.0.0.11 and 10.0.0.216 are once again going to setup secure communications, but this time with help from racoon. For simplicity this configuration will be using pre-shared keys, the dreaded 'shared secrets'. X.509 certificates are discussed in a separate section, see Section 7.2.3>.
We're going to stick to almost the default configuration, identical on both hosts:
path pre_shared_key "/usr/local/etc/racoon/psk.txt"; remote anonymous { exchange_mode aggressive,main; doi ipsec_doi; situation identity_only; my_identifier address; lifetime time 2 min; # sec,min,hour initial_contact on; proposal_check obey; # obey, strict or claim proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method pre_shared_key; dh_group 2 ; } } sainfo anonymous { pfs_group 1; lifetime time 2 min; encryption_algorithm 3des ; authentication_algorithm hmac_sha1; compression_algorithm deflate ; }
Lots of settings - I think yet more can be removed to get closer to the default configuration. A few noteworthy things. We've configured two anonymous settings which hold for all remotes, making further configuration easy. There is no need for per-host stanzas here, unless we really want them.
Furthermore, we've set it up such that we identify ourselves based on our IP address ('my_identifier address'), and declare that we can do 3des, sha1, and that we will be using a pre-shared key, located in psk.txt.
In psk.txt, we now setup two entries, which do differ on both hosts. On 10.0.0.11:
10.0.0.216 password2On 10.0.0.216:
10.0.0.11 password2Make sure these files are owned by root, and set to mode 0600, racoon will not trust their contents otherwise. Note that these files are mirrors from eachother.
Now we are ready to setup our desired policy, which is simple enough. On host 10.0.0.216:
#!/sbin/setkey -f flush; spdflush; spdadd 10.0.0.216 10.0.0.11 any -P out ipsec esp/transport//require; spdadd 10.0.0.11 10.0.0.216 any -P in ipsec esp/transport//require;And on 10.0.0.11:
#!/sbin/setkey -f flush; spdflush; spdadd 10.0.0.11 10.0.0.216 any -P out ipsec esp/transport//require; spdadd 10.0.0.216 10.0.0.11 any -P in ipsec esp/transport//require;Note how again these policies are mirrored.
We are now ready to launch racoon! Once launched, the moment we try to telnet from 10.0.0.11 to 10.0.0.216, or the other way around, racoon will start negotiating:
12:18:44: INFO: isakmp.c:1689:isakmp_post_acquire(): IPsec-SA request for 10.0.0.11 queued due to no phase1 found. 12:18:44: INFO: isakmp.c:794:isakmp_ph1begin_i(): initiate new phase 1 negotiation: 10.0.0.216[500]<=>10.0.0.11[500] 12:18:44: INFO: isakmp.c:799:isakmp_ph1begin_i(): begin Aggressive mode. 12:18:44: INFO: vendorid.c:128:check_vendorid(): received Vendor ID: KAME/racoon 12:18:44: NOTIFY: oakley.c:2037:oakley_skeyid(): couldn't find the proper pskey, try to get one by the peer's address. 12:18:44: INFO: isakmp.c:2417:log_ph1established(): ISAKMP-SA established 10.0.0.216[500]-10.0.0.11[500] spi:044d25dede78a4d1:ff01e5b4804f0680 12:18:45: INFO: isakmp.c:938:isakmp_ph2begin_i(): initiate new phase 2 negotiation: 10.0.0.216[0]<=>10.0.0.11[0] 12:18:45: INFO: pfkey.c:1106:pk_recvupdate(): IPsec-SA established: ESP/Transport 10.0.0.11->10.0.0.216 spi=44556347(0x2a7e03b) 12:18:45: INFO: pfkey.c:1318:pk_recvadd(): IPsec-SA established: ESP/Transport 10.0.0.216->10.0.0.11 spi=15863890(0xf21052)
If we now run setkey -D, which shows the Security Associations, they are indeed there:
10.0.0.216 10.0.0.11 esp mode=transport spi=224162611(0x0d5c7333) reqid=0(0x00000000) E: 3des-cbc 5d421c1b d33b2a9f 4e9055e3 857db9fc 211d9c95 ebaead04 A: hmac-sha1 c5537d66 f3c5d869 bd736ae2 08d22133 27f7aa99 seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Nov 11 12:28:45 2002 current: Nov 11 12:29:16 2002 diff: 31(s) hard: 600(s) soft: 480(s) last: Nov 11 12:29:12 2002 hard: 0(s) soft: 0(s) current: 304(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 3 hard: 0 soft: 0 sadb_seq=1 pid=17112 refcnt=0 10.0.0.11 10.0.0.216 esp mode=transport spi=165123736(0x09d79698) reqid=0(0x00000000) E: 3des-cbc d7af8466 acd4f14c 872c5443 ec45a719 d4b3fde1 8d239d6a A: hmac-sha1 41ccc388 4568ac49 19e4e024 628e240c 141ffe2f seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Nov 11 12:28:45 2002 current: Nov 11 12:29:16 2002 diff: 31(s) hard: 600(s) soft: 480(s) last: hard: 0(s) soft: 0(s) current: 231(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 2 hard: 0 soft: 0 sadb_seq=0 pid=17112 refcnt=0As are the Security Policies we configured ourselves:
10.0.0.11[any] 10.0.0.216[any] tcp in ipsec esp/transport//require created:Nov 11 12:28:28 2002 lastused:Nov 11 12:29:12 2002 lifetime:0(s) validtime:0(s) spid=3616 seq=5 pid=17134 refcnt=3 10.0.0.216[any] 10.0.0.11[any] tcp out ipsec esp/transport//require created:Nov 11 12:28:28 2002 lastused:Nov 11 12:28:44 2002 lifetime:0(s) validtime:0(s) spid=3609 seq=4 pid=17134 refcnt=3
If this does not work, check that all configuration files are owned by root, and can only be read by root. To start racoon on the foreground, use '-F'. To force it to read a certain configuration file, instead of at the compiled location, use '-f'. For staggering amounts of detail, add a 'log debug;' statement to racoon.conf.
As mentioned before, the use of shared secrets is hard because they aren't easily shared and once shared, are no longer secret. Luckily, there is asymmetric encryption technology to help resolve this.
If each IPSEC participant makes a public and a private key, secure communications can be setup by both parties publishing their public key, and configuring policy.
Building a key is relatively easy, although it requires some work. The following is based on the 'openssl' tool.
OpenSSL has a lot of infrastructure for keys that may or may not be signed by certificate authorities. Right now, we need to circumvent all that infrastructure and practice some good old Snake Oil security, and do without a certificate authority.
First we issue a 'certificate request' for our host, called 'laptop':
$ openssl req -new -nodes -newkey rsa:1024 -sha1 -keyform PEM -keyout \ laptop.private -outform PEM -out request.pemThis asks us some questions:
Country Name (2 letter code) [AU]:NL State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:Delft Organization Name (eg, company) [Internet Widgits Pty Ltd]:Linux Advanced Routing & Traffic Control Organizational Unit Name (eg, section) []:laptop Common Name (eg, YOUR name) []:bert hubert Email Address []:ahu@ds9a.nl Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:It is left to your own discretion how completely you want to fill this out. You may or may not want to put your hostname in there, depending on your security needs. In this example, we have.
We'll now 'self sign' this request:
$ openssl x509 -req -in request.pem -signkey laptop.private -out \ laptop.public Signature ok subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic \ Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl Getting Private keyThe 'request.pem' file can now be discarded.
Repeat this procedure for all hosts you need a key for. You can distribute the '.public' file with impunity, but keep the '.private' one private!
Once we have a public and a private key for our hosts we can tell racoon to use them.
We return to our previous configuration and the two hosts, 10.0.0.11 ('upstairs') and 10.0.0.216 ('laptop').
To the racoon.conf file on 10.0.0.11, we add:
path certificate "/usr/local/etc/racoon/certs"; remote 10.0.0.216 { exchange_mode aggressive,main; my_identifier asn1dn; peers_identifier asn1dn; certificate_type x509 "upstairs.public" "upstairs.private"; peers_certfile "laptop.public"; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; dh_group 2 ; } }This tells racoon that certificates are to be found in /usr/local/etc/racoon/certs/. Furthermore, it contains configuration items specific for remote 10.0.0.216.
The 'asn1dn' lines tell racoon that the identifier for both the local and remote ends are to be extracted from the public keys. This is the 'subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl' output from above.
The certificate_type line configures the local public and private key. The peers_certfile statement configures racoon to read the public key of the remote peer from the file laptop.public.
The proposal stanza is unchanged from what we've seen earlier, with the exception that the authentication_method is now rsasig, indicating the use of RSA public/private keys for authentication.
The addition to the configuration of 10.0.0.216 is nearly identical, except for the usual mirroring:
path certificate "/usr/local/etc/racoon/certs"; remote 10.0.0.11 { exchange_mode aggressive,main; my_identifier asn1dn; peers_identifier asn1dn; certificate_type x509 "laptop.public" "laptop.private"; peers_certfile "upstairs.public"; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; dh_group 2 ; } }
Now that we've added these statements to both hosts, we only need to move the key files in place. The 'upstairs' machine needs upstairs.private, upstairs.public, and laptop.public in /usr/local/etc/racoon/certs. Make sure that this directory is owned by root and has mode 0700 or racoon may refuse to read it!
The 'laptop' machine needs laptop.private, laptop.public, and upstairs.public in /usr/local/etc/racoon/certs. In other words, each host needs its own public and private key and additionally, the public key of the remote.
Verify that a Security Policy is in place (execute the 'spdadd' lines in Section 7.2.2>). Then launch racoon and everything should work.
To setup secure communications with a remote party, we must exchange public keys. While the public key does not need to be kept a secret, on the contrary, it is very important to be sure that it is in fact the unaltered key. In other words, you need to be certain there is no 'man in the middle'.
To make this easy, OpenSSL provides the 'digest' command:
$ openssl dgst upstairs.public MD5(upstairs.public)= 78a3bddafb4d681c1ca8ed4d23da4ff1
Now all we need to do is verify if our remote partner sees the same digest. This might be done by meeting in real life or perhaps over the phone, making sure the number of the remote party was not in fact sent over the same email containing the key!
Another way of doing this is the use of a Trusted Third Party which runs a Certificate Authority. This CA would then sign your key, which we've done ourselves above.