Cover V13, i14

Article
Figure 1

dec2004.tar

TCP/IP and Security

Arnaud Aubert

The worldwide success of the Internet rapidly made TCP/IP the most used network protocol. Despite its popularity, it lacks some important features especially regarding security. In fact, TCP/IP can neither ensure the hosts you're communicating with are the ones you think nor prevent the data from being captured. For example, passwords used in protocols like HTTP, POP3, or telnet are not usually encrypted.

The IPsec framework, ratified by the Internet Engineering Steering Group (IESG), allows defining a policy that specifies which packets you want to secure. Those treated packets are simply encapsulated in IP datagrams by applying two kinds of layers:

  • Authentication headers (AH) -- Based on integrity checksum computed using data and a private key, it ensures the host you're communicating with is the one you suppose it to be. Data integrity is fully assured, but this method cannot prevent network listeners from getting sensitive information from your authenticated traffic.
  • Encapsulating Security Payload (ESP) -- Based on encryption algorithms, this method prevents other hosts from retrieving confidential information from your network. The ESP layer can provide the same features as AH. You should therefore use ESP both for authentication and encryption to fully secure your network.

This technology is absolutely independent of the protocols used behind it to implement AH and ESP entities. Specifications exist for common algorithms such as MD5 or SHA1 for authentication and DES, 3DES, or Blowfish for encryption.

The IPsec policy defines which packets are secured. It comprises a set of rules dependent on each implementation and generally based on criteria such as IP address, port, direction, or protocol. The rule can ask for communications to be secured or not in one or both directions.

The keys used by security algorithms must be defined in a separate place called the Security Association Database (SADB). It comprises a set of security associations, which includes definitions for:

  • The type of security association (which can be either ESP or simply AH).
  • A unique 8-byte identifier called the Security Parameter Index (SPI) of the security association within the SADB. This identifier should be the same on both sides of the communication.
  • The authentication algorithm used (for AH and authenticated ESP).
  • The encryption algorithm used (only for ESP security associations).
  • Source and destination addresses concerned by this association. Note that a security association is direction dependent; thus, you need two security associations to protect communication between two hosts in both directions.

Also, the security association should include any key needed by the security algorithms. Key lengths are dependent on the algorithm and should be equal to that used at the remote side of the security association.

Applying IPsec to a Solaris/Linux Communication

Linux uses two main open source projects to implement IPsec:

  • FreeSWAN -- One of the first real complete implementations of IPsec. It is quite stable but the project recently stopped. Two other projects are continuing its development: openSWAN and strongSWAN.
  • KAME -- A joint effort of Japanese companies to provide an IPsec implementation to BSD platforms. The project has been ported to Linux since kernel 2.5.47 and back-ported to older kernels in some distributions like Red Hat Enterprise Linux. This software is used in this article for the Linux side.

In the example, I will specify an IPsec policy to secure traffic between a Solaris 9 host 192.168.1.201 and a Red Hat Enterprise Linux 3 ES host 192.168.1.203 (see Figure 1). Traffic will be secured by ESP using DES for encryption and MD5 for authentication.

Setting Up the Policy Database

The Solaris policy database is managed by the /usr/sbin/ipsecconf command. The entries are read at boot time from the configuration file /etc/inet/ipsecinit.conf. Updates to the policy can be made at runtime by parsing configuration files using the -a policyfile argument, but they won't be preserved across reboots. To secure traffic between the Solaris host and 192.168.1.203, we will ask to use ESP with any encryption or authentication algorithm to and from this Linux address. Run the following script on the Solaris host to force the use of IPsec when communicating with 192.168.1.203:

#!/usr/sbin/ipsecconf -a
{ raddr 192.168.1.203 } ipsec { encr_algs any encr_auth_algs any }
On Solaris, IPsec configuration is handled by ipsecconf. The main arguments are:

-a -- Load an IPsec configuration file.

-f -- Flush the current IPsec policies.

-l -- Display the rules currently applied by the policy.

The configuration file is a set of rules specifying which hosts should be secured with IPsec and which algorithms should be used.

The KAME implementation is managed by the setkey command. It receives instructions from either stdin using the -c argument or from a file with the -f argument. As in Solaris, updates to the policy are not preserved across reboots.

