====== IPSec ======
The following describes nwl's site IPSec setup. It's rather complex, as it has
to fulfil a number of requirements:
* be of the roadwarrior type (clients with changing IPs)
* provide an official IPv6 address for clients
* do not imply the need of a subnet behind the server or client to tunnel into
also there is a single limitation (for now), no IPv4 support (i.e. no support
for NAT and other PITAs).
===== Two Stage Setup Approach =====
The following sections describe a setup in two stages which is quite obscure
and not used anymore. It's documentation is left mainly for reference.
==== Server Setup ====
This is the //raccon.conf// for the server:
path certificate "/etc/ssl/ipsec";
remote anonymous {
exchange_mode main;
generate_policy on;
certificate_type x509 "certs/orbit.nwl.cc.crt" "private/orbit.nwl.cc.key";
verify_cert on;
my_identifier asn1dn;
peers_identifier asn1dn;
passive on;
proposal {
encryption_algorithm aes;
hash_algorithm md5;
authentication_method rsasig;
dh_group modp1024;
}
}
sainfo anonymous {
pfs_group modp768;
encryption_algorithm aes;
authentication_algorithm hmac_md5;
compression_algorithm deflate;
}
nothing else is necessary, as ''generate_policy on'' will generate the
necessary policies after completing phase 1.
==== Client Setup ====
Client side setup is obviously the more complex one. What makes it especially
difficult is the fact, that the source address is potentially unknown **and**
tunnel mode has to be used.
To prevent having to manually specifying a policy for all potential source
addresses, a dummy policy is being used which just triggers some transport mode
connection, and the phase1_up script does then set the real policies for later
use with the information in it's environment (specifically the current source
IP, which must be reachable by the server).
#!/usr/sbin/setkey -f
spdadd ::/0 2001:41d0:1:ea5f::1 any -P out ipsec
esp/transport//require
ah/transport//require;
spdadd 2001:41d0:1:ea5f::1 ::/0 any -P in ipsec
esp/transport//require
ah/transport//require;
The following //racoon.conf// is being used. Important fact here is that the
single ''remote'' definition is used for both IPSec sessions.
path certificate "/etc/racoon/nuty";
path script "/etc/racoon";
remote 2001:41d0:1:ea5f::1 {
exchange_mode main;
certificate_type x509 "nuty.nwl.cc.crt" "nuty.nwl.cc.key";
verify_cert on;
my_identifier asn1dn;
peers_identifier asn1dn;
script "phase1.sh" phase1_up;
script "phase1.sh" phase1_down;
proposal {
encryption_algorithm aes;
hash_algorithm md5;
authentication_method rsasig;
dh_group modp1024;
}
}
sainfo anonymous {
pfs_group modp768;
encryption_algorithm aes;
authentication_algorithm hmac_md5;
compression_algorithm deflate;
}
The following script does the magic: it creates the tunnel policies and
assigns the public IP to the interface with the default route. The tunnel IPs
are still hardcoded, maybe they could be passed as parameters from within
//racoon.conf//.
Note here that the remote tunnel IP is the same as the one of the remote
endpoint. So on the server side this setup behaves just like a transport mode
connection, but for a previously non-existent ip (which must be reachable, of
course).
#!/bin/bash
TUNLOC_IP="2001:41d0:1:ea5f::40"
TUNREM_IP="2001:41d0:1:ea5f::1"
TUNPFX="64"
OPT="-6"
[[ "${LOCAL_ADDR}" = *.*.*.* ]] && OPT="-4"
GW_IFACE="`ip ${OPT} route show | awk '/^default/{print $5}'`"
case $1 in
phase1_up)
logger -t "phase1.sh" "setting up"
/usr/sbin/setkey -c << EOF
spdadd ${TUNLOC_IP} ${TUNREM_IP} any -P out ipsec
esp/tunnel/${LOCAL_ADDR}-${REMOTE_ADDR}/require
ah/tunnel/${LOCAL_ADDR}-${REMOTE_ADDR}/require;
spdadd ${TUNREM_IP} ${TUNLOC_IP} any -P in ipsec
esp/tunnel/${REMOTE_ADDR}-${LOCAL_ADDR}/require
ah/tunnel/${REMOTE_ADDR}-${LOCAL_ADDR}/require;
EOF
/sbin/ip addr add ${TUNLOC_IP}/${TUNPFX} dev ${GW_IFACE}
;;
phase1_down)
logger -t "phase1.sh" "shutting down"
/sbin/ip addr del ${TUNLOC_IP}/${TUNPFX} dev ${GW_IFACE}
/usr/sbin/setkey -c << EOF
spddelete ${TUNLOC_IP} ${TUNREM_IP} any -P out;
spddelete ${TUNREM_IP} ${TUNLOC_IP} any -P in;
EOF
;;
esac
exit 0
==== Bugs ====
When using ''racoon'' in an IPv6 environment, IP address passing to phase1
scripts is broken. The following patch fixes this (see
[[https://trac.ipsec-tools.net/ticket/300|Bug #300]]):
Index: src/racoon/isakmp.c
===================================================================
RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp.c,v
retrieving revision 1.49
diff -r1.49 isakmp.c
3126d3125
< struct sockaddr_in *sin;
3139,3141c3138,3140
< sin = (struct sockaddr_in *)iph1->local;
< inet_ntop(sin->sin_family, &sin->sin_addr, addrstr, IP_MAX);
< snprintf(portstr, PORT_MAX, "%d", ntohs(sin->sin_port));
---
> getnameinfo(iph1->local, sizeof(struct sockaddr_storage),
> addrstr, IP_MAX, portstr, PORT_MAX,
> NI_NUMERICHOST | NI_NUMERICSERV);
3155,3157c3154,3156
< sin = (struct sockaddr_in *)iph1->remote;
< inet_ntop(sin->sin_family, &sin->sin_addr, addrstr, IP_MAX);
< snprintf(portstr, PORT_MAX, "%d", ntohs(sin->sin_port));
---
> getnameinfo(iph1->remote, sizeof(struct sockaddr_storage),
> addrstr, IP_MAX, portstr, PORT_MAX,
> NI_NUMERICHOST | NI_NUMERICSERV);
===== Site IPsec, Second Approach =====
... to be continued ...
===== Links =====
* [[http://www.ipsec-howto.org/|Ralf Spenneberg's IPSec Howto]]