Less known Solaris features: IPsec

The secrets of root
There were other systems with other roots, other priests and other believers. But how should they communicate with each other without put their secrets in danger. Some chants and documents were really precious. The messenges of root had to be sure, that they gave the chants to the roots with the same belief. But the messengers had another problems: There were many bandits on their way to the other systems. And it was unthinkable that a mere bandit would know the secrets of root. Foundations
This will the only article in this series without an explanation of the technologies. I could write for days about it and still leaving out important things. Instead of this, please look at the links section at the end of the article. Only some short words about this topic. Encryption is essential in networking. The Internet is a inherently insecure media. You have to assume, that you don´t talk to the right person as long as you didn´t authenticated him, you have to assume, that the data will be read by someone as long you won´t encrypt the data. IPSec solves this problems. I won´t tell you that IPsec is an easy protocol. The stuff around IPSec is defined in several RFC and the documentation is rather long. The encryption itself isn´t the complex part. But you need a key to encrypt your data. And there starts the complexity. It´s absolutly essential, that this key stays secret. How do you distribute keys through an inherently unsecure transport channel. And the next problem: How do you negotiate the encryption mechanism? And how to ensure, that you talk with the right system ? Problems … problems … problems! IPsec solves this problems. IPsec isn´t a single protocol. It´s a suite of protocols consisting out Internet Security Association and Key Management Protocol, this protocol build on the protocol for Internet Key Exchange, this protocol is based on the Oakley protocol. And fhere is a whole wad of further protocols and mechanisms and algorithms to ensure secure communication. IPsec in Solaris
Okay, but now i want to give you an example to configure IPsec on Solaris. Although the matter is complex, it isn´t hard to use IPsec within Solaris. IPsec is a rather old feature in Solaris. We´ve introduced it in Solaris 8 and improved the implementation since this time. So this implementatio is now in year eight of it´s availability. Example
The task for this example is to secure all traffic between two hosts. I´ve used two VM with Solaris Express Build 78 for this configuration. (You need at least an Solaris 10 Update 4 for this tutorial. In this update the ipsecconf command was introduced making the configuration much easier) theoden has the IP number 10.211.55.200. Gandalf has the IP number 10.211.55.201. I don´t want to use manual keying, instead of this the example will use self signed certificates. Prepare the installation
At first: Obviously you have to change hostnames and ip numbers and names for certificate corresponding to your own site. We have to work on two hosts. It´s a best practice to open up two terminal windows. Get root in both of them. To keep things apart use the bash shell and modifiy the shell prompt:

# bash<br />
# PS1="[\u@\h:\w]$ "<br />
[root@gandalf:~]$

Look at the login prompt in the examples. They designate on which system you have to work on. Okay … at first you have to ensure, that the names of the systems can be resolved. It´s a good practice to put the names of the systems into the /etc/hosts:

::1     localhost       loghost<br />
127.0.0.1       localhost       loghost<br />
10.211.55.201 gandalf<br />
10.211.55.200 theoden

Okay, we don´t want manual keying or some stinking preshares keys. Thus we need to create keys. Login to gandalf and assume the root role:

[root@gandalf:~]$ ikecert certlocal -ks -m 1024 -t rsa-md5 -D "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf" -A IP=10.211.55.201<br />
Creating private key.<br />
Certificate added to database.<br />
-----BEGIN X509 CERTIFICATE-----<br />
MIICOzCCAaSgAwIBAgIFAJRpUUkwDQYJKoZIhvcNAQEEBQAwTzELMAkGA1UEBhMC<br />
[ ... some lines omitted ... ]<br />
oi4dO39J7cSnooqnekHjajn7ND7T187k+f+BVcFVbSenIzblq2P0u7FIgIjdlv0=<br />
-----END X509 CERTIFICATE-----

Do the same on the other host.

[root@theoden:~]$ ikecert certlocal -ks -m 1024 -t rsa-md5 -D "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden" -A IP=10.211.55.200<br />
Creating private key.<br />
Certificate added to database.<br />
-----BEGIN X509 CERTIFICATE-----<br />
MIICOzCCAaSgAwIBAgIFAIRuR5QwDQYJKoZIhvcNAQEEBQAwTzELMAkGA1UEBhMC<br />
[ ... some lines omitted ... ]<br />
UHJ4P6Z0dtjnToQb37HNq9YWFRguSsPQvc/Lm+S9cJCLwINVg7NOXXgnSfY3k+Q=<br />
-----END X509 CERTIFICATE-----

You need the output of this commands later, so past them to a texteditor or at a save place … Configuration of IPsec
Okay, now we have to tell both hosts to use IPsec when they talk to each other:

