How to set up and configure a Linux GRE tunnel

This guide will walk through the setup and configuration of a GRE tunnel between two Linux hosts. The two Linux hosts are running Ubuntu 22.04 LTS.

What is a GRE tunnel in networking?
GRE (Generic Routing Encapsulation) tunnels encapsulate network packets inside new network packets. A virtual link is established between two hosts, allowing the hosts to communicate as if they were directly connected. The Cisco-developed tunneling protocol can encapsulate most protocol packet types.

Is a GRE tunnel encrypted?

Though a GRE tunnel functions similarly to a VPN, packets traveling inside a GRE tunnel are not encrypted but are instead encapsulated inside a GRE header. You must configure IPSec separately if you want to maintain data confidentiality.

How to set up and configure a GRE tunnel
Setting up a GRE tunnel naturally requires work on both hosts. You will need to create a tunnel interface on each, set up firewall rules, and create routing tables. For clarity, we’ll name one host “Host A” and the other “Host B”.

GRE tunnel setup on Host A
Enabling IP forwarding

The first step is to enable IP port forwarding on our host. Without this the GRE tunnel will not work. This is possible with a single command:

1

sysctl -w net.ipv4.ip_forward=1 Creating the GRE tunnel interface

Now we can create the GRE tunnel interface from Host A to Host B:

1
ip tunnel add gre1 mode gre remote <HOST_B_IP> local <HOST_A_IP> ttl 25
Naturally, you should replace <Host_B_IP> with the IP address of your target server and <Host_A_IP> with the IP address of the machine you are currently connected to.

Next, we need to assign an IP address to the GRE interface on our host:

1
ip addr add <HOST_A_PRIV_IP_GRE>/30 dev gre1
You should replace <HOST_A_PRIV_IP_GRE> with an unused private IP, for example:

1
ip addr add 10.0.0.1/30 dev gre1
Now it’s a simple matter of activating the GRE interface with the following command:

1
ip link set dev gre1 up
Setting up a firewall rule for source NAT
We’ll now add a firewall rule to perform source NAT. This will translate the source IP address of packets leaving our GRE interface into public routable addresses:

1
iptables -t nat -A POSTROUTING -s <HOST_B_PRIV_IP_GRE> ! -o gre+ -j SNAT --to-source <HOST_A_IP>
EXAMPLE:

1
iptables -t nat -A POSTROUTING -s 10.0.0.2 ! -o gre+ -j SNAT --to-source 1.1.1.1
Creating routing table rules for the GRE tunnel interface
Finally, we can add a custom routing table for the GRE tunnel that will route traffic from the GRE tunnel’s source IP through the GRE table:

1
2
3
echo '100 GRE' >> /etc/iproute2/rt_tables
ip rule add from <HOST_A_PRIV_IP_GRE>/32 table GRE
ip route add default via <HOST_B_PRIV_IP_GRE> table GRE
EXAMPLE:

1
2
3
echo '100 GRE' >> /etc/iproute2/rt_tables
ip rule add from 10.0.0.1/32 table GRE
ip route add default via 10.0.0.2 table GRE
GRE tunnel setup on Host B
For host B, the setup is the same, except of course that we must use flip the IP addresses and use a different private IP.

Enabling IP forwarding

We can set up IP forwarding on Host B with the same command as Host A.

1
sysctl -w net.ipv4.ip_forward=1
Creating the GRE tunnel interface
Now we can create the GRE tunnel interface from Host B to Host A:

1
ip tunnel add gre1 mode gre remote <HOST_A_IP> local <HOST_B_IP> ttl 225
You should replace <Host_A_IP> with the IP address of your first server and <Host_B_IP> with the IP address of the machine you are currently connected to.

Next, we need to assign an IP address to the GRE interface on our host:

1
ip addr add <HOST_B_PRIV_IP_GRE>/30 dev gre1
You should replace <HOST_B_PRIV_IP_GRE> with an unused private IP, for example:

1
ip addr add 10.0.0.2/30 dev gre1
Now it’s a simple matter of activating the GRE interface with the following command:

1
ip link set dev gre1 up
Setting up a firewall rule for source NAT
We’ll now add a firewall rule to perform source NAT. This will translate the source IP address of packets leaving our GRE interface into public routable addresses:

1
iptables -t nat -A POSTROUTING -s <HOST_B_PRIV_IP_GRE> ! -o gre+ -j SNAT --to-source <HOST_B_IP>
EXAMPLE:

1
iptables -t nat -A POSTROUTING -s 10.0.0.1 ! -o gre+ -j SNAT --to-source 2.2.2.2
Creating routing table rules for the GRE tunnel interface
Finally, we can add a custom routing table for the GRE tunnel that will route traffic from the GRE tunnel’s source IP through the GRE table:

1
2
3
echo '100 GRE' >> /etc/iproute2/rt_tables
ip rule add from <HOST_B_PRIV_IP_GRE>/32 table GRE
ip route add default via <HOST_A_PRIV_IP_GRE> table GRE
EXAMPLE:

1
2
3
echo '100 GRE' >> /etc/iproute2/rt_tables
ip rule add from 10.0.0.2/32 table GRE
ip route add default via 10.0.0.1 table GRE
That’s it! Your GRE tunnel should now be working. Remember, do not send any sensitive data via the tunnel without first setting up IPSec.

Credits: https://gratisvps.net/blog/how-to-set-up-and-configure-a-linux-gre-tunnel-2/