In this tutorial, I want to share the steps that you need to take to configure a GRE tunnel between a Cisco device and a Linux machine.
GRE – stands for Generic Routing Encapsulation protocol. It is a tunneling protocol developed by Cisco. It can encapsulate a wide variety of network layer protocols inside a virtual point-to-point tunnel.
If you are interested in configuring a GRE tunnel on Juniper EX9200, take a look here.
This is the network diagram that I will use in my lab.

Table of Contents
Configure the Alpine-0 Linux machine
In the first step, you need to configure the Alpine-0 Linux machine. I added a hostname, an IP address to the eth0 interface and a default route.
inserthostname-here:~$ sudo hostname Alpine-0
Alpine-0:~$ sudo ip add add 10.1.1.10/24 dev eth0
Alpine-0:~$ sudo ip route add default via 10.1.1.1

Configure the IP addresses on router R1
On router R1, I will use the CIDR 10.1.1.0/24 for the LAN interface and the CIDR 100.64.10.0/30 for the WAN interface.
R1#show ip int brief | include Giga
GigabitEthernet0/0 100.64.10.1 YES NVRAM up up
GigabitEthernet0/1 10.1.1.1 YES NVRAM up up
GigabitEthernet0/2 unassigned YES NVRAM administratively down down
GigabitEthernet0/3 unassigned YES NVRAM administratively down down
R1#

Configure the GRE tunnel on router R1
The next step is to configure the tunnel interface on router R1.
You need to add an IP address for the tunnel interface. You need to specify the tunnel source and the tunnel destination. There should be reachability between the tunnel source and the tunnel destination.
R1#conf term
Enter configuration commands, one per line. End with CNTL/Z.
R1(config)#interface Tun1
R1(config-if)#ip address 192.168.100.1 255.255.255.0
R1(config-if)# tunnel source GigabitEthernet0/0
R1(config-if)# tunnel destination 100.64.10.2
R1(config-if)#tunnel mode gre
% Incomplete command.
R1(config-if)#tunnel mode gre?
gre
R1(config-if)#tunnel mode gre ?
ip over IP
ipv6 over IPv6
multipoint over IPv4 (multipoint)
R1(config-if)#tunnel mode gre ip
R1(config-if)#

Add a static route for the CIDR 172.16.10.0/24 with the next hop the GRE Tunnel Interface
Next, you need to add a static route for the CIDR 172.16.10.0/24 with the next hop set as the GRE Tunnel interface.
R1(config)#ip route 172.16.10.0 255.255.255.0 Tunnel 1
R1(config)#do show ip route static
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP
a - application route
+ - replicated route, % - next hop override, p - overrides from PfR
Gateway of last resort is not set
172.16.0.0/24 is subnetted, 1 subnets
S 172.16.10.0 [1/0] via 192.168.100.2
is directly connected, Tunnel1
R1(config)#

Check the status of the GRE Tunnel Interface
After you have configured the tunnel interface, you need to check and ensure that it is in an up status.
Router R1
R1#show ip int brief
Interface IP-Address OK? Method Status Protocol
GigabitEthernet0/0 100.64.10.1 YES NVRAM up up
GigabitEthernet0/1 10.1.1.1 YES NVRAM up up
GigabitEthernet0/2 unassigned YES NVRAM administratively down down
GigabitEthernet0/3 unassigned YES NVRAM administratively down down
Tunnel1 192.168.100.1 YES manual up up
R1#

Configure the Alpine-1 Linux machine
Now, you need to configure the Alpine-1 Linux machine which will act as a router.
Alpine-1
inserthostname-here:~$ sudo hostname Alpine-1
Alpine-1:~$ sudo ip link set dev eth1 up
Alpine-1:~$ sudo ip add add 172.16.10.1/24 dev eth1
Alpine-1:~$
Alpine-1:~$ sudo ip add add 100.64.10.2/30 dev eth0

Enable the routing on the Alpine-1 Linux machine
Your next step is to enable the routing on the Alpine-1 Linux machine. You can do this with the command sudo sysctl -w net.ipv4.ip_forward=1.
Alpine-1:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
Alpine-1:~$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
Alpine-1:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
Alpine-1:~$

