Linux Networking - GRE tunnelling

Synopsis: A brief introduction of Linux GRE and GRETAP tunnels

Keywords: gre, gretap

Back To Blog HomePage


A gre tunnel is much like IPIP tunnel except that it utilizes GRE encapsulation which introduces an extra gre header between outter ip header and inner payload.
note the payload can be an IP datagram or an Ethernet frame.

In Linux, there are two types of gre tunnel. let's first look at the GRE tunnel.
1) Linux GRE L3 tunnel.
   Like we did with IPIP tunenl, we create an GRE point to point tunnel with two interfaces residing in two namespaces.
   In the following example, we reuse the topology in IP over IP tunnelling. 
     	 $sudo modprobe gre
         $sudo ip netns add netA
         $sudo ip netns add netB
         $sudo ip netns exec netA ip link add dummyA type dummy
         $sudo ip netns exec netB ip link add dummyB type dummy
         $sudo ip netns exec netA ip link set lo up
         $sudo ip netns exec netB ip link set lo up
         $sudo ip netns exec netA ip link set dummyA up
         $sudo ip netns exec netB ip link set dummyB up
         $sudo ip netns exec netA ip addr add 172.16.17.1/24 dev dummyA
         $sudo ip netns exec netB ip addr add 192.168.199.1/24 dev dummyB
         $sudo ip link add name underlayA type veth peer underlayB
         $sudo ip link set dev underlayA netns netA
         $sudo ip link set dev underlayB netns netB
         $sudo ip netns exec netA ip link set dev underlayA up
         $sudo ip netns exec netB ip link set dev underlayB up
         $sudo ip netns exec netA ip addr add 10.1.1.1/24 dev underlayA
         $sudo ip netns exec netB ip addr add 10.1.1.2/24 dev underlayB
         $sudo ip netns exec netA ip link add name greA type gre local 10.1.1.1 remote 10.1.1.2
         $sudo ip netns exec netB ip link add name greB type gre local 10.1.1.2 remote 10.1.1.1
         $sudo ip netns exec netA ip link set greA up
         $sudo ip netns exec netB ip link set greB up
         $sudo ip netns exec netA ip route add 192.168.199.0/24 nexthop dev greA
         $sudo ip netns exec netB ip route add 172.16.17.0/24 nexthop dev greB

   now we are able to capture the packets accross the tunnel:
      $sudo ip netns exec netA tcpdump -i underlayA -n 'ip'
      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
      listening on underlayA, link-type EN10MB (Ethernet), capture size 262144 bytes
      ^C04:17:26.414701 IP 10.1.1.1 > 10.1.1.2: GREv0, length 64: IP 172.16.17.1.39828 > 192.168.199.1.80: Flags [S], seq 1138993353, win 64620, options [mss 1436,sackOK,TS val 3856394034 ecr 0,nop,wscale 7], length 0
      04:17:26.414758 IP 10.1.1.2 > 10.1.1.1: GREv0, length 44: IP 192.168.199.1.80 > 172.16.17.1.39828: Flags [R.], seq 0, ack 1138993354, win 0, length 0
      04:17:27.514573 IP 10.1.1.2 > 10.1.1.1: GREv0, length 60: IP6 fe80::5efe:a01:102 > ff02::2: ICMP6, router solicitation, length 16
      04:17:37.376429 IP 10.1.1.1 > 10.1.1.2: GREv0, length 64: IP 172.16.17.1.39830 > 192.168.199.1.80: Flags [S], seq 610902698, win 64620, options [mss 1436,sackOK,TS val 3856404996 ecr 0,nop,wscale 7], length 0
      04:17:37.376473 IP 10.1.1.2 > 10.1.1.1: GREv0, length 64: IP 192.168.199.1.80 > 172.16.17.1.39830: Flags [S.], seq 2863747856, ack 610902699, win 65504, options [mss 1436,sackOK,TS val 149014169 ecr 3856404996,nop,wscale 7], length 0
      04:17:37.376500 IP 10.1.1.1 > 10.1.1.2: GREv0, length 56: IP 172.16.17.1.39830 > 192.168.199.1.80: Flags [.], ack 1, win 505, options [nop,nop,TS val 3856404996 ecr 149014169], length 0
      04:17:37.376546 IP 10.1.1.1 > 10.1.1.2: GREv0, length 196: IP 172.16.17.1.39830 > 192.168.199.1.80: Flags [P.], seq 1:141, ack 1, win 505, options [nop,nop,TS val 3856404996 ecr 149014169], length 140: HTTP: GET / HTTP/1.1
      04:17:37.376554 IP 10.1.1.2 > 10.1.1.1: GREv0, length 56: IP 192.168.199.1.80 > 172.16.17.1.39830: Flags [.], ack 141, win 511, options [nop,nop,TS val 149014169 ecr 3856404996], length 0
      04:17:37.377942 IP 10.1.1.2 > 10.1.1.1: GREv0, length 210: IP 192.168.199.1.80 > 172.16.17.1.39830: Flags [P.], seq 1:155, ack 141, win 511, options [nop,nop,TS val 149014170 ecr 3856404996], length 154: HTTP: HTTP/1.0 200 OK
      04:17:37.378017 IP 10.1.1.1 > 10.1.1.2: GREv0, length 56: IP 172.16.17.1.39830 > 192.168.199.1.80: Flags [.], ack 155, win 504, options [nop,nop,TS val 3856404997 ecr 149014170], length 0
      04:17:37.378053 IP 10.1.1.2 > 10.1.1.1: GREv0, length 587: IP 192.168.199.1.80 > 172.16.17.1.39830: Flags [P.], seq 155:686, ack 141, win 511, options [nop,nop,TS val 149014170 ecr 3856404997], length 531: HTTP
      04:17:37.378077 IP 10.1.1.1 > 10.1.1.2: GREv0, length 56: IP 172.16.17.1.39830 > 192.168.199.1.80: Flags [.], ack 686, win 501, options [nop,nop,TS val 3856404997 ecr 149014170], length 0
      04:17:37.378149 IP 10.1.1.2 > 10.1.1.1: GREv0, length 56: IP 192.168.199.1.80 > 172.16.17.1.39830: Flags [F.], seq 686, ack 141, win 511, options [nop,nop,TS val 149014170 ecr 3856404997], length 0
      04:17:37.378729 IP 10.1.1.1 > 10.1.1.2: GREv0, length 56: IP 172.16.17.1.39830 > 192.168.199.1.80: Flags [F.], seq 141, ack 687, win 501, options [nop,nop,TS val 3856404998 ecr 149014170], length 0
      04:17:37.378776 IP 10.1.1.2 > 10.1.1.1: GREv0, length 56: IP 192.168.199.1.80 > 172.16.17.1.39830: Flags [.], ack 142, win 511, options [nop,nop,TS val 149014171 ecr 3856404998], length 0 
   It's quite straightforward to know how GRE encapsulation works.
