IPSec over GRE setup tutorial

I have done some searching on the internet and found little about this specific topic, hence this post.

CentOS 7 will be my first choice of server operating system. I believe the steps for other OSes are very similar. I will also include some of the generic setup steps in this tutorial. I will not talk about the concept of GRE and IPSec because you’ll find a lot of other nice articles on the internet.

In IPSec concept, the source machine is called left and the destination is called right. I also will call them these names. All actions are done with root user.

Here is the information about the 2 servers:

Information

Left:
Public IP: 1.2.3.4
GRE internal IP: 192.168.168.1

Right:
Public IP: 4.3.2.1
GRE internal IP: 192.168.168.2

Configure GRE

Configuring GRE is very straightforward. First, we need to make sure we enabled the IP forwarding function in the kernel, by applying those parameters to /etc/sysctl.conf:

net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.ip_forward = 1

sysctl -p --system to apply those rules.

Make sure you have GRE module loaded in your kernel (and when boot up). This is a shell script.

lsmod | grep ip_gre > /dev/null
if [ $? -eq 1 ]; then
    modprobe ip_gre
    echo 'ip_gre' >> /etc/modules-load.d/gre.conf # for CentOS only
fi

For CentOS users, now it’s time to write some configuration files. On left:

DEVICE=gre1
BOOTPROTO=none
ONBOOT=yes
TYPE=GRE
PEER_OUTER_IPADDR=4.3.2.1 #Right's public ip address
PEER_INNER_IPADDR=192.168.168.2 #Right's internal GRE ip
MY_INNER_IPADDR=192.168.168.1 #Left's internal GRE ip

For right server, use the same configuration structure but change the values to appropriate ones.

Finally, start those GRE tunnels:

ifup gre1

For non-CentOS users, you may add your tunnel by executing those commands on each ends:

iptunnel add gre1 mode gre local 1.2.3.4 remote 4.3.2.1_IP ttl 255
ip addr add 192.168.168.1/30 dev gre1
ip link set gre1 up

Remember to change values.

Before we test it with ping, we need to add to iptables to allow NAT between the network.

iptables -t nat -A POSTROUTING -o gre1 -j ACCEPT
iptables -A INPUT -p gre -j ACCEPT

Now we can ping from left to right or vice versa.

IPSec

Install libreswan:

yum install libreswan -y

Initialize a new NSS databse:

ipsec initnss

Enable auto start from boot.

systemctl enable ipsec

Add ports to firewall. IKE uses UDP 500, IKE NAT-Traversal uses UDP 4500, Encapsulated Security Payload (ESP) uses protocol 50 and Authenticated Header (AH) uses protocol 51.

# IKE
iptables -A INPUT -p udp -m state --state NEW -m udp --dport 500 -j ACCEPT
# NAT-T
iptables -A INPUT -p udp -m state --state NEW -m udp --dport 4500 -j ACCEPT
# ESP
iptables -A INPUT -p esp -j ACCEPT
# AH
iptables -A INPUT -p ah -j ACCEPT

Use iptables-save > /etc/sysconfig/iptables to save firewall rules.

Configuration

In this section, we are going to use RSA encryption to encrypt our tunnel.

Firstly, create key pairs on both of our servers.

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

Find our left and right key on corresponding left and right server.

 showhostkey --left # or right

There will be something like right/leftrsasigkey=0sAQOw3XLeYw3q4…., copy it.

Write those keys into /etc/ipsec/mytunnel.conf, put the file on both of the servers. The content could be the same as servers will determine itself as right or left.

conn mytunnel
    [email protected]
    left=192.168.168.1
    leftrsasigkey=0sAQOrlo+hOafUZDlCQmXFrje/oZm [...] W2n417C/4urYHQkCvuIQ==
    [email protected]
    right=192.168.168.2
    rightrsasigkey=0sAQO3fwC6nSSGgt64DWiYZzuHbc4 [...] D/v8t5YTQ==
    authby=rsasig
    # load and initiate automatically
    auto=start

Start IPSec:

systemctl start ipsec
ipsec auto --add mytunnel
ipsec auto --up mytunnel

You do not need to execute the last 2 lines every time you boot the system. It is all automatic.

Check IPSec

On the right server, we start our tcpdump.

tcpdump -n -i gre1 esp or udp port 500 or udp port 4500

From left, ping right:

09:48:42.198023 IP 192.168.168.1 > 192.168.168.2: ESP(spi=0x52f7e0f4,seq=0x4), length 132
09:48:42.198271 IP 192.168.168.2 > 192.168.168.1: ESP(spi=0x1b637a20,seq=0x4), length 132
09:48:43.198544 IP 192.168.168.1 > 192.168.168.2: ESP(spi=0x52f7e0f4,seq=0x5), length 132
09:48:43.199250 IP 192.168.168.2 > 192.168.168.1: ESP(spi=0x1b637a20,seq=0x5), length 132
09:48:44.199709 IP 192.168.168.1 > 192.168.168.2: ESP(spi=0x52f7e0f4,seq=0x6), length 132
09:48:44.200260 IP 192.168.168.2 > 192.168.168.1: ESP(spi=0x1b637a20,seq=0x6), length 132

If we captured ESP packages, then our setup is successful.

Routing

Configure our routing policy to go through GRE tunnel rather than our default gateway. Example: route all Google DNS traffic to GRE:

ip route add 8.8.0.0/16 dev gre1

You need to add the rules to /etc/rc.local if you want to have persistent routing when you reboot your server.

Reference

  1. http://wiki.frantech.ca/doku.php/gre_tunnel

  2. https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Securing_Virtual_Private_Networks.html

Join the conversation

4 Comments

  1. Encapsulated Security Payload (ESP) uses Protocol 50 and Authenticated Header (AH) uses Protocol 51

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.