[root@gandalf:~]$ echo "{laddr gandalf raddr theoden} ipsec {auth_algs any encr_algs any sa shared}" >> /etc/inet/ipsecinit.conf

This translates to: When i´m speaking to theoden, i have to encrypt the data and can use any negotiated and available encryptition algorithm and any negotiated and available authentication algorithm. Such an rule is only valid on one direction. Thus we have to define the opposite direction on the other host to enable bidirectional traffic:

[root@theoden:~]$ echo "{laddr theoden raddr gandalf} ipsec {auth_algs any encr_algs any sa shared}" >> /etc/inet/ipsecinit.conf

Okay, the next configuration is file is a little bit more complex. Go into the directory /etc/inet/ike and create a file config with the following content:

<br />
cert_trust "10.211.55.200"<br />
cert_trust "10.211.55.201"
p1_xform<br />
  { auth_method preshared oakley_group 5 auth_alg sha encr_alg des }<br />
p2_pfs 5
{<br />
 label "DE-theoden to DE-gandalf"<br />
 local_id_type dn<br />
 local_id "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden"<br />
 remote_id "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf"
 local_addr  10.211.55.200<br />
 remote_addr 10.211.55.201
 p1_xform<br />
  {auth_method rsa_sig oakley_group 2 auth_alg md5 encr_alg 3des}<br />
}

This looks complex, but once you´ve understand this it´s quite easy:

cert_trust "10.211.55.200"<br />
cert_trust "10.211.55.201"

We use self-signed certificate. The certificate isn´t signed by an independent certification authority. Thus there is no automatic method to trust the certificate. You have to configure the iked explicitly to trust this certificates. This both lines tell the iked to trust the certificates with the alternate name 10.221.55.200 and 10.211.55.201. Where did this alternate names came from? You set them! Look in the command line for creating the certificate. You defined this name by using the -a switch.

label "DE-gandalf to DE-theoden"<br />
local_id_type dn<br />
local_id "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf"<br />
remote_id "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden"

Now you define an key exchange. You have to give each connection an unique name. After this you define, what part of the certificate is used to authenticate the remote system. In this example we use the distingushed name. The local system identifies itself with the certificate named C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf to a remote system, and expect a trusted certificate with the distingushed name C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden.

local_addr  10.211.55.200<br />
remote_addr 10.211.55.201

No the iked knows the ip addresses of the local and the remote host.

p1_xform<br />
  {auth_method rsa_sig oakley_group 2 auth_alg md5 encr_alg 3des}

After defining the authentication credentials, we have to define how the system should communicate. This line means: Use the certificates to authenticate the other system. The key determination protocol is based on a prime number. We use md5 as the groundlaying algorithm to authenticate and 3des for encryption. This is the part where you configure the methods for authentication and encryption. They have to be the same on both hosts, otherwise they won´t be able to negotiate to a common denominator thus you won´t be able to communicate between the both hosts at all. Now we do the same on the other system.

[root@gandalf:/etc/inet/ike]$ cd /etc/inet/ike<br />
[root@gandalf:/etc/inet/ike]$ cat conf<br />
cert_trust "10.211.55.200"<br />
cert_trust "10.211.55.201"
p1_xform<br />
  { auth_method preshared oakley_group 5 auth_alg sha encr_alg des }<br />
p2_pfs 5
{<br />
 label "DE-gandalf to DE-theoden"<br />
 local_id_type dn<br />
 local_id "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf"<br />
 remote_id "C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden"
 local_addr  10.211.55.201<br />
 remote_addr 10.211.55.200
 p1_xform<br />
  {auth_method rsa_sig oakley_group 2 auth_alg md5 encr_alg 3des}<br />
}

Obviously you have to swap the numbers for the local and remote system and you have to assign a unique label to it. Okay, we are almost done. But there is still a missing but very essential thing when you want to use certifcates. We have to distribute the certificates of the systems.

[root@gandalf:/etc/inet/ike]$ ikecert certdb -l<br />
Certificate Slot Name: 0   Key Type: rsa<br />
        (Private key in certlocal slot 0)<br />
        Subject Name: <C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf><br />
        Key Size: 1024<br />
        Public key hash: 28B08FB404268D144BE70DDD652CB874

At the beginning there is only the local key in the system. We have to import the key of the remote system. Do you remember the output beginning with -----BEGIN X509 CERTIFICATE----- and ending with -----END X509 CERTIFICATE-----? You need this output now. The next command won´t come back after you hit return. You have to paste in the key. On gandalf you paste the output of the key generation on theoden. On Theoden you paste the output of the key generation on gandalf. Let´s import the key on gandalf

