HOWTO IPSEC
From Gentoo Linux Wiki
| Installation • Kernel & Hardware • Networks • Portage • Software • System • X Server • Gaming • Non-x86 • Emulators • Misc |
Document Status: DRAFT
Contents |
[edit] Preface
[edit] Motivation
IPSec was developed for IPv6. Its intention is to secure network communications at the IP layer, instead of at the presentation or application layer. The lower in the OSI model you secure your communications, the more transparent that security becomes. If security is not transparent to the user, there is a chance the user may choose not to use it. By using a lower layer security protocol to make encryption and authenticaiton transparent to the user, we can more easily guarantee that the security measures will be utilized by the user.
Aside from encryption, IPSec can also guarantee the identity of the computer you are communicating with. This can prevent man-in-the-middle attacks, IP spoofing attacks, ARP poisoining attacks, etc. If used widely across the entire Internet, it could even prevent fraudulent Internet transanctions, spoofed websites used in Phishing, etc. This level of deployment, however, would require a concertated effort by the entire Internet community. As IPv6 becomes more widely deployed, this may eventually become a reality.
This HOWTO intends to make it easy to setup IPSec secured connections using your Gentoo box. Good luck!
[edit] Prerequisites
[edit] Kernel Configuration
Compile a 2.6.x kernel with the following options enabled:
| Linux Kernel Configuration: for IPSec |
Networking --->
[*] Networking support
Networking options --->
<M> IPsec user configuration interface
<M> PF_KEY sockets
<M> IP: AH transformation
<M> IP: ESP transformation
<M> IP: IPComp transformation
|
Note: In later kernels IPsec user configuration interface was renamed to Transformation user configuration interface
You also MUST activate encryption and hash algorithms within the Crypto section of the kernel. Enabling them as modules is fine though.
[edit] Packages to install
emerge -v ipsec-tools emerge -v iptables emerge -v iproute2
Please note, do not start the provided init script yet.
[edit] The Manual Way
[edit] Prepare Your Firewall
You must be able to send/receive packets from certain UDP ports (and other protocols?).
What we need
- UDP port 500 -- the ISAKMP (internet security association key management protocol)
- UDP port 4500 -- in case you want to use NAT-T (NAT-Traversal)
- ESP protocol (50) -- (Encapsulated Security Payload)
- AH protocol (51) -- (Authentification Header)
using iptables
You must accept all traffic regarding the ports/protocols mentioned above:
iptables -A INPUT -p udp --dport 500 -m state --state NEW -j ACCEPT iptables -A OUTPUT -p udp --dport 500 -m state --state NEW -j ACCEPT iptables -A INPUT -p esp -j ACCEPT iptables -A OUTPUT -p esp -j ACCEPT iptables -A INPUT -p ah -j ACCEPT iptables -A OUTPUT -p ah -j ACCEPT
[edit] Statically Securing Host-to-Host Communication
This is usually the easiest way to configure IPsec for two hosts.
[edit] Host Network Configuration
Here I'm using faked IP addresses and subnet. You may guess why ;)
- Host A as follows:
- IP/net: 111.222.333.444/24
- Host B as follows:
- IP/net: 555.666.777.888/24
[edit] Configuring Host A (111.222.333.444)
| File: /etc/conf.d/racoon |
RACOON_OPTS="-4 -l /var/log/racoon.log" RACOON_CONF="/etc/racoon/racoon.conf" RACOON_PSK_FILE="/etc/racoon/psk.txt" SETKEY_CONF="/etc/ipsec.conf" RACOON_RESET_TABLES="true" |
| File: /etc/ipsec.conf |
#!/usr/sbin/setkey -f
# Flush the SAD and SPD
flush;
spdflush;
# Attention: Use these keys for testing purposes only!
# Generate your own keys!
# AH SAs using 128 bit long keys
add 111.222.333.444 555.666.777.888 ah 0x200 -A hmac-md5
0x88dfd37ce0d4b0641f3c14fa9197301c;
add 555.666.777.888 111.222.333.444 ah 0x300 -A hmac-md5
0x91bc25a6e4c1e8e592bd9d2cbd09ff0b;
# ESP SAs using 192 bit long keys
add 111.222.333.444 555.666.777.888 esp 0x201 -E rijndael-cbc
0x61272157401bf304177fa8ac0c38de4095992d06c0499cf7;
add 555.666.777.888 111.222.333.444 esp 0x301 -E rijndael-cbc
0x49fce5b82ff7acc4d6aded691a0f5f9a65e18861ad4b66bf;
spdadd 111.222.333.444 555.666.777.888 any -P out ipsec
esp/transport//require
ah/transport//require;
spdadd 555.666.777.888 111.222.333.444 any -P in ipsec
esp/transport//require
ah/transport//require;
|
[edit] Configuring Host B (555.666.777.888)
For here, the configuration looks quite the same.
| File: /etc/conf.d/racoon |
RACOON_OPTS="-4 -l /var/log/racoon.log" RACOON_CONF="/etc/racoon/racoon.conf" RACOON_PSK_FILE="/etc/racoon/psk.txt" SETKEY_CONF="/etc/ipsec.conf" RACOON_RESET_TABLES="true" |
However, please note, that the only thing within the configuration files that differ from host A and B is the in/out order of the spdadd lines.
| File: /etc/ipsec.conf |
#!/usr/sbin/setkey -f
# Flush the SAD and SPD
flush;
spdflush;
# Attention: Use these keys for testing purposes only!
# Generate your own keys!
# AH SAs using 128 bit long keys
add 111.222.333.444 555.666.777.888 ah 0x200 -A hmac-md5
0x88dfd37ce0d4b0641f3c14fa9197301c;
add 555.666.777.888 111.222.333.444 ah 0x300 -A hmac-md5
0x91bc25a6e4c1e8e592bd9d2cbd09ff0b;
# ESP SAs using 192 bit long keys
add 111.222.333.444 555.666.777.888 esp 0x201 -E rijndael-cbc
0x61272157401bf304177fa8ac0c38de4095992d06c0499cf7;
add 555.666.777.888 111.222.333.444 esp 0x301 -E rijndael-cbc
0x49fce5b82ff7acc4d6aded691a0f5f9a65e18861ad4b66bf;
spdadd 111.222.333.444 555.666.777.888 any -P in ipsec
esp/transport//require
ah/transport//require;
spdadd 555.666.777.888 111.222.333.444 any -P out ipsec
esp/transport//require
ah/transport//require;
|
[edit] Loading the Configuration
On both hosts, load the configuration by starting the ipsec-tools racoon init script like below:
/etc/init.d/racoon start
[edit] Testing
Host-a will ping host-b:
| Code: ping -c4 host-b |
PING host-b (555.666.777.888) 56(84) bytes of data. 64 bytes from host-b (555.666.777.888): icmp_seq=1 ttl=59 time=54.5 ms 64 bytes from host-b (555.666.777.888): icmp_seq=2 ttl=59 time=55.1 ms 64 bytes from host-b (555.666.777.888): icmp_seq=3 ttl=59 time=54.8 ms 64 bytes from host-b (555.666.777.888): icmp_seq=4 ttl=59 time=55.1 ms --- host-b ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3002ms rtt min/avg/max/mdev = 54.548/54.919/55.130/0.232 ms |
While doing some traffic from host-A to host-B we can (on host A) sniff the traffic using tcpdump (or alike). You should see the following output (from tcpdump):
| Code: tcpdump |
[...] 19:30:16.661723 IP host-A > host-B: AH(spi=0x069623f6,seq=0x4a): ESP(spi=0x0b691cf7,seq=0x4a) 19:30:16.716527 IP host-B > host-A: AH(spi=0x05137270,seq=0x48): ESP(spi=0x0dd7604e,seq=0x48) 19:30:17.662021 IP host-A > host-B: AH(spi=0x069623f6,seq=0x4b): ESP(spi=0x0b691cf7,seq=0x4b) 19:30:17.717120 IP host-B > host-A: AH(spi=0x05137270,seq=0x49): ESP(spi=0x0dd7604e,seq=0x49) [...] |
When you though see lots of AH and ESP traffic, then you have succeeded. Have a look at tcpdump when sniffing for plaintext ICMP ping requests/responses to compare.
So, when you're done with this, not only is the ping traffic secured, all traffic is secured.
[edit] Creating your own random keys
You can easily create your own random keys for manual keying:
$ # 128 bit keys $ dd if=/dev/random count=16 bs=1| xxd -ps - 16+0 records in 16+0 records out 66cae55a472213e942da2275af5896d3 $ # 192 bit keys $ dd if=/dev/random count=24 bs=1| xxd -ps - 24+0 records in 24+0 records out bd94fe3cadd714e07a8ea8c4dc4ce1282c1b6a6ae79979cd
xxd is part of the vim-core package. An emerge vim-core will allow you to use it. Now, you can edit the file: /etc/racoon/psk.txt:
111.222.333.444 shared_key 555.666.777.888 shared_key
NOTE: The two shared keys have the same value.
[edit] IPsec tunnels
FIXME
[edit] Algorithms presentation
Include a presentation/discussion of the available algorithms so people can choose wisely between them.
[edit] Automated IPSec Tunnels / Transports / Firewalling
- Section Author: Eliot Gable <e gable AT@AT gmail .DOT. com>
- Date: 4/22/2006
[edit] Introduction
Creating IPSec tunnels and transport connections between a single host by hand takes fairly little time and effort -- especially if you use pre-shared keys. However, if you need to configure multiple tunnels between multiple hosts, manual configuration of IPSec tunnels and transport connections becomes extremely tedious. Things get worse when you are trying to make a connection to your home network from on the road. In this case, you probably won't know in advance what IP address you will be connecting from.
To combat these issues, I will present a more automated way of configuring IPSec tunnels and transport connections. I will also present how to configure Windows XP with Service Pack 2 to connect to your Gentoo system using IPSec.
For this new method of IPSec, we will use X.509 digital certificates for authentication.
[edit] Creating a Certificate Authority
If you do not already have OpenSSL installed, you will need to install it now:
emerge openssl
After OpenSSL is fully installed, we need to create a folder for storing our certificates. I use /etc/certs:
bash ~ # mkdir /etc/certs && chmod 700 /etc/certs && cd /etc/certs
Once inside the folder, we need to create a Certificate Authority. But, before we do so, we need to ensure we generate the CA certificate with the correct parameters. Edit /etc/ssl/openssl.cnf to ensure the following settings:
bash certs # vim /etc/ssl/openssl.cnf
| File: /etc/ssl/openssl.cnf |
[ CA_default ] ...<snip>... x509_extensions = v3_ca # The extentions to add to the cert ...<snip>... [ req ] ...<snip>... x509_extensions = v3_req # The extentions to add to the self signed cert ...<big snip>... [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ v3_ca ] ...<snip>... basicConstraints = CA:true ...<snip>... keyUsage = cRLSign, keyCertSign |
These settings basically tell OpenSSL to generate the CA certificate as a CA (basicConstraints=CA:true) and that the certificate is used for signing. They also tell OpenSSL to generate certificate requests as a non-CA certificate (basicConstraints=CA:FALSE), and to set the flags on the requested certificates for nonRepudiation, digitalSignature, and keyEncipherment. All of these settings are required for the IPSec tunnel to establish.
OpenSSL provides a script to generate a new Certificate Authority. From inside /etc/certs, issue the following command to create the CA:
bash certs # /etc/ssl/misc/CA.sh -newca
After you have created your Certificate Authority, you need to issue a certificate for your Gentoo box. To issue and manage certificates, we will use three scripts. Place these inside /etc/certs (or wherever you chose to store your certificates):
| File: /etc/certs/issue |
#!/bin/bash
#
# Author: Eliot Gable <e gable AT@AT gmail .DOT. com>
# Copyright (c) 4/22/2006
# Distributed under the terms of the GNU General Public License v2
NAME=$1
/etc/ssl/misc/CA.sh -newreq
/etc/ssl/misc/CA.sh -sign
mv newcert.pem ${NAME}_cert.pem
rm newreq.pem
mv newkey.pem ${NAME}_key.pem
openssl rsa -in ${NAME}_key.pem -out ${NAME}_key.pem
chmod 600 ${NAME}*.pem
|
| File: /etc/certs/revoke |
#!/bin/bash # # Author: Eliot Gable <e gable AT@AT gmail .DOT. com> # Copyright (c) 4/22/2006 # Distributed under the terms of the GNU General Public License v2 openssl ca -revoke $1 |
| File: /etc/certs/create_pfx |
#!/bin/bash
#
# Author: Eliot Gable <e gable AT@AT gmail .DOT. com>
# Copyright (c) 4/22/2006
# Distributed under the terms of the GNU General Public License v2
openssl pkcs12 -export -in ${1}_cert.pem -inkey ${1}_key.pem -out ${1}.pfx -name "IPSEC Cert for Home"
chmod 600 ${1}.pfx
|
Set these three scripts so they are executable:
bash certs # chmod 700 issue bash certs # chmod 700 revoke bash certs # chmod 700 create_pfx
Now, before you start issuing certificates, we need to edit /etc/ssl/openssl.cnf again. Specifically, you should modify these lines accordingly:
| File: /etc/ssl/openssl.cnf |
[ CA_default ] ...<snip>... x509_extensions = v3_req # The extentions to add to the cert ...<snip>... [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = US countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = MyState localityName = Locality Name (eg, city) localityName_default = MyCity 0.organizationName = Organization Name (eg, company) 0.organizationName_default = MyCompany # we can do this but it is not needed normally :-) #1.organizationName = Second Organization Name (eg, company) #1.organizationName_default = World Wide Web Pty Ltd organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = MyUnitName |
It is imperative that you change the x509_extensions line in the CA_default section back to v3_req before you issue certificates for your Gentoo box or for your client devices, otherwise they will be issued with the signing keyUsage settings used on the CA certificate. After you have set your defaults appropriately, it is time to issue your first certificate:
bash certs # ./issue myhost.mydomain.com
You will need to enter a password for the new certificate when prompted. Then, fill out the rest of the information as requested. For the common name, you can either enter something descriptive (like "VPN Cert"), or you can enter the host + domain name for the machine, like you would for a webserver certificate. After entering all of the requested information, you will have a chance to sign the certificate with your CA, where you will be prompted for your Certificate Authority password which you chose when setting up your CA.
After successfully signing the new certificate, you will be prompted for your new certificate's password. This step is required in order to generate a non-password protected key file. Racoon (the daemon that does the IPSec stuff) does not support password encrypted key files. When this process is complete, you will see two new files in /etc/certs: myhost.mydomain.com_cert.pem and myhost.mydomain.com_key.pem. These are your certificate and certificate key files, respectively.
After completing your first certificate, you will need to generate another one for your client machine. Go ahead and do that now, using the same 'issue' command and a different name for the client certificate. If your client machine will be a Windows machine, you will need to create a PFX file for importing the certificate and key into Windows. You can do that like so:
bash certs # ./create_pfx myclient.mydomain.com
It will prompt you for an export password which you will need in order to import the certificate and key into Windows. Make sure you do not forget this password, or you will not be able to import the certificate and key into Windows.
Do not do anything else with the client certificate yet (do not copy it to your Windows machine or anywhere else -- just leave it sit right there). We will cover the client setup later, including how to securely copy the certificate to your Windows machine.
Finally, we need to create a link to the CA certificate that Racoon can use to validate the client certificates:
bash certs # ln -s MyCA/cacert.pem `openssl x509 -noout -hash < MyCA/cacert.pem`.0
If you maintain a certificate revocation list, you need to do this for the CRL, too:
bash certs # ln -s MyCA/cacrl.pem `openssl x509 -noout -hash < MyCA/cacrl.pem`.r0
[edit] Init Script and Config File
To automate the setup of IPSec tunnels, I have created an easy-to-use configuration file (/etc/conf.d/ipsec) and a corresponding init script which does all the heavy lifting. You will need to create these files on your Gentoo system since Gentoo does not come with them by default:
| File: /etc/conf.d/ipsec |
# IPSec/ISAKMP Configuration File
#
# Author: Eliot Gable <e gable AT@AT gmail .DOT. com>
# Copyright (c) 4/22/2006
# Distributed under the terms of the GNU General Public License v2
debug_ipsec="off"
certificate_path="/etc/certs"
psk_path="/etc/racoon/psk.txt"
# If the 'listen' variable is configured, the array of values
# are dumped directly into the 'listen { }' section of
# racoon.conf as entered here. To find out what you can specify
# and the format required, man racoon.conf.
listen=(
"isakmp 111.111.111.111 [500]"
"isakmp_natt 111.111.111.111 [4500]"
"isakmp 192.168.0.1 [500]"
"isakmp_natt 192.168.0.1 [4500]"
)
# For any IPSec connection, you can specify:
# ul_proto <any/ip6/ip4/Upper layer protocol to apply IPSec to>
# protocol <ah/esp/ipcomp> level <use/require>
# encryption_algorithm <rijndael/3des/etc>
# hash_algorithm <md5/sha1/sha256/sha384/sha512/etc>
# compression_algorithm <none/deflate>
# authentication_algorithm <hmac_sha1/hmac_md5/etc>
# authentication <psk/X.509>
# If authentication==psk:
# psk <your pre-shared key> ** NOTE: pre-shared key support is not yet completed
# If authentication==X.509:
# certificate <certificate name relative to certificate_path>
# certificate_key <cert key relative to certificate_path>
# For details on which algorithms and key lengths can be used, man setkey
# Here, we define a tunnel to a work location
# For tunnels, we can specify:
# src_net - Source network block/IP
# dst_net - Destination network block/IP
# src_port - Source port
# dst_port - Destination port
# src_gw_ip - Source gateway IP
# dst_gw_ip - Destination gateway IP
tunnel_hometowork=(
"src_net 192.168.0.0/24"
"dst_net 192.168.1.0/24"
"src_gw_ip 111.111.111.111"
"dst_gw_ip 222.222.222.222"
"ul_proto any"
"protocol esp level require"
"encryption_algorithm aes"
"compression_algorithm deflate"
"hash_algorithm md5"
"authentication X.509"
"certificate myhost.mydomain.com_cert.pem"
"certificate_key myhost.mydomain.com_key.pem"
)
iptables_hometowork=(
"INPUT -s 192.168.1.0/24 -j ACCEPT"
"OUTPUT -d 192.168.1.0/24 -j ACCEPT"
"FORWARD -s 192.168.1.0/24 -j ACCEPT"
"FORWARD -d 192.168.1.0/24 -j ACCEPT"
"INPUT -s 222.222.222.222 -j ACCEPT"
"OUTPUT -d 222.222.222.222 -j ACCEPT"
)
transport_work2=(
"src_ip 111.111.111.111"
"dst_ip 333.333.333.333"
"ul_proto any"
"protocol esp level require"
"protocol ah level require"
"encryption_algorithm aes"
"hash_algorithm sha1"
"authentication X.509"
"compression_algorithm deflate"
"certificate myhost.mydomain.com.pem"
"certificate_key myhost.mydomain.com.pem"
)
iptables_work2=(
"INPUT -s 333.333.333.333 -j ACCEPT"
"OUTPUT -d 333.333.333.333 -j ACCEPT"
)
# This enables connections while traveling on the road when you do not know your
# IP address information.
roadwarrior=(
"status enable"
"authentication X.509"
"certificate myhost.mydomain.com_cert.pem"
"certificate_key myhost.mydomain.com_key.pem"
"encryption_algorithm 3des"
"hash_algorithm sha1"
"authentication_algorithm hmac_sha1"
"compression_algorithm deflate"
)
|
After you have created your configuration file, you will need to create the init script (which should not be modified unless you really know what you are doing):
| File: /etc/init.d/ipsec |
#!/sbin/runscript
#
# Author: Eliot Gable <e gable AT@AT gmail .DOT. com>
# Copyright (c) 4/22/2006
# Update: 5/2/2006
# Fixed 2 bugs that crop up on newer version of setkey
# Distributed under the terms of the GNU General Public License v2
depend() {
need net
}
start() {
create_policies || return 1
create_firewall_rules || return 1
create_racoon_conf || return 1
}
stop() {
if [ -x /var/lib/ipsec/remove_firewall ]; then
/var/lib/ipsec/remove_firewall
fi
if [ -x /var/lib/ipsec/remove_routes ]; then
/var/lib/ipsec/remove_routes
fi
# This is a slightly overblown way of killing racoon if it is running
if [ -e /service/racoon ]; then
ebegin "Bringing down racoon using daemontools"
svc -d /service/racoon &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
# At the moment, we are going to trust that daemontools really killed racoon.
# We really should check up on it, though, like we do below.
else
if [ -x /etc/init.d/racoon ] && [ -e /var/lib/init.d/started/racoon ]; then
/etc/init.d/racoon stop
else
if [ -r /var/run/racoon.pid ] && [ "$(ps ax | grep racoon | grep -v grep)" ]; then
PID=$(cat /var/run/racoon.pid)
ebegin "Terminating racoon PID ${PID}"
kill -SIGTERM ${PID} &>/dev/null
LOOP1=1
while [ "$(ps ax | grep ${PID} | grep -v grep)" ] && (( $LOOP1 < 3 )); do
LOOP2=1
while [ "$(ps ax | grep ${PID} | grep -v grep)" ] && (( $LOOP2 < 5 )); do
printf "."
sleep 1
LOOP2=$((LOOP+1))
done
if [ "$(ps ax | grep ${PID} | grep -v grep)" ]; then
kill -SIGKILL ${PID} &>/dev/null
printf "K"
fi
done
if [ "$(ps ax | grep ${PID} | grep -v grep)" ]; then
ewend 1 "Could not kill the racoon! Something is wrong."
return 1
else
ewend 0 ""
fi
else
einfo "Racoon PID file not found."
if [ "$(ps ax | grep racoon | grep -v grep)" ]; then
ebegin "Terminating racoon's life"
killall -SIGTERM racoon
LOOP1=1
while [ "$(ps ax | grep racoon | grep -v grep)" ] && (( $LOOP1 < 3 )); do
LOOP2=1
while [ "$(ps ax | grep racoon | grep -v grep)" ] && (( $LOOP2 < 5 )); do
printf "."
sleep 1
LOOP2=$((LOOP+1))
done
if [ "$(ps ax | grep racoon | grep -v grep)" ]; then
killall -SIGKILL racoon
printf "K"
fi
done
if [ "$(ps ax | grep racoon | grep -v grep)" ]; then
ewend 1 "Could not kill the racoon! Something is wrong."
return 1
else
ewend 0 ""
fi
else
einfo "Racoon not running (maybe it's sleeping)."
fi
fi
rm -f /var/run/racoon.pid
fi
fi
# The racoon should now be thuroughly dead
# Flush the SAD and SPD
ebegin "Flushing IPSec policies"
setkey -P -F &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
rm -f /var/lib/ipsec/remove_routes
}
restart() {
svc_stop
svc_start
}
create_policies() {
# First, clear out any old policies
ebegin "Flushing old policies"
setkey -P -F &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
# Start a new script for removing any routes we add
mkdir -p /var/lib/ipsec
printf "#!/bin/bash\n\nsource /sbin/functions.sh\n\n" > /var/lib/ipsec/remove_routes
chmod 750 /var/lib/ipsec/remove_routes
# Loop through the IPSec tunnels/transports and create appropriate policies
for tun in ${!tunnel*}; do
unset src_net dst_net src_gw_ip dst_gw_ip src_ip dst_ip src_port dst_port ul_proto esp_level ah_level ipcomp_level
unset esp_proto_sd esp_proto_ds ah_proto_sd ah_proto_ds ipcomp_proto_sd ipcomp_proto_ds
unset policy1 policy2 policy3 policy4 policy5 policy6 policy7 policy8
TUN="tunnel=(\"\${${tun}[@]}\")"
eval $TUN
# Extract all of the options for the tunnel
for i in ${!tunnel[*]}; do
if [[ "src_net" == ${tunnel[${i}]:0:7} ]]; then
local src_net=${tunnel[${i}]##src_net }
fi
if [[ "dst_net" == ${tunnel[${i}]:0:7} ]]; then
local dst_net=${tunnel[${i}]##dst_net }
fi
if [[ "src_port" == ${tunnel[${i}]:0:8} ]]; then
local src_port="[${tunnel[${i}]##src_port }]"
fi
if [[ "dst_port" == ${tunnel[${i}]:0:8} ]]; then
local dst_port="[${tunnel[${i}]##dst_port }]"
fi
if [[ "src_gw_ip" == ${tunnel[${i}]:0:9} ]]; then
local src_gw_ip=${tunnel[${i}]##src_gw_ip }
fi
if [[ "dst_gw_ip" == ${tunnel[${i}]:0:9} ]]; then
local dst_gw_ip=${tunnel[${i}]##dst_gw_ip }
fi
if [[ "ul_proto" == ${tunnel[${i}]:0:8} ]]; then
local ul_proto=${tunnel[${i}]##ul_proto }
fi
if [[ "protocol esp level" == ${tunnel[${i}]:0:18} ]]; then
local esp_level=${tunnel[${i}]##protocol esp level }
fi
if [[ "protocol ah level" == ${tunnel[${i}]:0:17} ]]; then
local ah_level=${tunnel[${i}]##protocol ah level }
fi
if [[ "protocol ipcomp level" == ${tunnel[${i}]:0:21} ]]; then
local ipcomp_level=${tunnel[${i}]##protocol ipcomp level }
fi
done
# Decide whether to include ah/esp/ipcomp
if [[ "$esp_level" ]]; then
local esp_proto_sd=$(printf "\n\tesp/tunnel/${src_gw_ip}-${dst_gw_ip}/${esp_level}")
local esp_proto_ds=$(printf "\n\tesp/tunnel/${dst_gw_ip}-${src_gw_ip}/${esp_level}")
fi
if [[ "${ah_level}" ]]; then
local ah_proto_sd=$(printf "\n\tah/tunnel/${src_gw_ip}-${dst_gw_ip}/${ah_level}")
local ah_proto_ds=$(printf "\n\tah/tunnel/${dst_gw_ip}-${src_gw_ip}/${ah_level}")
fi
if [[ "${ipcomp_level}" ]]; then
local ipcomp_proto_sd=$(printf "\n\tipcomp/tunnel/${src_gw_ip}-${dst_gw_ip}/${ipcomp_level}")
local ipcomp_proto_ds=$(printf "\n\tipcomp/tunnel/${dst_gw_ip}-${src_gw_ip}/${ipcomp_level}")
fi
# Build our 8 policies for fully encrypted communications
local policy1=$(printf "spdadd ${src_net}${src_port} ${dst_net}${dst_port} ${ul_proto} -P out ipsec ${esp_proto_sd} ${ah_proto_sd} ${ipcomp_proto_sd} ;")
local policy2=$(printf "\nspdadd ${src_net}${src_port} ${dst_gw_ip}${dst_port} ${ul_proto} -P out ipsec ${esp_proto_sd} ${ah_proto_sd} ${ipcomp_proto_sd} ;")
local policy3=$(printf "\nspdadd ${src_gw_ip} ${dst_gw_ip} ${ul_proto} -P out ipsec ${esp_proto_sd} ${ah_proto_sd} ${ipcomp_proto_sd} ;")
local policy4=$(printf "\nspdadd ${src_gw_ip}${src_port} ${dst_net}${dst_port} ${ul_proto} -P out ipsec ${esp_proto_sd} ${ah_proto_sd} ${ipcomp_proto_sd} ;")
local policy5=$(printf "\nspdadd ${dst_net}${dst_port} ${src_net}${src_port} ${ul_proto} -P in ipsec ${esp_proto_ds} ${ah_proto_ds} ${ipcomp_proto_ds} ;")
local policy6=$(printf "\nspdadd ${dst_net}${dst_port} ${src_gw_ip}${src_port} ${ul_proto} -P in ipsec ${esp_proto_ds} ${ah_proto_ds} ${ipcomp_proto_ds} ;")
local policy7=$(printf "\nspdadd ${dst_gw_ip} ${src_gw_ip} ${ul_proto} -P in ipsec ${esp_proto_ds} ${ah_proto_ds} ${ipcomp_proto_ds} ;")
local policy8=$(printf "\nspdadd ${dst_gw_ip}${dst_port} ${src_net}${src_port} ${ul_proto} -P in ipsec ${esp_proto_ds} ${ah_proto_ds} ${ipcomp_proto_ds} ;")
# Now we are ready to insert policies
printf "${policy1} ${policy2} ${policy3} ${policy4} ${policy5} ${policy6} ${policy7} ${policy8}\n" > /tmp/polfile
ebegin "Checking generated policy"
setkey -n -f /tmp/polfile &>/tmp/error
RET=$?
ERR=$(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
if [[ "$ERR" ]]; then
ewend 1 $ERR
cat /tmp/polfile && rm -f /tmp/polfile
return 1
else
ewend 0
fi
ebegin "Instating policy for ${tun}"
setkey -f /tmp/polfile &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
if [[ "${debug_ipsec}" == "on" ]]; then
einfo "The following policy was generated for ${tun}:"
cat /tmp/polfile
fi
rm -f /tmp/polfile &>/dev/null
ebegin "Routing traffic for ${dst_net} to ${src_gw_ip}"
ip route add ${dst_net} via ${src_gw_ip} &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
# Make an entry in the remove_routes script to remove this route we just added
printf "ebegin \"Removing route for ${dst_net} via ${src_gw_ip}\"\n" >> /var/lib/ipsec/remove_routes
printf "ip route del ${dst_net} via ${src_gw_ip} &>/tmp/error\n" >> /var/lib/ipsec/remove_routes
printf "ewend \$? \$(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)\n" >> /var/lib/ipsec/remove_routes
done
for tran in ${!transport*}; do
unset src_net dst_net src_gw_ip dst_gw_ip src_ip dst_ip src_port dst_port ul_proto esp_level ah_level ipcomp_level
unset esp_proto_sd esp_proto_ds ah_proto_sd ah_proto_ds ipcomp_proto_sd ipcomp_proto_ds
unset policy1 policy2 policy3 policy4 policy5 policy6 policy7 policy8
TRAN="transport=(\"\${${tran}[@]}\")"
eval $TRAN
# Extract all of the options for the tunnel
for i in ${!transport[*]}; do
if [[ "src_ip" == ${transport[${i}]:0:6} ]]; then
local src_ip=${transport[${i}]##src_ip }
fi
if [[ "dst_ip" == ${transport[${i}]:0:6} ]]; then
local dst_ip=${transport[${i}]##dst_ip }
fi
if [[ "src_port" == ${transport[${i}]:0:8} ]]; then
local src_port="[${transport[${i}]##src_port }]"
fi
if [[ "dst_port" == ${transport[${i}]:0:8} ]]; then
local dst_port="[${transport[${i}]##dst_port }]"
fi
if [[ "ul_proto" == ${transport[${i}]:0:8} ]]; then
local ul_proto=${transport[${i}]##ul_proto }
fi
if [[ "protocol esp level" == ${transport[${i}]:0:18} ]]; then
local esp_level=${transport[${i}]##protocol esp level }
fi
if [[ "protocol ah level" == ${transport[${i}]:0:17} ]]; then
local ah_level=${transport[${i}]##protocol ah level }
fi
if [[ "protocol ipcomp level" == ${transport[${i}]:0:21} ]]; then
local ipcomp_level=${transport[${i}]##protocol ipcomp level }
fi
done
# Decide whether to include ah/esp/ipcomp
if [[ "$esp_level" ]]; then
local esp_proto_sd=$(printf "\n\tesp/transport/${src_ip}-${dst_ip}/${esp_level}")
local esp_proto_ds=$(printf "\n\tesp/transport/${dst_ip}-${src_ip}/${esp_level}")
fi
if [[ "${ah_level}" ]]; then
local ah_proto_sd=$(printf "\n\tah/transport/${src_ip}-${dst_ip}/${ah_level}")
local ah_proto_ds=$(printf "\n\tah/transport/${dst_ip}-${src_ip}/${ah_level}")
fi
if [[ "${ipcomp_level}" ]]; then
local ipcomp_proto_sd=$(printf "\n\tipcomp/transport/${src_ip}-${dst_ip}/${ipcomp_level}")
local ipcomp_proto_ds=$(printf "\n\tipcomp/transport/${dst_ip}-${src_ip}/${ipcomp_level}")
fi
local policy1=$(printf "spdadd ${src_ip}${src_port} ${dst_ip}${dst_port} ${ul_proto} -P out ipsec ${esp_proto_sd} ${ah_proto_sd} ${ipcomp_proto_sd} ;")
local policy2=$(printf "\nspdadd ${dst_ip}${dst_port} ${src_ip}${src_port} ${ul_proto} -P in ipsec ${esp_proto_ds} ${ah_proto_ds} ${ipcomp_proto_ds} ;")
# Now we are ready to insert policies
printf "${policy1} ${policy2}\n" > /tmp/polfile
ebegin "Checking generated policy"
setkey -n -f /tmp/polfile &>/tmp/error
RET=$?
ERR=$(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
if [[ "$ERR" ]]; then
ewend 1 $ERR
cat /tmp/polfile && rm -f /tmp/polfile
return 1
else
ewend 0
fi
ebegin "Instating policy for ${tran}"
setkey -f /tmp/polfile &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
if [[ "${debug_ipsec}" == "on" ]]; then
einfo "The following policy was generated for ${tran}:"
cat /tmp/polfile
fi
rm -f /tmp/polfile &>/dev/null
done
unset tunnel transport
}
create_firewall_rules() {
r_fw="/var/lib/ipsec/remove_firewall"
mkdir -p /var/lib/ipsec
printf "#!/bin/bash\n\nsource /sbin/functions.sh\n\n" > $r_fw
chmod 750 $r_fw
for rules in ${!iptables*}; do
RULES="rules2=(\"\${${rules}[@]}\")"
eval $RULES
# Extract all of the rules for the tunnels/transports
einfo "Instating firewall rules for ${rules} ..."
printf "ebegin \"Removing firewall rules for ${rules}\"\n" >> $r_fw
for i in ${!rules2[*]}; do
rule_add="iptables -I ${rules2[${i}]}"
rule_del="iptables -D ${rules2[${i}]}"
ebegin " - ${rule_add}"
$rule_add &>/tmp/error
ewend $? $(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)
printf "ebegin \" - ${rule_del}\"\n" >> $r_fw
printf "${rule_del} &>/tmp/error\n" >> $r_fw
printf "ewend \$? \$(cat /tmp/error 2>/dev/null && rm -f /tmp/error 2>/dev/null)\n" >> $r_fw
done
done
}
create_racoon_conf() {
mkdir -p /var/lib/ipsec
conf=/var/lib/ipsec/racoon.conf
printf "# File: /var/lib/ipsec/racoon.conf\n#\n" > $conf
printf "# This file is automatically generated by /etc/init.d/ipsec. All changes will be overwritten.\n\n" >> $conf
printf "path certificate \"$certificate_path\";\n" >> $conf
printf "path pre_shared_key \"$psk_path\";\n\n" >> $conf
if [[ "${listen[@]}" ]]; then
printf "listen {\n" >> $conf
for listn in "${listen[@]}"; do
printf "\t$listn;\n" >> $conf
done
printf "}\n\n" >> $conf
fi
for tun in ${!tunnel*}; do
unset encryption_algorithm encryption_keylen authentication_algorithm authentication_keylen
unset authentication certificate certificate_key pre_shared_key compression_algorithm exchange_mode
unset src_net dst_net src_port dst_port src_gw_ip dst_gw_ip ul_proto block
ebegin "Building security associations for ${tun}"
TUN="tunnel=(\"\${${tun}[@]}\")"
eval $TUN
# Extract all of the options for the tunnel
for i in ${!tunnel[*]}; do
if [[ "src_net" == ${tunnel[${i}]:0:7} ]]; then
local src_net=${tunnel[${i}]##src_net }
fi
if [[ "dst_net" == ${tunnel[${i}]:0:7} ]]; then
local dst_net=${tunnel[${i}]##dst_net }
fi
if [[ "src_port" == ${tunnel[${i}]:0:8} ]]; then
local src_port="[${tunnel[${i}]##src_port }]"
fi
if [[ "dst_port" == ${tunnel[${i}]:0:8} ]]; then
local dst_port="[${tunnel[${i}]##dst_port }]"
fi
if [[ "src_gw_ip" == ${tunnel[${i}]:0:9} ]]; then
local src_gw_ip=${tunnel[${i}]##src_gw_ip }
fi
if [[ "dst_gw_ip" == ${tunnel[${i}]:0:9} ]]; then
local dst_gw_ip=${tunnel[${i}]##dst_gw_ip }
fi
if [[ "ul_proto" == ${tunnel[${i}]:0:8} ]]; then
local ul_proto=${tunnel[${i}]##ul_proto }
fi
if [[ "exchange_mode " == ${tunnel[${i}]:0:14} ]]; then
local exchange_mode=${tunnel[${i}]##exchange_mode }
fi
if [[ "encryption_algorithm " == ${tunnel[${i}]:0:21} ]]; then
local encryption_algorithm=${tunnel[${i}]##encryption_algorithm }
fi
if [[ "encryption_keylen " == ${tunnel[${i}]:0:18} ]]; then
local encryption_keylen=${tunnel[${i}]##encryption_keylen }
fi
if [[ "hash_algorithm " == ${tunnel[${i}]:0:15} ]]; then
local hash_algorithm=${tunnel[${i}]##hash_algorithm }
fi
if [[ "compression_algorithm " == ${tunnel[${i}]:0:22} ]]; then
local compression_algorithm=${tunnel[${i}]##compression_algorithm }
fi
if [[ "authentication_algorithm " == ${tunnel[${i}]:0:25} ]]; then
local authentication_algorithm="[${tunnel[${i}]##authentication_algorithm }]"
fi
if [[ "authentication_keylen " == ${tunnel[${i}]:0:22} ]]; then
local authentication_keylen="[${tunnel[${i}]##authentication_keylen }]"
fi
if [[ "authentication " == ${tunnel[${i}]:0:15} ]]; then
local authentication=${tunnel[${i}]##authentication }
fi
if [[ "certificate " == ${tunnel[${i}]:0:12} ]]; then
local certificate=${tunnel[${i}]##certificate }
fi
if [[ "certificate_key " == ${tunnel[${i}]:0:16} ]]; then
local certificate_key=${tunnel[${i}]##certificate_key }
fi
if [[ "pre_shared_key " == ${tunnel[${i}]:0:15} ]]; then
local pre_shared_key=${tunnel[${i}]##pre_shared_key }
fi
done
# Set some defaults
local exchange_mode=${exchange_mode:-main}
local encryption_algorithm=${encryption_algorithm:-aes}
local encryption_keylen=${encryption_keylen:-256}
local hash_algorithm=${hash_algorithm:-md5}
local compression_algorithm=${compression_algorithm:-deflate}
local authentication_algorithm=${authentication_algorithm:-hmac_sha1}
local authentication_keylen=${authentication_keylen:-160}
local authentication=${authentication:-pre_shared_key}
# We have now extracted all of the settings for the tunnel
printf "remote ${dst_gw_ip} {\n" >> $conf
printf "\texchange_mode ${exchange_mode};\n" >> $conf
if [[ "${authentication}" == "X.509" ]]; then
printf "\tcertificate_type x509 \"${certificate}\" \"${certificate_key}\";\n" >> $conf
printf "\tverify_cert on;\n" >> $conf
printf "\tmy_identifier asn1dn;\n" >> $conf
printf "\tpeers_identifier asn1dn;\n" >> $conf
fi
printf "\tproposal {\n" >> $conf
printf "\t\tencryption_algorithm ${encryption_algorithm};\n" >> $conf
printf "\t\thash_algorithm ${hash_algorithm};\n" >> $conf
if [[ "${authentication}" == "X.509" ]]; then
printf "\t\tauthentication_method rsasig;\n" >> $conf
fi
if [[ "${authentication}" == "psk" ]]; then
printf "\t\tauthentication_method pre_shared_key;\n" >> $conf
fi
printf "\t\tdh_group modp1024;\n" >> $conf
printf "\t}\n" >> $conf
printf "}\n" >> $conf
local block=$(printf "\tpfs_group modp768;\n\tencryption_algorithm ${encryption_algorithm};\n\tauthentication_algorithm ${authentication_algorithm};\n\tcompression_algorithm ${compression_algorithm};")
printf "sainfo address ${src_gw_ip} ${ul_proto} address ${dst_gw_ip} ${ul_proto} {\n$block\n}\n" >> $conf
printf "sainfo address ${src_gw_ip} ${ul_proto} address ${dst_net} ${dst_port} ${ul_proto} {\n$block\n}\n" >> $conf
printf "sainfo address ${src_net} ${src_port} ${ul_proto} address ${dst_net} ${dst_port} ${ul_proto} {\n$block\n}\n" >> $conf
printf "sainfo address ${src_net} ${src_port} ${ul_proto} address ${dst_gw_ip} ${ul_proto} {\n$block\n}\n" >> $conf
printf "\n" >> $conf
ewend 0
done
for tran in ${!transport*}; do
unset encryption_algorithm encryption_keylen authentication_algorithm authentication_keylen
unset authentication certificate certificate_key pre_shared_key compression_algorithm exchange_mode
unset src_ip dst_ip src_port dst_port ul_proto block
ebegin "Building security associations for ${tran}"
TRAN="transport=(\"\${${tran}[@]}\")"
eval $TRAN
# Extract all of the options for the transport
for i in ${!transport[*]}; do
if [[ "src_ip" == ${transport[${i}]:0:6} ]]; then
local src_ip=${transport[${i}]##src_ip }
fi
if [[ "dst_ip" == ${transport[${i}]:0:6} ]]; then
local dst_ip=${transport[${i}]##dst_ip }
fi
if [[ "src_port" == ${transport[${i}]:0:8} ]]; then
local src_port="[${transport[${i}]##src_port }]"
fi
if [[ "dst_port" == ${transport[${i}]:0:8} ]]; then
local dst_port="[${transport[${i}]##dst_port }]"
fi
if [[ "ul_proto" == ${transport[${i}]:0:8} ]]; then
local ul_proto=${transport[${i}]##ul_proto }
fi
if [[ "exchange_mode " == ${transport[${i}]:0:14} ]]; then
local exchange_mode=${transport[${i}]##exchange_mode }
fi
if [[ "encryption_algorithm " == ${transport[${i}]:0:21} ]]; then
local encryption_algorithm=${transport[${i}]##encryption_algorithm }
fi
if [[ "encryption_keylen " == ${transport[${i}]:0:18} ]]; then
local encryption_keylen=${transport[${i}]##encryption_keylen }
fi
if [[ "hash_algorithm " == ${transport[${i}]:0:15} ]]; then
local hash_algorithm=${transport[${i}]##hash_algorithm }
fi
if [[ "compression_algorithm " == ${transport[${i}]:0:22} ]]; then
local compression_algorithm=${transport[${i}]##compression_algorithm }
fi
if [[ "authentication_algorithm " == ${transport[${i}]:0:25} ]]; then
local authentication_algorithm="[${transport[${i}]##authentication_algorithm }]"
fi
if [[ "authentication_keylen " == ${transport[${i}]:0:22} ]]; then
local authentication_keylen="[${transport[${i}]##authentication_keylen }]"
fi
if [[ "authentication " == ${transport[${i}]:0:15} ]]; then
local authentication=${transport[${i}]##authentication }
fi
if [[ "certificate " == ${transport[${i}]:0:12} ]]; then
local certificate=${transport[${i}]##certificate }
fi
if [[ "certificate_key " == ${transport[${i}]:0:16} ]]; then
local certificate_key=${transport[${i}]##certificate_key }
fi
if [[ "pre_shared_key " == ${transport[${i}]:0:15} ]]; then
local pre_shared_key=${transport[${i}]##pre_shared_key }
fi
done
# Set some defaults
local exchange_mode=${exchange_mode:-main}
local encryption_algorithm=${encryption_algorithm:-aes}
local encryption_keylen=${encryption_keylen:-256}
local hash_algorithm=${hash_algorithm:-md5}
local compression_algorithm=${compression_algorithm:-deflate}
local authentication_algorithm=${authentication_algorithm:-hmac_sha1}
local authentication_keylen=${authentication_keylen:-160}
local authentication=${authentication:-pre_shared_key}
# We have now extracted all of the settings for the tunnel
printf "remote ${dst_ip} {\n" >> $conf
printf "\texchange_mode ${exchange_mode};\n" >> $conf
if [[ "${authentication}" == "X.509" ]]; then
printf "\tcertificate_type x509 \"${certificate}\" \"${certificate_key}\";\n" >> $conf
printf "\tverify_cert on;\n" >> $conf
printf "\tmy_identifier asn1dn;\n" >> $conf
printf "\tpeers_identifier asn1dn;\n" >> $conf
fi
printf "\tproposal {\n" >> $conf
printf "\t\tencryption_algorithm ${encryption_algorithm};\n" >> $conf
printf "\t\thash_algorithm ${hash_algorithm};\n" >> $conf
if [[ "${authentication}" == "X.509" ]]; then
printf "\t\tauthentication_method rsasig;\n" >> $conf
fi
if [[ "${authentication}" == "psk" ]]; then
printf "\t\tauthentication_method pre_shared_key;\n" >> $conf
fi
printf "\t\tdh_group modp1024;\n" >> $conf
printf "\t}\n" >> $conf
printf "}\n" >> $conf
local block=$(printf "\tpfs_group modp768;\n\tencryption_algorithm ${encryption_algorithm};\n\tauthentication_algorithm ${authentication_algorithm};\n\tcompression_algorithm ${compression_algorithm};")
printf "sainfo address ${src_ip} ${ul_proto} address ${dst_ip} ${ul_proto} {\n$block\n}\n" >> $conf
ewend 0
done
if [[ "${!roadwarrior[*]}" ]]; then
unset encryption_algorithm encryption_keylen authentication_algorithm authentication_keylen
unset authentication certificate certificate_key pre_shared_key compression_algorithm exchange_mode
unset src_ip dst_ip src_port dst_port ul_proto block
for i in ${!roadwarrior[*]}; do
if [[ "exchange_mode " == ${roadwarrior[${i}]:0:14} ]]; then
local exchange_mode=${roadwarrior[${i}]##exchange_mode }
fi
if [[ "encryption_algorithm " == ${roadwarrior[${i}]:0:21} ]]; then
local encryption_algorithm=${roadwarrior[${i}]##encryption_algorithm }
fi
if [[ "encryption_keylen " == ${roadwarrior[${i}]:0:18} ]]; then
local encryption_keylen=${roadwarrior[${i}]##encryption_keylen }
fi
if [[ "hash_algorithm " == ${roadwarrior[${i}]:0:15} ]]; then
local hash_algorithm=${roadwarrior[${i}]##hash_algorithm }
fi
if [[ "compression_algorithm " == ${roadwarrior[${i}]:0:22} ]]; then
local compression_algorithm=${roadwarrior[${i}]##compression_algorithm }
fi
if [[ "authentication_algorithm " == ${roadwarrior[${i}]:0:25} ]]; then
local authentication_algorithm="[${roadwarrior[${i}]##authentication_algorithm }]"
fi
if [[ "authentication_keylen " == ${roadwarrior[${i}]:0:22} ]]; then
local authentication_keylen="[${roadwarrior[${i}]##authentication_keylen }]"
fi
if [[ "authentication " == ${roadwarrior[${i}]:0:15} ]]; then
local authentication=${roadwarrior[${i}]##authentication }
fi
if [[ "certificate " == ${roadwarrior[${i}]:0:12} ]]; then
local certificate=${roadwarrior[${i}]##certificate }
fi
if [[ "certificate_key " == ${roadwarrior[${i}]:0:16} ]]; then
local certificate_key=${roadwarrior[${i}]##certificate_key }
fi
if [[ "pre_shared_key " == ${roadwarrior[${i}]:0:15} ]]; then
local pre_shared_key=${roadwarrior[${i}]##pre_shared_key }
fi
done
# Set some defaults
local exchange_mode=${exchange_mode:-main}
local encryption_algorithm=${encryption_algorithm:-3des}
local encryption_keylen=${encryption_keylen:-256}
local hash_algorithm=${hash_algorithm:-sha1}
local compression_algorithm=${compression_algorithm:-deflate}
local authentication_algorithm=${authentication_algorithm:-hmac_sha1}
local authentication_keylen=${authentication_keylen:-160}
local authentication=${authentication:-pre_shared_key}
# We have now extracted all of the settings for the tunnel
printf "remote anonymous {\n" >> $conf
printf "\texchange_mode ${exchange_mode};\n" >> $conf
if [[ "${authentication}" == "X.509" ]]; then
printf "\tcertificate_type x509 \"${certificate}\" \"${certificate_key}\";\n" >> $conf
printf "\tverify_cert on;\n" >> $conf
printf "\tmy_identifier asn1dn;\n" >> $conf
printf "\tpeers_identifier asn1dn;\n" >> $conf
fi
printf "\tnat_traversal on;\n" >> $conf
printf "\tgenerate_policy on;\n" >> $conf
printf "\tproposal {\n" >> $conf
printf "\t\tencryption_algorithm ${encryption_algorithm};\n" >> $conf
printf "\t\thash_algorithm ${hash_algorithm};\n" >> $conf
if [[ "${authentication}" == "X.509" ]]; then
printf "\t\tauthentication_method rsasig;\n" >> $conf
fi
if [[ "${authentication}" == "psk" ]]; then
printf "\t\tauthentication_method pre_shared_key;\n" >> $conf
fi
printf "\t\tdh_group modp1024;\n" >> $conf
printf "\t}\n" >> $conf
printf "}\n" >> $conf
local block=$(printf "\tencryption_algorithm ${encryption_algorithm};\n\tauthentication_algorithm ${authentication_algorithm};\n\tcompression_algorithm ${compression_algorithm};")
printf "sainfo anonymous {\n$block\n}\n" >> $conf
ewend 0
fi
ebegin "Starting racoon"
racoon -f $conf &>/tmp/error
RET=$?
ERR=$(cat /tmp/error 2>/dev/null)
CONFERR=$(cat /tmp/error 2>/dev/null | grep "failed to parse configuration")
ewend $RET $ERR
if [[ -z $RET ]]; then
svc_stop
if [[ "${CONFERR}" ]]; then
ewarn "There was a problem with your configuration. I am about to dump the config."
sleep 5
less $conf
fi
fi
if [[ "${debug_ipsec}" == "on" ]]; then
einfo "The following policy was generated for ${tran}:"
cat $conf
fi
}
docmd() {
if [[ "$debug_ipsec" == "on" ]]; then
ebegin " - ${CMD}"
fi
${CMD} &>/tmp/error
if [[ "$debug_ipsec" == "on" ]]; then
ewend $? $(cat /tmp/error)
fi
rm -f /tmp/error
}
if [ -r /etc/conf.d/ipsec ]; then
source /etc/conf.d/ipsec
fi
|
Don't forget to make the script executable and add it to your default runlevel:
bash init.d # chmod 755 /etc/init.d/ipsec bash init.d # rc-update add ipsec default
[edit] Creating the IPSec Connection
[edit] IPSec Between Two Gentoo Boxes
If you are creating a tunnel between two Gentoo boxes, go ahead and install the /etc/conf.d/ipsec and /etc/init.d/ipsec files on your second Gentoo box. You can literally copy the configuration of your first box to your second box and swap the source and destination IP addresses and then change the name of the certificate on your second box accordingly. Don't forget to change the IP addresses to listen to in the listen section at the top. Aside from changing IP addresses and your certificate files, everything else stays the same.
Next, you need to copy your certificate from your first machine to your second machine. On your second machine, issue the following commands:
bash ~ # mkdir /etc/certs && chmod 700 /etc/certs && cd /etc/certs bash certs # scp 111.111.111.111:/etc/certs/mysecondhost.mydomain.com* .
The scp utility allows you to securely copy files between two hosts running SSH. For more information on how scp operates, man scp.
You will also need to copy over the CA certificate and the CA certificate revocation list. The names of the CA certificate and CA CRL will vary. They will look something like '0a9b467afd.0' and '65ad8d7ee6.r0' inside the /etc/certs directory on the server where you set up the CA. Copy both files to this host:
bash certs # scp 111.111.111.111:/etc/certs/*.0 . bash certs # scp 111.111.111.111:/etc/certs/*.r0 .
If you maintain a CRL, you will need to set up some method for automating the transfer of the CRL to each of your clients on a regular basis.
Now, on both Gentoo boxes, issue this command:
bash ~ # /etc/init.d/ipsec start
That's it! You should have a fully operational IPSec connection between your two Gentoo boxes. Try a ping:
bash ~ # ping -c 5 222.222.222.222 connect: Resource temporarily unavailable bash ~ # ping -c 5 222.222.222.222 PING 222.222.222.222 (222.222.222.222) 56(84) bytes of data. 64 bytes from 222.222.222.222: icmp_seq=1 ttl=64 time=30.2 ms 64 bytes from 222.222.222.222: icmp_seq=2 ttl=64 time=31.1 ms 64 bytes from 222.222.222.222: icmp_seq=3 ttl=64 time=31.2 ms 64 bytes from 222.222.222.222: icmp_seq=4 ttl=64 time=32.0 ms 64 bytes from 222.222.222.222: icmp_seq=5 ttl=64 time=32.4 ms --- 222.222.222.222 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4002ms rtt min/avg/max/mdev = 30.284/31.420/32.474/0.791 ms bash ~ #
If you run a tcpdump simultaneously with the ping, you should see something like this:
bash ~ # tcpdump -n -i eth0 host 222.222.222.222 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 68 bytes 18:59:45.761406 IP 111.111.111.111.500 > 222.222.222.222.500: [|isakmp] 18:59:45.767691 IP 222.222.222.222.500 > 111.111.111.111.500: [|isakmp] 18:59:45.903988 IP 111.111.111.111.500 > 222.222.222.222.500: [|isakmp] 18:59:45.920815 IP 222.222.222.222.500 > 111.111.111.111.500: [|isakmp] 18:59:46.121085 IP 111.111.111.111.500 > 222.222.222.222.500: [|isakmp] 18:59:46.133957 IP 222.222.222.222.500 > 111.111.111.111.500: [|isakmp] 18:59:46.202756 IP 111.111.111.111.500 > 222.222.222.222.500: [|isakmp] 18:59:47.275971 IP 111.111.111.111.500 > 222.222.222.222.500: [|isakmp] 18:59:47.284567 IP 222.222.222.222.500 > 111.111.111.111.500: [|isakmp] 18:59:47.321799 IP 111.111.111.111.500 > 222.222.222.222.500: [|isakmp] 18:59:52.614406 IP 111.111.111.111 > 222.222.222.222: ESP(spi=0x0d23c49b,seq=0x1), length 132 18:59:52.614562 IP 222.222.222.222 > 111.111.111.111: ESP(spi=0x05167468,seq=0x1), length 132 18:59:53.616321 IP 111.111.111.111 > 222.222.222.222: ESP(spi=0x0d23c49b,seq=0x2), length 132 18:59:53.616437 IP 222.222.222.222 > 111.111.111.111: ESP(spi=0x05167468,seq=0x2), length 132 18:59:54.616211 IP 111.111.111.111 > 222.222.222.222: ESP(spi=0x0d23c49b,seq=0x3), length 132 18:59:54.616330 IP 222.222.222.222 > 111.111.111.111: ESP(spi=0x05167468,seq=0x3), length 132 18:59:55.617116 IP 111.111.111.111 > 222.222.222.222: ESP(spi=0x0d23c49b,seq=0x4), length 132 18:59:55.617231 IP 222.222.222.222 > 111.111.111.111: ESP(spi=0x05167468,seq=0x4), length 132 18:59:56.618996 IP 111.111.111.111 > 222.222.222.222: ESP(spi=0x0d23c49b,seq=0x5), length 132 18:59:56.619113 IP 222.222.222.222 > 111.111.111.111: ESP(spi=0x05167468,seq=0x5), length 132
[edit] Configuring Windows XP w/Service Pack 2 For IPSec
First, we need to securely copy the XP certificate (the .pfx file) and CA certificate (.pem file) to the Windows client. To do this, go download WinSCP. It is a secure copy program which uses SSH to transfer files. Use WinSCP to transfer both files to your Desktop. When you are finished, close WinSCP and follow these steps:
| 1. Click on Start->Run and type 'mmc'. | |
| 2. Click Ok. The Windows Management Console should appear. | |
| 3. Click File->Add/Remove Snap In... | |
| 4. Click IP Security Policy Management. | |
| 5. Click Add. | |
| 6. Make sure the dot is in Local computer. | |
| 7. Click Ok. | |
| 8. Click IP Security Monitor. | |
| 9. Click Add. | |
| 10. Click Event Viewer. | |
| 11. Click Add. | |
| 12. Make sure the dot is in Local computer. | |
| 13. Click Ok. | |
| 14. Click Certificates. | |
| 15. Click Add. | |
| 16. Put the dot in Computer Account. | |
| 17. Click Next. | |
| 18. Make sure the dot is in Local computer. | |
| 19. Click Finish. | |
| 20. Click Close. | |
| 21. Click Ok. | |
| 22. Expand Certificates. | |
| 23. Click Trusted Root Certification Authority. | |
| 24. Click Action->All Tasks->Import | |
| 25. Click Next. | |
| 26. Browse to the location where you saved your CA certificate (.pem file). | |
| 27. Click Next. | |
| 28. Make sure the dot is in Place all certificates in the following store. | |
| 29. Make sure the Trusted Root Certification Authorities store is selected. | |
| 30. Click Next. | |
| 31. Click Finish. | |
| 32. Click on the Personal certificate store. | |
| 33. Click Action->All Tasks->Import. | |
| 34. Browse to the location where you saved your client certificate (.pfx file). | |
| 35. Click Next. | |
| 36. Enter the password you chose when you created your PFX certificate. | |
| 37. Click Next. | |
| 38. Make sure the dot is in Place all certificates in the following store. | |
| 39. Make sure the Personal certificate store is selected. | |
| 40. Click Next. | |
| 41. Click Finish. | |
| 42. Click IP Security Policies on Local Computer. | |
| 43. Right-click on the white-space on the right-hand side. | |
| 44. Left-click on Create IP Security Policy. | |
| 45. Click Next. | |
| 46. Type a name for your security policy. | |
| 47. Type a description for your security policy. | |
| 48. Click Next. | |
| 49. Uncheck Activate the default response rule. | |
| 50. Click Next. | |
| 51. Make sure Edit properties is checked. | |
| 52. Click Finish. | |
| 53. Uncheck Use Add Wizard. | |
| 54. Click Add to create a new rule. | |
| 55. Click Add to create a new IP filter list. | |
| 56. Name the IP filter list 'Me to Gentoo'. | |
| 57. In the description, type 'Me to Gentoo'. | |
| 58. Uncheck Use Add Wizard. | |
| 59. Click Add to create a new IP filter. | |
| 60. For the source address, select My IP Address. | |
| 61. For the destination address, select A specific IP Address. | |
| 62. In the IP Address box, enter the IP address of your Gentoo Linux IPSec server. | |
| 63. Uncheck Mirrored. | |
| 64. Click Ok to close the IP Filter Properties. | |
| 65. Click Ok to close the IP Filter List Properties. | |
| 66. Click Add to create a new IP filter list. | |
| 67. Name the IP filter list 'Gentoo to Me'. | |
| 68. In the description, type 'Gentoo to Me'. | |
| 69. Use Add Wizard should still be unchecked. | |
| 70. Click Add to create a new IP filter. | |
| 71. For the source address, select A specific IP Address. | |
| 72. In the IP Address box, enter the IP address of your Gentoo Linux IPSec server. | |
| 73. For the destination address, select My IP Address. | |
| 74. Uncheck Mirrored. | |
| 75. Click Ok to close the IP Filter Properties. | |
| 76. Click Ok to close the IP Filter List Properties. | |
| 77. Put a dot in Me to Gentoo. | |
| 78. Click the Filter Action tab. | |
| 79. Uncheck Use Add Wizard. | |
| 80. Click Add to create a new Filter Action. | |
| 81. Make sure the dot is in Negotiate Security. | |
| 82. Click Add to define a new security method. | |
| 83. Put the dot in Custom. | |
| 84. Click Settings. | |
| 85. Make sure there is a check in Data integrity and encryption (ESP). | |
| 86. For Integrity algorithm, make sure SHA1 is selected. | |
| 87. For Encryption algorithm, if you have an option to choose AES, choose it; otherwise, choose 3DES. | |
| 88. Put a check in the left Generate a new key every. | |
| 89. Put a check in the right Generate a new key every. | |
| 90. Click Ok. | |
| 91. Put a check in Use session key perfect forward security (PFS). | |
| 92. Click the General tab. | |
| 93. In the name field, type 'Secure Two-Way Communication'. | |
| 94. In the description field, type 'This option requires both parties to communicate over a secure channel. | |
| 95. Click Ok. | |
| 96. Put a dot in Secure Two-Way Communication. | |
| 97. Click the Authentication Methods tab. | |
| 98. Click Edit. | |
| 99. Put a dot in Use a certificate from this certificate authority (CA). | |
| 100. Click Browse. | |
| 101. Select the CA certificate you imported in steps 22 through 31. | |
| 102. Click Ok to select the certificate. | |
| 103. Click Ok to close the Authentication Method Properties dialog. | |
| 104. Click Close to close the New Rule Properties dialog. | |
| 105. Click Add to create a new rule. | |
| 106. Put a dot in Gentoo to Me. | |
| 107. Click on the Filter Action tab. | |
| 108. Put a dot in Secure Two-Way Communication. | |
| 109. Click on the Authentication Methods tab. | |
| 110. Click Edit. | |
| 111. Put a dot in Use a certificate from this certificate authority (CA). | |
| 112. Click Browse. | |
| 113. Select the CA certificate you imported in steps 22 through 31. | |
| 114. Click Ok to select the certificate. | |
| 115. Click Ok to close the Authentication Method Properties dialog. | |
| 116. Click Close to close the New Rule Properties dialog. | |
| 117. Click Ok to close the IP Security Policy Properties dialog. | |
| 118. Right-click the new security policy you created. | |
| 119. Left-click Assign to use the new security policy. | |
| 120. Ensure the policy is assigned. |
If you are still with us at this point, you should now have an IPSec transport connection between your Windows XP SP2 computer and your Gentoo IPSec server. When you issue a ping to your Gentoo server, you should see a couple of messages saying "Negotiating IP Security". After 1-4 of these messages, your pings should start going through. If you continue to receive these messages, it is most likely that you either did not import your certificates correctly, you did not enter the correct IP address in one of the fields of the IP filters, or you did not select the correct options for the filter actions. It is also possible that you messed something up on your Gentoo side. To troubleshoot the connection, turn on Logon/Logoff auditing (Control Panel->Administrative Tools->Local Security Policy->Local Policies->Audit Policy) and use the Security Log in the Event Viewer.