2). Linux GRE L2 tunnel
    A GRE L2 tunnel behaves like a point to point ethernet wire.
    Any Ethernet packets sent to the wire will be encapsulated using GRE format.
    Here is an example of how to use gre tap in Linux, note we directly specify an address on the tap interface:
         $sudo modprobe gre
         $sudo ip netns add netA
         $sudo ip netns add netB
         $sudo ip netns exec netA ip link set lo up
         $sudo ip netns exec netB ip link set lo up
         $sudo ip link add name underlayA type veth peer underlayB
         $sudo ip link set dev underlayA netns netA
         $sudo ip link set dev underlayB netns netB
         $sudo ip netns exec netA ip link set dev underlayA up
         $sudo ip netns exec netB ip link set dev underlayB up
         $sudo ip netns exec netA ip addr add 10.1.1.1/24 dev underlayA
         $sudo ip netns exec netB ip addr add 10.1.1.2/24 dev underlayB
         $sudo ip netns exec netA ip link add name gretapA type gretap local 10.1.1.1 remote 10.1.1.2
         $sudo ip netns exec netB ip link add name gretapB type gretap local 10.1.1.2 remote 10.1.1.1
         $sudo ip netns exec netA ip link set gretapA up
         $sudo ip netns exec netB ip link set gretapB up
         $sudo ip netns exec netA ip addr add 192.100.100.1/24 dev gretapA
         $sudo ip netns exec netB ip addr add 192.100.100.2/24 dev gretapB

    Not surprisingly, we have whole Ethernet frame as the playload, a packet is dissected below:
        Frame 1: 136 bytes on wire (1088 bits), 136 bytes captured (1088 bits)
        Ethernet II, Src: f2:59:9d:5e:f3:23 (f2:59:9d:5e:f3:23), Dst: b6:ab:c6:d5:7d:33 (b6:ab:c6:d5:7d:33)
        Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
        Generic Routing Encapsulation (Transparent Ethernet bridging)
            Flags and Version: 0x0000
            Protocol Type: Transparent Ethernet bridging (0x6558)
        Ethernet II, Src: 16:82:e0:3a:41:7e (16:82:e0:3a:41:7e), Dst: 96:dd:6c:1b:d4:45 (96:dd:6c:1b:d4:45)
            Destination: 96:dd:6c:1b:d4:45 (96:dd:6c:1b:d4:45)
            Source: 16:82:e0:3a:41:7e (16:82:e0:3a:41:7e)
            Type: IPv4 (0x0800)
        Internet Protocol Version 4, Src: 192.100.100.1, Dst: 192.100.100.2
        Internet Control Message Protocol

DONE.
REF: https://tools.ietf.org/html/rfc2784