This time I want to gather some info about IPsec VPN and show how to build a "Pre Shered Key" IPsec tunnel between McAfee firewall and linux CentOS 6.5 server with openswan.

Please don't look for any info about McAfee configs. Linux config only.

1. Introduction

1.1 What is IPsec

Internet Protocol Security (IPsec) is a open standard suite of protocols used to authenticate and encrypt IP Packets in a connection with assurance of data integrity and confidentiality.

IPsec allows us to create a secure virtual communication over a untrusted networks (such as the internet) to allow LAN-to-LAN communication.
We can use IPsec in several ways (host-to-host, host-to-network) but I think the most common type is network-to-network.

1.2 IKE

Internet Key Exchange is the protocol used to set up a security association (SA) in the IPsec protocol.

The IKE protocol uses UDP packets, usually on port 500, and generally requires 4-6 packets with 2-3 turn-around times to create an SA on both sides.

There are two versions of IKE protocol:

  • IKEv1 - it has some issues related to NAT, ESP and Denial of service attacs

  • IKEv2 - it has a set of improvements that are fixing issues from v1 and some other extensions

IKE consists of two phases:

  • phase 1 - is to establish a secure authenticated communication channel by using the Diffie–Hellman key exchange algorithm to generate a shared secret key to encrypt further IKE communications. IKE SA will be completed here.

  • phase 2 - the IKE peers use the secure channel established in Phase 1 to negotiate Security Associations.

phase 2 is already expecting the key information but it comes FROM phase 1.

For more info please visit :
http://en.wikipedia.org/wiki/Internet_Key_Exchange

1.3 AH and ESP

"Authentication Header" (AH) and "Encapsulating Security Payload" (ESP) are the two main level protocols used by IPsec, and they authenticate (AH) and encrypt+authenticate (ESP) the data flowing over that connection.

1.4 tunnel and transport mode

In IPsec there are two primary modes a connection can have:

  • transport mode - secures a point to point connection(only the TCP/UDP payload is encrypted)

  • tunnel mode - secures subnet to subnet connections(IP packet with header information is encapsulated and encrypted)

2. Design

As you can see, the design is pretty simpple.

On the left side, there is Linux CentOS 6.5 server with Openswan U2.6.32/K2.6.32-431.el6.x86_64 (netkey) installed from the repo. On the right side there is a McAfee firewall.

We want to establish a connection between two local subnets on each side. So we want to have secure connectivity between 192.168.1.0/24 and 10.0.0.0/24.

3. Example Configuration

In the table below you can find all informations related to the openswan ipsec configuration file.

|----------------------------------|----------------|
| Authentication Method            | Pre Shared Key |
| Phase 1 Encryption Scheme        | IKE            |
| Phase 1 DH Group                 | 5 (1536 bits)  |
| Phase 1 Encryption Algorithm     | AES256         |
| Phase 1 Hashing Algorithm        | SHA1           |
| Phase 1 Lifetime                 | 86400s         |
| Main or Aggressive mode          | main mode      |
| Phase 2 Encapsulation            | ESP            |
| Phase 2 Encryption Algorithm     | AES256         |
| Phase 2 Authentication Algorythm | MD5            |
| Phase 2 Perfect Forward Secret   | YES            |
| Phase 2 Lifetime                 | 86400s         |
| Phase 2 DH Group                 | 2 (1024 bits)  |
| NAT-T                            | yes            |
| DPD                              | yes            |

All you can find here will be placed in the config files.

4. Instalation and initial config

So lets install all nessesery software and tools

# yum install openswan tcpdump 

There are two config files:

/etc/ipsec.conf

In this file, you will find two main sections. Configuration setup section(starts with config setup) and connection section (starts with conn example).

version 2.0   

config setup
        interfaces=%defaultroute
        protostack=netkey
        nat_traversal=yes
        klipsdebug=none
        virtual_private=%v4:10.1.0.0/24,v4%:172.25.1.0/24
        plutodebug="all crypt"
        plutostderrlog=/var/log/pluto.log
        uniqueids=yes

