Updated for Debian 7 (wheezy) on 2014‑06‑23. The old texts for Debian 4.0 (etch) and Debian 3.1 (sarge) are still available.
This aims to be a simple how‐to for setting up IPsec in Debian.
So what’s wrong with other howtos about how to setup IPsec? Well, they usually don’t cover Debian specifically, but that’s not my chief problem. The main thing which makes other IPsec texts unsuitable for me is that they all assume I’m using IPsec to do a VPN. Well, I’m not, I’m using it to get IP security for otherwise completely insecure thing like NIS and NFS. And once you’ve got it running you can enable things like FTP and even telnet, and you can then run X over the network like it was meant to be run and not inside some ugly SSH tunnel.
Another thing which put me off other texts about IPsec was that they all used PSKs in their examples and then, maybe, covered X.509 certificates at the end, and only as a list of things to do differently. This irks me because I prefer to use OpenPGP keys, and don’t want to be forced to learn how to set up IPsec into a configuration I won’t be using in order to only then learn how to do what I really want to do.
Well, enough ranting.
Debian has contained many implementations of IPsec, and still does, but the prevailing one seems to be strongSwan.
Anyway, on to the installation.
Simply install the strongswan package.
The default strongswan-starter package is not configured to start up or shut down in the right sequence on system reboot or shutdown, so we need to edit some files and add some links. First, we patch the header in the init.d startup script:
# patch --backup --version-control=numbered --strip=0 <<EOF
--- /etc/init.d/ipsec.~1~ 2012-06-15 16:21:24.000000000 +0200
+++ /etc/init.d/ipsec 2014-06-22 17:34:58.000000000 +0200
@@ -1,9 +1,10 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: ipsec
-# Required-Start: \$network \$remote_fs
-# Required-Stop: \$network \$remote_fs
-# Default-Start: 2 3 4 5
+# Required-Start: \$network \$local_fs
+# Required-Stop: \$network \$local_fs
+# X-Start-Before: rpcbind mountnfs
+# Default-Start: S 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Strongswan IPsec services
### END INIT INFO
EOF
patching file /etc/init.d/ipsec
#
Then we remove and add some links:
# update-rc.d -f ipsec remove update-rc.d: using dependency based boot sequencing # update-rc.d -f ipsec start 41 S 2 3 4 5 . stop 91 1 . start 34 0 6 . update-rc.d: using dependency based boot sequencing #
Now we can safely start and stop IPsec. But it won’t do anything without configuration.
First, you need to create your OpenPGP public and private keys. Using plain gpg, this is a bit of work, but I have previously written a script to generate OpenPGP keys for Mandos, so I prefer to just use that. (You can download the script directly, or just install the mandos-client package.) Anyway, we first need to create our keys. We do this in the /etc/ipsec.d/private directory:
# mandos-keygen --dir /etc/ipsec.d/private Note: Due to entropy requirements, key generation could take anything from a few minutes to SEVERAL HOURS. Please be patient and/or supply the system with more entropy if needed. Started: Mon Jun 23 03:20:53 CEST 2014 .........+++++ ................+++++ ......+++++ ..........+++++ Finished: Mon Jun 23 03:23:25 CEST 2014 #
Then rename the key files and move them to their correct locations:
# cd /etc/ipsec.d/private # mv seckey.txt $(hostname)-key.asc # mv pubkey.txt ../certs/$(hostname).asc #
We need to make sure strongSwan knows about our private key, so edit /etc/ipsec.secrets and add one line:
# cat >> /etc/ipsec.secrets <<EOF
: RSA $(hostname)-key.asc
EOF
#
If you are using IPv4 addresses as well as IPv6, you need to create separate IPsec configurations for the IPv4 addresses, and also generate separate keys for those connections, otherwise it won’t work. (I’m guessing that strongSwan gets confused by multiple connections to the same host with the same key, but I really don’t know.)
# mandos-keygen --name $(hostname)-v4 --dir /etc/ipsec.d/private Note: Due to entropy requirements, key generation could take anything from a few minutes to SEVERAL HOURS. Please be patient and/or supply the system with more entropy if needed. Started: Mon Jun 23 03:26:27 CEST 2014 ..+++++ .....................................................+++++ ..+++++ ......+++++ Finished: Mon Jun 23 03:29:04 CEST 2014 # mv seckey.txt $(hostname)-v4-key.asc # mv pubkey.txt ../certs/$(hostname)-v4.asc
And add your IPv4 private key to /etc/ipsec.secrets:
# cat >> /etc/ipsec.secrets <<EOF
: RSA $(hostname)-v4-key.asc
EOF
#
Before we get IPsec configured and running, we need some preparations.
After an IPsec SA is
established to a specific IP address, an entry will automatically be
added to the IPsec SPD, which will allow
For these things, we need a firewall and the iptables package. (Historical note: It used to be that the IPsec Security Policy Database could be used as a de‐facto firewall, but strongSwan insists on managing and changing the SPD itself – most notably erasing it on exit – so this is currently not possible.) Here is a script I have written to set up a firewall based on what is in the /etc/ipsec.conf file created above:
#!/bin/sh ## Add exceptions to IPsec SPD # Accept IKE and IKEv2 for ipaddr in ::/0 0.0.0.0/0; do for port in 500 4500; do for dir in in out; do ip xfrm policy update src $ipaddr dst $ipaddr proto udp \ sport $port dport $port dir $dir ptype main done done done # Accept ICMPv6 neighbour-* for dir in in out; do for type in 135 136; do ip xfrm policy update src ::/0 dst ::/0 proto ipv6-icmp type \ $type code 0 dir $dir ptype main done done ## Add exceptions to firewall for chain in INPUT OUTPUT; do for iptables in iptables ip6tables; do $iptables --flush $chain # Accept encrypted packets $iptables --append $chain --protocol esp --jump ACCEPT # Accept IKE and IKEv2 for port in 500 4500; do $iptables --append $chain --proto udp \ --source-port $port --destination-port $port \ --jump ACCEPT done done if [ "$chain" = INPUT ]; then ip6tables --append INPUT --protocol udp --match frag \ --fragid 0 --fraglast --jump ACCEPT fi # Accept ICMPv6 neighbour-* ip6tables --append $chain --protocol icmpv6 --match icmp6 \ --icmpv6-type neighbour-solicitation --jump ACCEPT ip6tables --append $chain --protocol icmpv6 --match icmp6 \ --icmpv6-type neighbour-advertisement --jump ACCEPT done for iptables in iptables ip6tables; do if ! $iptables --new-chain reject_ipsec_hosts 2>/dev/null; then $iptables --flush reject_ipsec_hosts fi done for iptables in iptables ip6tables; do # Accept packets which will match an IPsec policy $iptables --append INPUT --match policy --dir in --pol ipsec \ --mode transport --jump ACCEPT # Reject packets from IPsec-only hosts $iptables --append INPUT --jump reject_ipsec_hosts # Accept packets which will be encrypted $iptables --append OUTPUT --match policy --dir out --pol ipsec \ --mode transport --jump ACCEPT # Reject packets for IPsec-only hosts $iptables --append OUTPUT --jump reject_ipsec_hosts done ipsec_transport(){ : "ipsec_transport 2001:470:1f15:1a45::4/128 88.80.26.40/32" my_ipv6="$1" my_ipv4="$2" peer_ip="$3" case "$peer_ip" in *:*) peer_ipv6="${peer_ip}/128" ip6tables --append reject_ipsec_hosts --source \ "${my_ipv6}"/128 --destination "${peer_ipv6}" --jump \ REJECT --reject-with icmp6-adm-prohibited ip6tables --append reject_ipsec_hosts --source \ "${peer_ipv6}" --destination "${my_ipv6}"/128 --jump \ REJECT --reject-with icmp6-adm-prohibited ;; *.*) peer_ipv4="${peer_ip}/32" iptables --append reject_ipsec_hosts --source \ "${my_ipv4}"/32 --destination "${peer_ipv4}" --jump \ REJECT --reject-with icmp-admin-prohibited iptables --append reject_ipsec_hosts --source \ "${peer_ipv4}" --destination "${my_ipv4}"/32 --jump \ REJECT --reject-with icmp-admin-prohibited ;; esac } my_ipv6=$(sed --quiet --expression='s/^[^#]*[[:space:]]left=\([^#]*:[^#]*\)#\?.*$/\1/p' /etc/ipsec.conf) export my_ipv6 my_ipv4=$(sed --quiet --expression='s/^[^#]*[[:space:]]left=\([^#]*\.[^#]*\)#\?.*$/\1/p' /etc/ipsec.conf) export my_ipv4 sed --quiet --expression='s/^[^#]*[[:space:]]right=\(.*[.:]\)/\1/p' \ /etc/ipsec.conf | while read peer_ip; do ipsec_transport "${my_ipv6}" "${my_ipv4}" "${peer_ip}" done
(It is a bit long, since it can accept IPv4 addresses as well.) I suggest that you save this script as /usr/local/sbin/firewall and run it as a pre-up command in /etc/network/interfaces, something like this:
auto eth0 iface eth0 inet6 static pre-up /usr/local/sbin/firewall || : address 2001:db8::2 netmask 64 gateway 2001:db8::1 dns-nameservers 2001:db8:1::4 2001:db8:1::5 dns-search example.org
Be sure to modify the pre-up setting to reflect the full name and location of the above firewall script, in case you renamed it and/or placed it somewhere else.
Now, the only actual configuration file, the /etc/ipsec.conf file. I’m assuming a host name of “host1” with IP address 2001:db8::2 and an IPsec connection to another host named “host2” with IP address 2001:db8::3
config setup charonstart=yes plutostart=no nocrsend=yes conn %default keyexchange=ikev2 type=transport auto=ignore left=2001:db8::2 mobike=no leftcert=host1.asc leftupdown=/usr/local/sbin/firewall conn to_host2 auto=start right=2001:db8::3 rightcert=host2.asc
Be sure to modify the conn %default/leftupdown setting to reflect the full name and location of the above firewall script, in case you renamed it and/or placed it somewhere else.
Now, repeat (and rename) that last conn to_* section for each additional host to configure for IPsec.
If using IPv4 addresses as well, you need some more lines. I’m assuming IPv4 addresses 192.0.2.2 and 192.0.2.3 for host1 and host2, respectively:
conn ipv4_default left=192.0.2.2 leftcert=host1-v4.asc conn to_host2_v4 also=ipv4_default auto=start right=192.0.2.3 rightcert=host2-v4.asc
Again, repeat (and rename) that last conn to_* section for each additional host to configure for IPsec.
Now you can start strongSwan by typing service ipsec start and, once you have configured the other host similarly and started it there as well, you should have IPsec running. You can test it by running the ipsec status command. The IPsec connection (or “Security Association”) should show as “ESTABLISHED”.
With this configuration, we will no longer accept any non‐IPsec packets from host2, and will also send only IPsec packets to that host. Now that’s what I call real network security.
To the extent possible under law,
Teddy Hogeborn
has waived all copyright and related or neighboring rights to
Debian IPsec Micro‐Howto.
This work is published from:
Sverige.