[root@gandalf:/etc/inet/ike]$ ikecert certdb -a<br />
-----BEGIN X509 CERTIFICATE-----<br />
MIICOzCCAaSgAwIBAgIFAIRuR5QwDQYJKoZIhvcNAQEEBQAwTzELMAkGA1UEBhMC
UHJ4P6Z0dtjnToQb37HNq9YWFRguSsPQvc/Lm+S9cJCLwINVg7NOXXgnSfY3k+Q=<br />
-----END X509 CERTIFICATE-----<br />
[root@gandalf:/etc/inet/ike]$

After pasting, you have to hit Enter once and after this you press Ctrl-D once. Now we check for the sucessful import. You will see two certificates now.

[root@gandalf:/etc/inet/ike]$ ikecert certdb -l<br />
Certificate Slot Name: 0   Key Type: rsa<br />
        (Private key in certlocal slot 0)<br />
        Subject Name: <C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf><br />
        Key Size: 1024<br />
        Public key hash: 28B08FB404268D144BE70DDD652CB874
Certificate Slot Name: 1   Key Type: rsa<br />
        Subject Name: <C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden><br />
        Key Size: 1024<br />
        Public key hash: 76BE0809A6CBA5E06219BC4230CBB8B8

Okay, switch to theoden and import the key from gandalf on this system.

[root@theoden:/etc/inet/ike]$ ikecert certdb -l<br />
Certificate Slot Name: 0   Key Type: rsa<br />
        (Private key in certlocal slot 0)<br />
        Subject Name: <C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden><br />
        Key Size: 1024<br />
        Public key hash: 76BE0809A6CBA5E06219BC4230CBB8B8
[root@theoden:/etc/inet/ike]$ ikecert certdb -a<br />
-----BEGIN X509 CERTIFICATE-----<br />
MIICOzCCAaSgAwIBAgIFAJRpUUkwDQYJKoZIhvcNAQEEBQAwTzELMAkGA1UEBhMC
oi4dO39J7cSnooqnekHjajn7ND7T187k+f+BVcFVbSenIzblq2P0u7FIgIjdlv0=<br />
-----END X509 CERTIFICATE-----
[root@theoden:/etc/inet/ike]$ ikecert certdb -l<br />
Certificate Slot Name: 0   Key Type: rsa<br />
        (Private key in certlocal slot 0)<br />
        Subject Name: <C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=theoden><br />
        Key Size: 1024<br />
        Public key hash: 76BE0809A6CBA5E06219BC4230CBB8B8
Certificate Slot Name: 1   Key Type: rsa<br />
        Subject Name: <C=de, O=moellenkamp, OU=moellenkamp-vpn, CN=gandalf><br />
        Key Size: 1024<br />
        Public key hash: 28B08FB404268D144BE70DDD652CB874

Activate the configuration
Okay, now we have to activate this configuration on both systems:

[root@gandalf:/etc/inet/ike]$ svcadm enable ike<br />
[root@gandalf:/etc/inet/ike]$ ipsecconf -a /etc/inet/ipsecinit.conf

and

[root@theoden:/etc/inet/ike]$ svcadm enable ike<br />
[root@theoden:/etc/inet/ike]$ ipsecconf -a /etc/inet/ipsecinit.conf

Check the configuration
Login into theoden as root and start a packet sniffer:

[root@theoden:~]$ snoop host gandalf<br />
Using device ni0 (promiscuous mode)

Okay … now login to gandalf and start some pings to theoden:

[root@gandalf:~]$ ping theoden;ping theoden;ping theoden<br />
theoden is alive<br />
theoden is alive<br />
theoden is alive

Okay, theoden can speak with gandalf and vice versa. But is it encrypted? In the terminal window for theoden the following output should be printed:

 gandalf -> theoden      ESP SPI=0x1d2c0e88 Replay=4<br />
     theoden -> gandalf      ESP SPI=0x84599293 Replay=4<br />
     gandalf -> theoden      ESP SPI=0x1d2c0e88 Replay=5<br />
     theoden -> gandalf      ESP SPI=0x84599293 Replay=5<br />
     gandalf -> theoden      ESP SPI=0x1d2c0e88 Replay=6<br />
     theoden -> gandalf      ESP SPI=0x84599293 Replay=6

ESP stands for Encapsulated Security Payload. Mission accomplished. Do you want to learn more?
Documentation
System Administration Guide: IP Services » IP Security IPsec at Wikipedia
IPsec
Internet Key Exchange
Oakley Protocol
Internet Security Association and Key Management Protocol Other
An Illustrated Guide to IPsec