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
-
http://wiki.frantech.ca/doku.php/gre_tunnel
-
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Securing_Virtual_Private_Networks.html
This is IPSec over GRE, not GRE over IPSec
Thanks for the correction.
Encapsulated Security Payload (ESP) uses Protocol 50 and Authenticated Header (AH) uses Protocol 51
Thanks for the correction.