How to create a GRE tunnel between two Linux servers

Note: If you are tunneling to a server owned by OVH, you are very unlikely to have GRE support in your kernel. You should use a IPIP tunnel instead.
Prerequisites
- A VPS/Server that you wish to tunnel from (Server A)
- A VPS/Server that you wish to tunnel to (Server B)
- iptables installed on on (Linux distros normally include this)
- iproute2 (Majority of Linux Distros include this out of the box)
- A kernel with GRE support (Linux includes this by default — ip_gre kernel module)
- A list of ports you need forwarded to your destination
Tunnel Setup
First we need to set up the tunnel.
On Server A; Run these commands:
Change SERVER_A_IP to the IP of the machine you want to tunnel FROM and change SERVER_B_IP to the IP of the machine you want to tunnel TO.
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p
iptunnel add gre1 mode gre local SERVER_A_IP remote SERVER_B_IP ttl 255
ip addr add 192.168.168.1/30 dev gre0
ip link set gre1 up
On server B; run the following:
Change SERVER_A_IP to the IP of the machine you want to tunnel FROM and change SERVER_B_IP to the IP of the machine you want to tunnel TO.
iptunnel add gre1 mode gre local SERVER_B_IP remote SERVER_A_IP ttl 255
ip addr add 192.168.168.2/30 dev gre0
ip link set gre1 up
The first line of each set of commands changes what IP to use locally and which remotely. The 2nd line documents each end point. In a /30, Only 2 IP’s can be used: .1 and .2.
Test the Tunnel
On server A, you should now be able to ping 192.168.168.2
.
To confirm it is all working, test ping 192.168.168.1
from server B.
Configuring Source Routes
Source routes are required to ensure data sent in the tunnel is returned through the tunnel.
To configure these, execute the following commands on Server B.
echo '100 GRE' >> /etc/iproute2/rt_tables
ip rule add from 192.168.168.0/30 table GRE
ip route add default via 192.168.168.1 table GRE
Please note that the echo command only needs to be run once. The entry will be saved into /etc/iproute2/rt_tables until you remove it manually.
NAT Entries
NAT is used to forward the data into the tunnel and out the other end.
On Server A run the following command:
Change SERVER_A_IP to the IP of the machine you want to tunnel FROM.
iptables -t nat -A POSTROUTING -s 192.168.168.0/30 ! -o gre+ -j SNAT --to-source SERVER_A_IP
Test Outbound Connections
On Server B; run the following command to see if the tunnel is passing traffic properly:
curl http://www.cpanel.net/showip.cgi --interface 192.168.168.2
The IP shown should be that of Server A.
Forwarding Ports Over your GRE Tunnel
To keep it simple, we’ll forward all ports to server B .
Run the following commands on Server A:
Change SERVER_A_IP to the IP of the machine you want to tunnel FROM.
iptables -t nat -A PREROUTING -d SERVER_A_IP -j DNAT --to-destination 192.168.168.2
iptables -A FORWARD -d 192.168.168.2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
If you only wish to forward specific ports, you could add -p tcp --dport [PORT]
.
The first rule handles the port forwarding and the second rule makes sure that connections get NAT’d, and handled correctly.
At this point you should be able to connect to Server A’s IP and the destination port with your application and get passed through the GRE tunnel without issue.
Restarting your GRE Tunnel After Rebooting
You are able to edit /etc/rc.local with any editor and place the commands we just ran before the exit 0 at the bottom.
Credit to Mark E. for writing this article for us.
Originally published on https://docs.rawsrv.com. Our knowledgebase is updated first and more frequently than our Medium page! Follow us on Twitter to get notified when we post!