conn example
        forceencaps=yes
        dpddelay=30         
        dpdtimeout=120         
        dpdaction=restart_by_peer
        type=tunnel  
        aggrmode=no   


        left=x.x.x.x 
        leftid=x.x.x.x 
        leftsubnet=192.168.1.0/24
        leftnexthop=%defaultroute 

        right=y.y.y.y                         
        rightid=y.y.y.y
        rightsubnets=10.0.0.0/24
        rightnexthop=%defaultroute

        auto=start                                         
        authby=secret

       #phase 1 encryption-hash-dfgroup
        keyexchange=ike
        ike=aes256-sha1-modp1536
        keylife=86400s

        #phase 2 encryption-authentication;dhgroup
        phase2=esp
        phase2alg=3des-md5;modp1024
        ikelifetime=86400s
        pfs=yes

/etc/ipsec.secrets

PUB_IP_LEFT PUB_IP_RIGHT : PSK "PreSheredKey"

We have to define a set of public IP addresses for each side and a PSK that those thwo sides will be sharing (for dynamic ip you can use %any as PUB_IP_*)

/etc/sysctl.conf

net.ipv4.conf./*/.secure_redirects = 0
net.ipv4.conf./*/.send_redirects = 0
net.ipv4.conf./*/.accept_redirects = 0

Where * is for all interfaces in the system.

Now to verify the configuration

[root@linux ~]# ipsec verify
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path                  [OK]
Linux Openswan U2.6.32/K2.6.32-358.el6.x86_64 (netkey)
Checking for IPsec support in kernel             [OK]
SAref kernel support                             [N/A]
NETKEY:  Testing for disabled ICMP send_redirects [OK]
NETKEY detected, testing for disabled ICMP accept_redirects                                 [OK]
Testing against enforced SElinux mode            [OK]
Checking that pluto is running                   [OK]
 Pluto listening for IKE on udp 500              [OK]
 Pluto listening for NAT-T on udp 4500           [OK]
Two or more ifce found, checking IP forwarding   [OK]
Checking NAT and MASQUERADEing                   [OK]
Checking for 'ip' command                        [OK]
Checking /bin/sh is not /bin/dash           [WARNING]
Checking for 'iptables' command                  [OK]

When configurations of both sides have the same config with same proposals and ciphers you can be sure it will work :)

Restart openswan and check the status.

[root@linux]# /etc/init.d/ipsec status
IPsec running  - pluto pid: 21755
pluto pid 21755
1 tunnels up
some eroutes exist
[root@linux]# ipsec auto status

000 "example/0x1": 192.168.1.0/24===x.x.x.x<x.x.x.x>[x.x.x.x,+S=C]---.......---y.y.y.y<y.y.y.y>[+S=C]===10.0.0.0/24; erouted; eroute owner: #4
....
000 #4: "example/0x1":500 STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 67744s; newest IPSEC; eroute owner; isakmp#3; idle; import:admin initiate
000 #4: "example/0x1" esp.3ea39cc@y.y.y.y esp.dae57278@x.x.x.x tun.0@y.y.y.y tun.0@x.x.x.x ref=0 refhim=4294901761
000 #3: "example/0x1":500 STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 67753s; newest ISAKMP; lastdpd=3s(seq in:0 out:0); idle; import:admin initiate

The ipsec auto status command together with pluto logfile (/var/log/pluto.log) give us a good way to troubleshoot.

Last line entry : "500 STATE_MAIN_I4" is telling us that the tunnel is established.

ipsec ports and iptables

Basically, the thing is to allow IPsec packets (IKE on UDP port 500 plus ESP, protocol 50) incoming, if the destination address is your gateway (and optionally, only from known senders)
outgoing, with the from address of your gateway (and optionally, only to known receivers)

A simple set of rules

# allow IPsec
# IKE negotiations
iptables -A INPUT -p udp --sport 500 --dport 500 -j ACCEPT
iptables -A OUTPUT -p udp --sport 500 --dport 500 -j ACCEPT

# ESP encrypton and authentication
iptables -A INPUT  -p 50 -j ACCEPT
iptables -A OUTPUT -p 50 -j ACCEPT
# uncomment for AH authentication header
# iptables -A INPUT  -p 51 -j ACCEPT
# iptables -A OUTPUT -p 51 -j ACCEPT

# when nat-t enabled
iptables -A INPUT  -p 4500 -j ACCEPT
iptables -A OUTPUT -p 4500 -j ACCEPT

HINT!
If you have a MASQUERADE on public interface(default route), you have to exclude the remote local subnets from it.

iptables -t nat -A POSTROUTING -d 10.0.0.0/24 -j RETURN
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE