DæmonNews: News and views for the BSD community

Daemon News Ezine BSD News BSD Mall BSD Support Forum BSD Advocacy BSD Updates

FreeBSD IPSEC: Racoon + X.509 Certificates

by Alex C. Jokela (alex@camulus.com)

Abstract

This document provides a simple guide to quickly get racoon using X.509 certificates instead of shared keys.

Certificates

Creating a Certificate Authority

First and foremost, you will want to download a couple of files from either my own site or from the author of the originals.

If for some reason or another the links end up being dead, copies of my files can be found at the end of this document in Appendix A.

Once you have downloaded Makefile and openssl.cnf, you should probably edit openssl.cnf to suit your situation (i.e. changing the organization and contact names). I would also put the two files in their own directory, ssl, for example.

After editing openssl.cnf, type at the command line:

make init

If you are curious as to what exactly make init is doing, here you go:

test ! -f serial
mkdir crl newcerts private
chmod go-rwx private
echo '01' > serial
touch index
openssl req -nodes -config openssl.cnf -days 1825 -x509 -newkey rsa -out ca-cert.pem -outform PEM

Creating X.509 Certificates

Now that we have a CA, we make some certificates, one for each end-host that our tunnel will connect.

Hint: Instead of hostX, use the hostname of the machine that the certificate will eventually live on.

  1. We will need to make a private key:
    openssl genrsa -out hostX.key
      
  2. Generate the Certificate:
    openssl req -new -nodes -key hostX.key -out hostX.csr
      
  3. Using our Makefile:
    make sign
      
  4. You should now have a self-signed X.509 certificate. Repeat this for the other host that will be used.

If you are curious as to what exactly make sign is doing, here you go:

openssl ca -batch -config openssl.cnf -in hostX.csr -out hostX.cert

Creating Tunnels

For the following, we will be using the fictitious IP addresses of 3.3.3.3 and 4.4.4.4 for the "real world" IPs. For our tunnel-endpoints, we will be using 10.1.1.1 on the 3.3.3.3 machine, and 10.1.2.1 on the 4.4.4.4 machine.

On 3.3.3.3

ifconfig gif0 create
ifconfig gif0 tunnel 3.3.3.3 4.4.4.4
ifconfig gif0 inet 10.1.1.1 10.1.2.1

The reverse of this will need to be preformed on 4.4.4.4

Setting up Routing

For this fictitious network, we have one endpoint of the tunnel being, for example, a secondary DNS server. There are no systems behind it, i.e., it is not performing NAT. The other endpoint, however, is performing NAT, and you would like be able to have the systems behind the endpoint be able to securely contact the other endpoint and vise versa.

On 4.4.4.4 (our DNS server mentioned above), run the following command:

route add -net 172.16 -interface gif0

assuming you use that network prefix. Most commonly, people with small SOHO networks use something like 192.168.0.

We need not put any new static routes in place for the NAT'ing endpoint. That is because this particular machine is already configured (you configured it for NAT, right?) for routing packets from the inside network.

Testing Tunnels before using IPSEC

The following assumes that you have punched the correct holes into your firewall configuration. You need to allow IP-in-IP packets (in /etc/protocols, it is ipencap for the type).

From the DNS server (4.4.4.4)

ping 172.16.0.100

We are part way there, now try pinging from 172.16.0.100

ping 10.1.2.1

Both of the above commands should work. If they do not, do not proceed until you have corrected the problem. Things to think over to help diagnose the problem:

  1. Did you correctly setup the gif interfaces?
  2. Did you remember to put in a static route on the machine that would represent the DNS machine in the above example?

IPSEC

Kernel Configuration

In order to start encrypting packets, you will need to make sure that your kernel has IPSEC support compiled into it. This is relatively simple. The following will assume that you already have a fresh copy of the FreeBSD source.

  1. Copy the GENERIC kernel configuration to the name of your choice:
    cp /usr/src/sys/i386/conf/GENERIC
    /usr/src/sys/i386/conf/FRANK-N-BEANS
      
  2. Add the following to the kernel config:
    options   IPSEC         #IP security
    options   IPSEC_ESP     #IP security (crypto; define w/ IPSEC)
    options   IPSEC_DEBUG   #debug for IP security
      
  3. Compile and install your new kernel:
    cd /usr/src && make KERCONF=FRANK-N-BEANS buildkernel && make KERNCONF=FRANK-N-BEANS installkernel && reboot
      

Configuring Racoon for X.509 Certificates

First, you need to transfer the tuple of certs (ca-cert.pem, hostX.key, hostX.cert) to the system on which they are to reside. The files should be put in a directory like /usr/local/etc/racoon/cert. Add the following to your racoon.conf and make sure to change the IP address of the remote endpoint IP of the tunnel. The following would be used on the NAT machine:

remote 10.1.2.1
{
  exchange_mode main,aggressive;
  doi ipsec_doi;

  situation identity_only;
  my_identifier asn1dn;
  peers_identifier asn1dn;
  verify_identifier on;
  certificate_type x509 "hostX.cert" "hostX.key";
  nonce_size 16;
  lifetime time 1 min;    # sec,min,hour

  support_mip6 on;

  proposal_check strict;  # obey, strict or claim



  proposal {

    encryption_algorithm 3des;
    hash_algorithm sha1;
    authentication_method rsasig ;
    dh_group 2 ;
  }
}

Make sure to change your certificate path to match the real location of your certificates.

path certificate "/usr/local/etc/racoon/cert";

Finally, we need to tell racoon about our CA certificate, ca-cert.pem. In your certificates directory, run the following:

ln -s ca-cert.pem `openssl x509 -noout -hash -in ca-cert.pem`.0