The following script will define the same policy on the Solaris endpoint:

#!/sbin/setkey -f
# Secure outgoind communications
spdadd 192.168.1.203 192.168.1.201 any -P out ipsec esp/transport//require;
# Secure ingoing communications
spdadd 192.168.1.201 192.168.1.203 any -P in ipsec esp/transport//require;
The setkey command is responsible for KAME policy and keys management. It takes these most useful arguments:

-f filename -- Load a KAME configuration file.

-DP and -FP -- Display and flush the rules currently applied.

-D and -F -- Display and flush the keys currently defined.

Spdadd instruction syntax is: spdadd src_range dst_range proto_to_secure -P in|out policy.

Using KAME, we need to add two explicit rules for both transport directions (identified by the -P in|out). In Solaris syntax, the raddr instruction implicitly activates a bi-directional security.

Setting Up the Security Association Database

Traffic should now be impossible between the two hosts, because the policy enforces security but the keys have not been defined yet. The security associations are responsible for this and are located in /etc/inet/secret/ipseckeys for Solaris. They are loaded by the ipseckey -f filename command. For readability purposes, short key length algorithms have been chosen.

Run the following script on Solaris to set up the security associations related to the previous policies:

#!/usr/sbin/ipseckey -f
add esp spi 0x10001 src 192.168.1.201 dst 192.168.1.203 \
  encralg DES encrkey 0123456789abcdef  authalg MD5 authkey \
  0123456789abcdef0123456789abcdef
add esp spi 0x10002 src 192.168.1.203 dst 192.168.1.201 \
  encralg DES encrkey fedcba9876543210
authalg MD5 authkey fedcba9876543210fedcba9876543210
On the KAME side, the setkey command manages the security association in addition to the Security Policy database (SPD). The following script will apply the keys to the already defined policy:

#!/sbin/setkey -f
add 192.168.1.2O1 192.168.1.203 esp 0x10001 -E \
  des-cbc 0x0123456789abcdef -A hmac-md5 0x \
  0123456789abcdef0123456789abcdef;
add 192.168.1.2O3á192.168.1.201 esp 0x10002 -E des-cbc \
  0xfedcba9876543210 -A hmac-md5 0x fedcba9876543210fedcba9876543210;
Notice that the 0x10001 and 0x10002 numbers are Security Parameter Indexes (SPI). They are used to identify the security association in the SADB and need to be the same on both sides of the connection. Once the keys and the policy have been configured properly, traffic is secured and the same telnet session would result in a dump like:

# tcpdump host 192.168.1.101
18:07:51.910553 test1 > test3: ESP(spi=0x00010002,seq=0x1e2) (DF)
18:07:51.910754 test3 > test1: ESP(spi=0x00010001,seq=0x191) (DF) [tos 0x10]
18:07:51.912927 test3 > test1: ESP(spi=0x00010001,seq=0x192) (DF) [tos 0x10]
18:07:51.953335 test1 > test3: ESP(spi=0x00010002,seq=0x1e3) (DF)
18:07:51.953436 test3 > test1: ESP(spi=0x00010001,seq=0x193) (DF) [tos 0x10]
18:07:52.003291 test1 > test3: ESP(spi=0x00010002,seq=0x1e4) (DF)
The IPsec framework matches the policy with security associations; the packets' data is no longer clearly visible and is fully authenticated. The sniffer shows SPIs that have been used to generate the IPsec packet. You may specify to tcpdump the keys used by the security association to view deciphered packets.

Tunneling with IPsec

IPsec can go beyond securing packets using the tunneling mode so that entire packets are encapsulated. If the entire IP datagram is encapsulated, two intranets may be securely connected through the Internet. The intranet addresses are then included in the tunneled packets so they are re-routed correctly at the end of the tunnel.

For this example, let's say that Linux is connected through the eth1 interface to the private network 172.17.0.0/16 as 172.17.0.1; whereas Solaris is connected as 172.16.0.1 to 172.16.0.0/16 through the sfe1 interface.

On Solaris, we will flush the old policy using ipsecconf -f and create a classic IP-IP tunnel. Don't forget to enable forwarding on the required network interfaces. The use of ESP with DES and MD5 for the tunnel will be specified using the encr_algs and encr_auth_algs arguments with the ifconfig command:

