If you wish to add an additional layer of protection to your Linux server, then virtually placing another “in front” of it may be an option using a GRE tunnel.
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.
There are a number of reasons you may want to set up a GRE tunnel, which may include:
- DDoS Protection: If your current provider does not offer any DDoS protection, or very little, then you can set up a tunnel from another provider which does, which will filter your traffic through their protection.
- Additional IP: If your current provider does not offer additional IPs, or they are too costly, then you can set up a tunnel to utlitise IPs offered by another provider.
- Privacy: You can mask the true provider/IP address of the content you serve by setting up a tunnel through a more favourable country or provider.
For the purposes of this walkthrough, we will be seeking to utilise the DDoS protection of another provider to protect a Minecraft server, but it will equally work just as well for any game server or other services.
- Server A:
- IP Address: 1.1.1.1
- Tunnel IP Address: 10.0.0.1
- OS: Ubuntu 20.04
- DDoS Protection: The best!
- Server B – the Minecraft server:
- IP Address: 2.2.2.2
- Tunnel IP Address: 10.0.0.2
- OS: Ubuntu 20.04
- DDos Protection: None.
Of course, you would change the IP Address of each server to match your own.
Server A Configuration
To start, we must enable IP forwarding on this server. This only needs to be executed once:
# Enable IP forwarding
sudo echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sudo sysctl -p
The following must be executed on every reboot of the server:
# Bring the tunnel online
sudo ip tunnel add gre1 mode gre local 1.1.1.1 remote 2.2.2.2 ttl 255
sudo ip addr add 10.0.0.1/30 dev gre1
sudo ip link set gre1 up
# NAT configuration
iptables -t nat -A POSTROUTING -s 10.0.0.0/30 ! -o gre+ -j SNAT --to-source 1.1.1.1
# Allow data to travel between Server A and B
iptables -A FORWARD -d 10.0.0.2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# Forward application/port traffic
iptables -t nat -A PREROUTING -d 1.1.1.1 -p tcp --dport 25565 -j DNAT --to-destination 10.0.0.2
Server A now has an internal IP of 10.0.0.1 within the tunnel.
By specifying -p tcp --dport 25565
, we are only forwarding TCP traffic on port 25565. If you want to forward more services on different ports, you would execute multiple iptables -t nat
commands, changing the protocol and port as necessary.
Server B Configuration
The following must be executed on every reboot of the server:
# Bring the tunnel online
sudo ip tunnel add gre1 mode gre local 2.2.2.2 remote 1.1.1.1 ttl 255
sudo ip addr add 10.0.0.2/30 dev gre1
sudo ip link set gre1 up
# Set up the new route
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
Server B now has an internal IP of 10.0.0.2 within the tunnel.
Testing the Tunnel
We can now execute some commands on Server B to ensure data transmission within the tunnel:
root@serverb:~# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=10.6 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=10.5 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=10.6 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=10.5 ms
root@serverb:~# curl ipv4.icanhazip.com
2.2.2.2
root@serverb:~# curl ipv4.icanhazip.com --interface 10.0.0.2
1.1.1.1
Congratulations! You now have a working GRE tunnel between two Linux servers. You would now bind your Minecraft server to, or share the IP address, 1.1.1.1
instead of 2.2.2.2
and your game server now has the full DDoS protection offered by Server A.
Persistent Rules
Now that your tunnel is working, you will want to automatically set up the tunnel each time your servers reboot. To do this, we will use /etc/rc.local
as a service. This must be done on both Server A and Server B.
We must first create a new service file using the sudo nano /etc/systemd/system/rc-local.service
command and entering the following into it:
[Unit]
Description=/etc/rc.local Compatibility
ConditionPathExists=/etc/rc.local
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target
Save the contents, then we create a new rc.local
file using the sudo nano /etc/rc.local
command. Inside this, we enter the commands listed in the Configuration headers above for each respective Server:
#!/bin/bash
# Bring the tunnel online
sudo ip tunnel add gre1 mode gre local 1.1.1.1 remote 2.2.2.2 ttl 255
... other commands ...
Save the contents, then chmod
the file using the sudo chmod +x /etc/rc.local
command.
Enable the service using the sudo systemctl enable rc-local
command, and optionally reboot both servers to ensure the tunnels are started at boot time.
There may be a much better way of adding the rules persistently than the above given, and I would love to hear if you know better.