In this post I will present a tutorial on how to setup an IPSec connection between two Linux hosts, which are running Fedora Linux, but the major part of this howto will also apply to any RHEL based distro. For detailed information about IPSec please refer to the google's search engine. ;-)

Recently I came with the idea to encrypt the network traffic between my two computers, connected the same local area network. Since I don't trust any other devices that are connected to the same LAN, I have configured a simple IPSec tunnel and created a basic IPtables ruleset for filtering.

Btw: most of the presented steps you will have to do on both hosts.

Step 1 - Install the Openswan (both)

$ yum install openswan

Step 2 - Clean the existing databases and keys (both)

$ rm -r /etc/ipsec.d/*.db
$ rm -f /etc/ipsec.secrets

Step 3 - Create a new certificate and key databases (both)

$ certutil -N -d /etc/ipsec.d/

When prompted for a password simple press "enter" (we want passwordless keys).

Step 4 - Create RSA keys (both)

$ ipsec newhostkey --configdir /etc/ipsec.d --output /etc/ipsec.secrets

Step 5 - Edit /etc/ipsec.conf file, and uncomment the line below (both)

#include /etc/ipsec.d/*.conf

Step 6 - Do the key exchange between hosts using SSH for security/confidentiality

Use the following commands to extract each key.
Extract first host's rsa key:

$ ipsec showhostkey --left

Extract second host's rsa key:

$ ipsec showhostkey --right

Step 7 - Prepare essential configuration file

This config should be the same on both hosts. Btw: please keep the proper indentation.

$ cat > /etc/ipsec.d/twohost.conf << EOF>
conn twohost
    left={put here IP address assigned to the first host's NIC}
    leftrsasigkey={put here rsa key from the first host}
    right={put here IP address assigned to the second host's NIC}
    rightrsasigkey={put here rsa key from the second host}    

As you can see, in this cfg we specify the AES 256bit encryption algorithm with SHA1 hash function, but feel free to customize it. Also there's the diffie hellman's cipher strength - modp2048 (2048 bits long).

Step 8 - Start the ipsec service (both)

$ service ipsec start

Nfo: At this point you should make sure, that after reboot ipsec will start automatically. A RHEL way to enable service on boot is:

$ chkconfig ipsec on

Or when using systemd (Fedora):

$ systemctl enable ipsec

Now check ipsec's status

$ service ipsec status
"twohost" #8: transition from state STATE_MAIN_R0 to state STATE_MAIN_R1
"twohost" #8: STATE_MAIN_R1: sent MR1, expecting MI2
"twohost" #8: NAT-Traversal: Result using RFC 3947 (NAT-Traversal): no NAT detected
"twohost" #8: transition from state STATE_MAIN_R1 to state STATE_MAIN_R2
"twohost" #8: STATE_MAIN_R2: sent MR2, expecting MI3
"twohost" #8: Main mode peer ID is ID_IPV4_ADDR: '10.99.1.xx'
"twohost" #8: transition from state STATE_MAIN_R2 to state STATE_MAIN_R3
"twohost" #8: STATE_MAIN_R3: sent MR3, ISAKMP SA established {auth=OAKLEY_RSA_SIG cipher=aes_256 prf=oakley_sha group=modp2048}
"twohost" #7: received Delete SA payload: deleting ISAKMP State #7
packet from 10.99.1.xx:500: received and ignored empty informational notification payload

Looks like we are connected. Let's see also the IPSec policies.

$ ip xfrm policy
src 10.99.1.xx/32 dst 10.99.1.xx/32
    dir out priority 2080 ptype main
    tmpl src 10.99.1.xx dst 10.99.1.xx
        proto esp reqid 16385 mode tunnel
src 10.99.1.xx/32 dst 10.99.1.xx/32
    dir fwd priority 2080 ptype main
    tmpl src 10.99.1.xx dst 10.99.1.xx
        proto esp reqid 16385 mode tunnel
src 10.99.1.xx/32 dst 10.99.1.xx/32
    dir in priority 2080 ptype main
    tmpl src 10.99.1.xx dst 10.99.1.xx
        proto esp reqid 16385 mode tunnel

If you see similar output then it means you have properly established ipsec connection between two hosts.

Step 9 - Simple Filtering with IPTables

Now you may wonder how to allow incoming traffic only from "secured" by IPSec host. For instance, accepting incoming connections to  listening services only from that particular IPSec host. Of course Reject or Drop the rest. However, please note that in the following example Openswan's UDP ports, for establishing IPSec tunnel, will stay globally open.

Nfo: On Fedora I'm running a custom firewall rules, so disabling firewalld service was required. Perhaps you should consider the same.

$ iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
$ iptables -A INPUT -i lo -j ACCEPT
$ iptables -A INPUT -m policy --dir in --pol ipsec -j ACCEPT
$ iptables -A INPUT -m udp -p udp --dport 500 -j ACCEPT
$ iptables -A INPUT -m udp -p udp --dport 4500 -j ACCEPT
$ iptables -P INPUT DROP

To save the rules execute:

$ service iptables save

Step 10 - Enable NetworkManager-wait-online service on Fedora hosts (optional)

On Fedora hosts, when you connect to your LAN by the wireless NIC using NetworkManager, you may hit an unpleasant situation. After system's boot the ipsec's service won't be listening on WLAN interface, because it has not been configured on time by the NetworkManager daemon. To solve this enable wait online service.

systemctl enable NetworkManager-wait-online.service

More details below (Source).

This will ensure that all configured network devices are up and have an IP address assigned before boot continues. This service will time out after 90s. Enabling this service might considerably delay your boot even if the timeout is not reached.

And that would be all. Thanks for readin.

Current rating: 5


forever 4 years, 8 months ago


tnx for this tutorial, saved me ours of searching!


Link | Reply
Current rating: 5

New Comment


required (not published)