#!/bin/sh
ipsecconf -f
ndd -set /dev/ip ip_forwarding 0
ndd -set /dev/ip ip_strict_dst_multihoming 1
ifconfig ip.tun0 plumb
ifconfig ip.tun0 172.16.0.1 172.17.0.1 tsrc 192.168.1.201 tdst 192.168.1.203
ifconfig ip.tun0 encr_algs DES encr_auth_algs MD5
ifconfig ip.tun0 up
ndd -set /dev/ip sfe1:ip_forwarding 1
ndd -set /dev/ip ip.tun0:ip_forwarding 1
The same operations on Linux/KAME will be done using the following script:

#!/bin/sh
echo 1 > /proc/sys/net/ipv4/ip_forward
ip tunnel add mytun mode ipip remote 192.168.1.201 local 192.168.1.203
ifconfig mytun 172.17.0.1
route add -net 172.16.0.0/16 dev mytun
setkey -c << EOF
spdflush;
flush;
add 192.168.1.201 192.168.1.203 esp 0x10001 -m tunnel -E des-cbc \
  0x0123456789abcdef -A hmac-md5 0x0123456789abcdef0123456789abcdef;
add 192.168.1.203 192.168.1.201 esp 0x10002 -m tunnel -E des-cbc \
  0xfedcba9876543210 -A hmac-md5 0xfedcba9876543210fedcba9876543210;
spdadd 172.16.0.0/16 172.17.0.0/16 any -P in ipsec \
  esp/tunnel/192.168.1.201-192.168.1.203/require;
spdadd 172.17.0.0/16 172.16.0.0/16 any -P out ipsec \
  esp/tunnel/192.168.1.203-192.168.1.201/require;
EOF
In this example, the spdflush and flush instructions, respectively, flush policy and security associations directly from within the configuration file.

Note that under Linux, the security association definitions must now include the -m tunnel argument. Network 172.16.0.0/16 can now talk to 172.17.0.0/16 through the 192.168.1.0/24 network securely because all data being tunneled to and from 192.168.1.203 and 192.168.1.201 is now IPsec'd.

Automating Key Management

Another IPsec mechanism is called Internet Key Exchange (IKE). It allows automated negotiation of the way data should be encrypted between hosts. This automation includes aspects like the protocols and keys to be used, the lifetime of these keys or the way IKE should trust another host before negotiating. The IKE protocol is divided into two phases:

  • Phase 1 (a.k.a. Main Mode) -- Use public key encryption methods to create a bi-directional ISAKMP (Internet Security Association and Key Management Protocol) security association. This secured channel is later used to negotiate new keys. Multiple authentication methods can be used but we'll concentrate on using basic pre-shared keys. Notice, however, that you may also use X.509 certificates.
  • Phase 2 (a.k.a. Quick Mode) -- Use the first phase's ISAKMP to regularly change security keys by updating the SADB. Negotiated keys can be asked by dumping the SADB with setkey -D on Linux or ipseckey dump on Solaris.

We will now use a pre-shared key to re-establish the transport security system previously used. The secured connection will be the same, except we will now use triple DES and let the operating system take care of the choice and change of the security keys. These keys in fact will be randomized. We should first flush the previous policy using ipsecconf -f and SADB using ipseckey flush and ask for 3DES encryption to Solaris:

#!/usr/sbin/ipsecconf -a
{ raddr 192.168.1.203 } ipsec { encr_algs 3des encr_auth_algs md5 }
The same would be done on Linux/KAME using:

#!/sbin/setkey -f
spdflush;
spdadd 192.168.1.203 192.168.1.201 any -P out ipsec esp/transport//require;
spdadd 192.168.1.201 192.168.1.203 any -P in ipsec esp/transport//require;
Once the SPD entries have been set up again, we will ask IKE to take care of the key assignment automatically.

Configuring IKE with Solaris

Let's start by configuring the Solaris host using the /etc/inet/ike/config file, which is automatically loaded at boot time by the in.iked daemon:

{
label "Partnership with Linux/Racoon"
local_addr 192.168.1.201
remote_addr 192.168.1.203
local_id_type ip
p1_xform { auth_method preshared oakley_group 2 auth_alg md5 encr_alg 3des }
}
IKE rules are separated by brackets and identified by a label. The rules specify both local (local_addr) and remote ends (remote_addr) that should be concerned. Also, the p1_xform instruction consists in a proposal of a way to secure the commmunication. More instructions are available in the ike.config (4) man page

This IKE rule will apply between local_addr and remote_addr in both directions. The instruction named p1_xform describes a way to secure the system. The IKE transaction will result in the choice of a proposal common to both endpoints. The oakley_group instruction defines the level of encryption for the second phase. Once we've defined how the data should be protected, we must define a shared secret key.

The key length will no longer need to be specific to the algorithm used internally because real security associations will be generated by IKE. Pre-shared keys are stored on Solaris in /etc/inet/secret/ike.preshared as a set of rules identifying local and remote ends and their associated shared secret. SunOS needs the keys to be written in hexadecimal format. Set the file contents to the following in order to use the simple secret "AAAAAAAA":

{
localidtype IP
localid 192.168.1.201
remoteidtype IP
remoteid 192.168.1.203
key 4141414141414141
}
Each pre-shared key is defined within a bracket pair. The key should associate one host to another one. Localid and remoteid will be interpreted depending on localidtype and remoteidtype, which state how the host should be identified (by IP address in this example). The key field defines the secret key in hexadecimal without any leading 0x.

Running /usr/lib/inet/in.iked -f /etc/inet/ike/config will start the daemon and apply the rule defined without rebooting.

Configuring IKE with Racoon

The KAME project includes a daemon named racoon, which is responsible for the key management. The following /etc/racoon/racoon.conf file will define the same rules as on Solaris except that the rule will apply to any remote host. In this configuration, the keyword "anonymous" specifies the settings that should be applied to anyone negotiating security:

path include '/etc/racoon';
path pre_shared_key '/etc/racoon/psk.txt'

# Phase 1 - Configuration
remote anonymous
{
exchange_mode main;
proposal { encryption_algorithm 3des; hash_algorithm md5; \
  authentication_method pre_shared_key; dh_group 2; }
}

# Phase 2 - Configuration
sainfo anonymous
{
encryption_algorithm 3des ;
authentication_algorithm hmac_md5;
compression_algorithm deflate;
}
Both main (Phase 1) and quick modes (Phase 2) must be configured in the racoon.conf file. The proposal keyword behaves like p1_xform on the Solaris side. Compression_algorithm is a mandatory instruction simply specifying that packet compression (IPComp) should not be enabled.

The /etc/racoon/psk.txt will simply contain the following line. This simple secret key is the hexadecimal representation of the string "AAAAAAAA". The pre-shared keys file will be searched for the identifier of the remote peer so that its associated secret will be used:

192.168.1.101 0x4141414141414141
Starting racoon -f /etc/racoon/racoon.conf will start the daemon and apply the rule defined.

Testing Encryption

Now both racoon and in.iked have been loaded and configured properly, a simple tcpdump will show that security associations for both directions have been automatically created and indexed by SPIs that were not defined manually:

# tcpdump host 192.168.1.201
tcpdump: listening on eth0
19:39:26.127175 test1 > test3: ESP(spi=0x06db34e8,seq=0x3) (DF)
19:39:26.127284 test3 > test1: ESP(spi=0x7aa657a6,seq=0x2)

2 packets received by filter
0 packets dropped by kernel
The goal of this article was to introduce and demonstrate some of the basic yet powerful features of the IPsec framework. Many implementations of this technology do exist, and it can be sometimes difficult to make them work together. For more information on the subject, check the following references.

References

IPsec and IKE Administration Guide in Solaris System Administrator Collection -- http://docs.sun.com/db/doc/817-2694

The IETF IP Security Protocol working group Web page -- http://www.ietf.org/html.charters/ipsec-charter.html

FreeSWAN Web site -- http://www.freeswan.org

KAME Web site -- http://www.kame.net

IPsec Tools (Linux port of KAME) -- http://ipsec-tools.sourceforge.net/

Arnaud Aubert is an independent consultant and trainer working from France. He contributes regularly to IT publications. He can be reached at aaubert@magesi.com.