Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Linux setup GRE tunnel

profile picture
Author
Fabrizio La Rosa
Published
2019-08-20
Time to read
6 minutes reading time

Introduction

Generic Routing Encapsulation (GRE) is a tunneling protocol developed by Cisco Systems which can encapsulate a wide variety of network layer protocols inside virtual point-to-point links or point-to-multipoint links over an Internet Protocol network.

A GRE tunnel is useful in certain situations, like protecting a server without DDoS protection using another one with the protection, or to enable applications that only allow IPv4 to also accept IPv6.

Prerequisites

First of all, you must have two servers with root access. In this tutorial they will be called Server A and Server B, and will have the following characteristics:

  • Server A - the server that all the clients will connect to
    • IP: 198.51.100.1
    • GRE tunnel internal IP: 10.0.0.1
  • Server B - the server which is actually running all the applications
    • IP: 203.0.113.1
    • GRE tunnel internal IP: 10.0.0.2

Step 1 - Module loading

For setting up a GRE tunnel on Linux you must have ip_gre module loaded in your kernel. To make sure it's loaded just do:

sudo modprobe ip_gre
lsmod | grep gre

And you should see:

ip_gre                 #####  0
gre                    #####  1 ip_gre

If you see something else it's possible that your kernel does not support GRE.

To forward all the traffic in and out of the GRE tunnel we're going to use iptables and iproute2 that should be already installed in all the major linux distributions. In case they're not installed use the following command

for Debian based distros:

sudo apt install iptables iproute2

for Red Hat based distros:

sudo yum install iptables iproute2

Step 2 - Tunnel setup

First we have to set up our tunnel.

On Server A execute this code to enable ip forwarding:

sudo echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sudo sysctl -p

Now create a new networking interface which will be the one using the GRE tunnel:

sudo ip tunnel add gre1 mode gre local 198.51.100.1 remote 203.0.113.1 ttl 255
sudo ip addr add 10.0.0.1/30 dev gre1
sudo ip link set gre1 up

Then, do the same on Server B changing the IPs:

sudo ip tunnel add gre1 mode gre local 203.0.113.1 remote 198.51.100.1 ttl 255
sudo ip addr add 10.0.0.2/30 dev gre1
sudo ip link set gre1 up

Step 2.1 - Ping test

On Server A do:

ping 10.0.0.2

And on Server B do:

ping 10.0.0.1

If the ping works then the GRE tunnel is correctly set up.

Step 3 - New routes implementation

A route is required to make sure data that comes in via the GRE tunnel is handled correctly.

On Server B execute:

sudo echo '100 GRE' >> /etc/iproute2/rt_tables
sudo ip rule add from 10.0.0.0/30 table GRE
sudo ip route add default via 10.0.0.1 table GRE

Step 4 - NAT configuration

NAT is used to pass data over our GRE and out the other end.

On Server A run:

iptables -t nat -A POSTROUTING -s 10.0.0.0/30 ! -o gre+ -j SNAT --to-source 198.51.100.1

To test the outbound connection execute on Server B this commands:

for Debian based distros:

sudo apt install curl

for Red Hat based distros:

sudo yum install curl

and then:

curl http://www.cpanel.net/showip.cgi --interface 10.0.0.2

At the end you should see Server A's IP.

Step 5 - Port forwarding

On Server A run this commands to allow all the data going to and coming from Server B:

sudo iptables -A FORWARD -d 10.0.0.2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -s 10.0.0.2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

Then, we want to forward all our data from Server A to Server B.

Execute on Server A:

sudo iptables -t nat -A PREROUTING -d 198.51.100.1 -p PROTO -m PROTO --dport PORT -j DNAT --to-destination 10.0.0.2

replacing PROTO and PORT with your actual ones.

For example, to forward all the data to a Webserver (Port TCP 80) we have to run:

sudo iptables -t nat -A PREROUTING -d 198.51.100.1 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2

We must do it for each port we are using.

Step 6 - Persistence

On a server restart all the things we did will be wiped out. To make sure the GRE tunnel and everything else is going to work after a restart we have to edit the file /etc/rc.local and add all the commands we did (except for the echo ones!) before the exit 0.

Conclusions

Now, if we connect to Server A using the ports we configured (Port TCP 80 for example) we're going instead to connect to Server B without knowing it.

Note: if you use CSF to manage iptables you may have to put all the iptables commands in your /etc/csf/csfpost.sh and insert both servers' IP (also the GRE one) in your /etc/csf/csf.allow.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get 20€ free credit!

Valid until: 31 December 2024 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more