Check if the GRE module is enabled on the Alpine-1 Linux machine
In order to configure GRE on a Linux machine, you need to enable the GRE module first.
You can check if the module is loaded with the command lsmod.
Alpine-1:~$ lsmod | grep gr
Alpine-1:~$
As you can see, the module is not loaded. In order to load it, run the command: sudo modprobe ip_gre.
Alpine-1:~$ sudo modprobe ip_gre
Alpine-1:~$
Alpine-1:~$
Alpine-1:~$ lsmod | grep gr
ip_gre 32768 0
ip_tunnel 36864 1 ip_gre
ipv6 598016 13 ip_gre
Alpine-1:~$

Configure the tunnel interface on the Alpine-1 Linux machine
After you have enabled the ip_gre module, you can create and configure a tunnel interface.
Alpine-1:~$ sudo ip tunnel add gre1 mode gre remote 100.64.10.1 local 100.64.10.
2 ttl 255
Alpine-1:~$ sudo ip link set gre1 up
Alpine-1:~$ sudo ip add add 192.168.100.2/24 dev gre1
Alpine-1:~$

Add a static route for the CIDR 10.1.1.0/24 with the next hop the GRE Tunnel Interface
Alpine-1:~$ sudo ip route add 10.1.1.0/24 via 192.168.100.2 dev gre1
Alpine-1:~$

Check the routing table on the Alpine-1 Linux machine
Next you need to check the routing table. You need to confirm that the right routes are in place and you are able to reach the LAN side of router R1.
Alpine-1:~$ netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
10.1.1.0 192.168.100.2 255.255.255.0 UG 0 0 0 gre1
100.64.10.0 0.0.0.0 255.255.255.252 U 0 0 0 eth0
172.16.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 gre1
Alpine-1:~$

Configure the Ubuntu machine
Finally, you need to configure the Ubuntu machine. On the Ubuntu machine, you need to configure the hostname, an IP address and add a default route which points to the Alpine-1 Linux machine. The Ubuntu machine is connected to the Alpine-1 Linux machine which acts as a router in our case.
cisco@inserthostname-here:~$ sudo hostname Ubuntu
cisco@inserthostname-here:~$ sudo ip add add 172.16.10.10/24 dev ens2
cisco@inserthostname-here:~$ sudo ip route add default via 172.16.10.1
cisco@inserthostname-here:~$

Test the connectivity between the Ubuntu machine and the Alpine-0 Linux VM
The last step is to check the connectivity between the end hosts: the Ubuntu machine and the Linux Alpine VM.
cisco@Ubuntu:~$ ping -c 4 10.1.1.10
PING 10.1.1.10 (10.1.1.10) 56(84) bytes of data.
64 bytes from 10.1.1.10: icmp_seq=1 ttl=62 time=34.9 ms
64 bytes from 10.1.1.10: icmp_seq=2 ttl=62 time=8.09 ms
64 bytes from 10.1.1.10: icmp_seq=3 ttl=62 time=4.76 ms
64 bytes from 10.1.1.10: icmp_seq=4 ttl=62 time=7.26 ms
--- 10.1.1.10 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 4.759/13.757/34.924/12.282 ms
cisco@Ubuntu:~$

Confirm that the traffic was encapsulated and sent through the GRE tunnel interface
Now, let’s confirm that the traffic was encapsulated and sent through the GRE tunnel interface. I took some packet captures on the link between the router R1 and the Alpine-1 Linux machine. As you can see in the below screenshot, you have the confirmation that the traffic was encapsulated and sent trough the GRE tunnel interface.

That’s it! You have learned how to configure a GRE tunnel between Cisco IOS and Linux. If you found this blog post helpful, please like and subscribe for more Cisco networking tutorials. Thank you for reading it!

There could be a catch with Ubuntu GRE endpoints, not sure if it applies for Alpine though:
https://serverfault.com/questions/475503/rp-filter-and-linux-tunneling
Thank you, Iaroslav! I did not know about “Reverse Path Filtering”. I did not face any issues because of it. I was able to send and receive traffic without any problem. I assume the “Reverse Path Filtering” is already disabled.