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:
Creating the GRE tunnel interface
Now we can create the GRE tunnel interface from Host A to Host B:
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:
You should replace <HOST_A_PRIV_IP_GRE> with an unused private IP, for example:
Now it’s a simple matter of activating the GRE interface with the following command:
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:
EXAMPLE:
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:
EXAMPLE:
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.
Creating the GRE tunnel interface
Now we can create the GRE tunnel interface from Host B to Host A:
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:
You should replace <HOST_B_PRIV_IP_GRE> with an unused private IP, for example:
Now it’s a simple matter of activating the GRE interface with the following command:
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:
EXAMPLE:
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:
EXAMPLE:
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.
1
sysctl -w net.ipv4.ip_forward=1
1
ip tunnel add gre1 mode gre remote <HOST_B_IP> local <HOST_A_IP> ttl 25
1
ip addr add <HOST_A_PRIV_IP_GRE>/30 dev gre1
1
ip addr add 10.0.0.1/30 dev gre1
1
ip link set dev gre1 up
1
iptables -t nat -A POSTROUTING -s <HOST_B_PRIV_IP_GRE> ! -o gre+ -j SNAT --to-source <HOST_A_IP>
1
iptables -t nat -A POSTROUTING -s 10.0.0.2 ! -o gre+ -j SNAT --to-source 1.1.1.1
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
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
1
sysctl -w net.ipv4.ip_forward=1
1
ip tunnel add gre1 mode gre remote <HOST_A_IP> local <HOST_B_IP> ttl 225
1
ip addr add <HOST_B_PRIV_IP_GRE>/30 dev gre1
1
ip addr add 10.0.0.2/30 dev gre1
1
ip link set dev gre1 up
1
iptables -t nat -A POSTROUTING -s <HOST_B_PRIV_IP_GRE> ! -o gre+ -j SNAT --to-source <HOST_B_IP>
1
iptables -t nat -A POSTROUTING -s 10.0.0.1 ! -o gre+ -j SNAT --to-source 2.2.2.2
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
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
console.log( 'Code is Poetry' );