====== 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]]