Setting up the necessary SPD Entries

You now have one last thing to do - setup the IPSEC rules that get fed to the kernel. This, of course, will need to be done on each endpoint system of the tunnel. The following would go into your /etc/ipsec.conf:

flush;
spdflush;

spdadd 10.1.2.1/32 10.1.1.1/32 any -P in  ipsec esp/tunnel/10.1.2.1-10.1.1.1/require;
spdadd 10.1.1.1/32 10.1.2.1/32 any -P out ipsec esp/tunnel/10.1.1.1-10.1.2.1/require;

spdadd 172.16.0.0/16 10.1.2.1/32 any -P out ipsec esp/tunnel/10.1.1.1-10.1.2.1/require;
spdadd 10.1.2.1/32 172.16.0.0/16 any -P in ipsec esp/tunnel/10.1.2.1-10.1.1.1/require;

Starting your IPSEC in /etc/rc.conf

cloned_interfaces="gif0"

gif_interfaces="gif0"
gifconfig_gif0="3.3.3.3 4.4.4.4"

ifconfig_gif0="inet 10.1.1.1 10.1.2.1"

racoon_enable="YES"
racoon_flags="-f /usr/local/etc/racoon/racoon.conf"

ipsec_enable="YES"

Simply flip the IPs for the other system.

References and Links

Bibliography

  1. Jeremy Mates (jmates@sial.org)
  2. Mike DeGraw-Bertsch (mbertsch@radioactivedata.org)

Appendix A

Makefile:

requests = *.csr

sign: ${requests}

# remove -batch option if want chance to not certify a particular request
${requests}: FORCE
        @openssl ca -batch -config openssl.cnf -in $@ -out ${@:.csr=.cert}
        @[ -f ${@:.csr=.cert} ] && rm $@

revoke:
        @test $${cert:?"usage: make revoke cert=certificate"}
        @openssl ca -config openssl.cnf -revoke $(cert)
        @$(MAKE) gencrl

gencrl:
        @openssl ca -config openssl.cnf -gencrl -out ca-crl.pem

clean:
        -rm ${requests}

# creates required supporting files, CA key and certificate
init:
        @test ! -f serial
        @mkdir crl newcerts private
        @chmod go-rwx private
        @echo '01' > serial
        @touch index
        @openssl req -nodes -config openssl.cnf -days 1825 -x509 -newkey rsa -out ca-cert.pem -outform PEM

# for legacy make support
FORCE:

openssl.cnf

HOME                    = .
RANDFILE                = $ENV::HOME/.rnd

[ ca ]
default_ca      = CA_default

[ CA_default ]
dir             = .
# unset at present, and my limited certs can be kept in current dir
#certs          = $dir/certs
new_certs_dir   = $dir/newcerts
crl_dir         = $dir/crl
database        = $dir/index

certificate     = $dir/ca-cert.pem
serial          = $dir/serial
crl             = $dir/ca-crl.pem
private_key     = $dir/private/ca-key.pem
RANDFILE        = $dir/private/.rand

x509_extensions = usr_cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt        = ca_default
cert_opt        = ca_default

default_crl_days= 30
default_days    = 3650
# if need to be compatible with older software, use weaker md5
default_md      = sha1
# MSIE may need following set to yes?
preserve        = no

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy          = policy_match

# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

####################################################################
[ req ]
default_bits            = 2048
default_keyfile         = ./private/ca-key.pem
default_md              = sha1

prompt                  = no
distinguished_name      = root_ca_distinguished_name

x509_extensions = v3_ca

# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret

# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix   : PrintableString, BMPString.
# utf8only: only UTF8Strings.
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
# so use this option with caution!
string_mask = nombstr

# req_extensions = v3_req

[ root_ca_distinguished_name ]
commonName = Camulus.org
countryName = US
stateOrProvinceName = Minnesota
localityName = Proctor
0.organizationName = camulus.org
emailAddress = root@camulus.org

[ usr_cert ]


# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always

nsCaRevocationUrl               = https://secure.camulus.org/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName

[ v3_req ]

# Extensions to add to a certificate request

basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]


# Extensions for a typical CA

# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always

# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true

[ crl_ext ]

# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.

# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always
Google
Web daemonnews.org

More Articles
  • Stupid Launchd Tricks
  • Installing BSD on IBM Netvista S40 - Part 5: OS/2 Installation
  • Review: Nagios System and Network Monitoring
  • Working with gmirror and a Sun Fire X2100 (part 2)
  • Working with gmirror and a Sun Fire X2100 (part 1)
  • Open Source Initiatives and You...
  • Installing BSD on IBM Netvista S40 - Part 4: NetBSD Installation
  • Book Review: Open Source Pen Testers Toolkit
  • Daemon's Advocate
  • BSDCan 2006 Friday Photos
  • Installing BSD on IBM Netvista S40 - Part 3: DragonFly Installation
  • BSDCan 2006 Photos
  • AFS: network filesystem beyond NFS weaknesses
  • Mastering FreeBSD and OpenBSD Security
  • Installing BSD on IBM Netvista S40 - Part 2: FreeBSD Installation

  • Advertisements

    BSD News
  • SCALE 5x - Open Source Confernece In Los Angeles This Weekend
  • Open source is the ticket for In Ticketing
  • FreeBSD 4.x EoL
  • Submit A News Item
  • Stupid Launchd Tricks
  • Win a trip to BSDCan 2007
  • DragonFly BSD 1.8 Released
  • Why Gentoo Shouldn 't be on Your Server
  • Java/PAE Woes in FreeBSD



  • Author maintains all copyrights on this article.
    Images and layout Copyright © 1998-2006 Dæmon News. All Rights Reserved.