gre-tun

A GRE Tunnel Implementation for FreeBSD


GRE tunnelling

Tunnels are a method of connecting two networks together across another network. There are all kinds of tunnels out there, and you can use any protocol. For example say you have two Appletalk networks at two locations and each location is connected to the Internet. You want to connect the two networks but don't want to pay for a physical circuit between the two sites. No problem - you can have a machine at each end that takes Appletalk packets from the local network and sends them in IP packets to the machine at the other end. The machine at the other end takes the Appletalk packets out of their IP wrappers and emits them on its Ethernet. Simple, isn't it?

Generic Router Encapsulation (GRE) tunnels are defined by the Internet Engineering Task Force (IETF) in two Requests for Comments (RFCs): RFC1701 Generic Router Encapsulation, and RFC1702 Generic Routing Encapsulation over IPv4 networks. The first RFC describes the protocol in detail, and the second describes GRE encapsulation as it specifically applies to IP. One advantage of GRE over earlier protocols is that any transport protocol can be encapsulated in GRE.

Note that there are lots of tunnelling protocols. GRE is a very simple, low overhead approach - the GRE protocol itself can be expressed in as few as 8 octets. There's no real authentication or tunnel configuration parameter negotiation. If you don't have the tunnel parameters set right on each end most likely things just won't work. If you need more than this functionality you should be looking into Layer 2 Tunnelling Protocol (L2TP), which essentially implements PPP over a GRE tunnel. There's a lot more overhead, but things like authentication, automatic address allocation, encryption, etc. are availble to you.


How gre-tun works

gre-tun is a specific implementation of a subset of the GRE specification that runs on FreeBSD systems which support the tun network device. The tun device provides access to the IP stack by allowing a program to open a device /dev/tunn for read and write access. If an IP (or other protocol) address is assigned to the interface then packets sent to that address are passed to the program. Packets written by the program are emitted sourced from the appropriate address. This allows very simple programmatic access to IP functions.

gre-tun works by first opening a tunnel device, then applying the appropriate IP addresses and network mask. It also opens a raw socket to its tunnel partner. Packets sent to the tunnel IP address are handed off to the program, which encapsulates them into a GRE packet and sends them using the normal IP raw write function to the other tunnel endpoint. Packets sent by the tunnel partner are received on the raw socket, GRE information stripped off (and validated), then emitted through the tunnel device to the kernel which processes the packet just as if it was recieved on an Ethernet, PPP, or other interface.

The GRE specification provides for a number of options. These are:


How to build it

Warning
This is alpha quality code. I do not not provide any warranty or support - use it at your own risk. You can pass it along to others freely but it is not in the public domain; I retain all rights to the source code and documentation. If you pass it on to others you must do so unaltered with this document (again unaltered) included. If you make changes I'd appreciate your passing them along to me to be integrated into the official version. You'll be mentioned in the code...

First you need to get a copy. The source is here as a single C source file. Your brwoser should load the source which you can save using the File.../Save... menu commands.

To compile the program just enter the command

cc -o gre-tun gre-tun.c
Copy the executable to your favourite directory and you'll be ready to go. Note that you probably do NOT want to do something silly like make the program owned by root with the sticky bit set; then end-users will be able to set up tunnels. Not a Good Thing [tm] in most cases.

BTW, if you get it to work on another system let me know. I'd like to keep it pretty much up-to-date.


How to run it

First make sure you have tunnel support configured in your kernel. If you enter the command ifconfig -a you should see at least one interface called tunn. These interfaces are used by gre-tun. At least one must not be in the UP state.

Second make sure you have an appropriate number of tunnel devices in your /dev directory. Determine what the highest numbered tunnel device is, and enter the commands

cd /dev
./MAKEDEV tun n

Now run the command gre-tun options, where options are flags specifying how the tunnel is to be configured. Flags are:

-source
source-address
Sets the tunnel source address. This is the local address by which the tunnel will be known locally. For most applications this can be the same address as an Ethernet interface. If not specified it defaults to the value given by the -local flag.
-destination
destination-address
Sets the tunnel destination address. This is the IP address of the remote end of the tunnel. This may be the same as the address of the remote tunnels host. If not specified it defaults to the value given by the -remote flag.
-remote
remote-address
Sets the address of the host at the remote end of the tunnel. This is the address to which GRE encapsulated packets will be sent, so it must be reachable from the local tunnel endpoint. This parameter must be specified.
-local
local-address
Sets the address of the local host. This can be the same as the source address defined above. It is the address that will receive packets from the remote end. This parameter must be specified.
-tunnel
tunnel-device
The tunnel device to use. If not specified gre-tun tries to open devices starting at /dev/tun0 and working its way up until it runs out of devices or finds one not in use.
-netmask
subnet-mask
Sets the tunnel network mask. If not specified it defaults to 0xfffffff8 (255.255.255.252), which indicates a point-to-point link.
-key
key-value
Sets the authentication key. The keys at either end of the tunnel must match for packets to flow. Note that this really doesn't buy much in the way of security since the keys are transmitted in clear text. I guess it's marginally better than nothing though.
-sequence


Causes gre-tun to generate sequence numbers. This code currently doesn't work so I wouldn't turn it on if I were you. Packets received from the remote end with sequence numbers are accepted and if the numbers do not match up properly a warning is logged to the system log.
-checksum

Not yet implemented. Causes gre-tun to insert checksums in the GRE header. This protects against corrupted packets. If checksums are provided by the remote end gre-tun currently ignores them.
-help

Prints out the command line options.
-debug

Turns on debugging information. If specified gre-tun will not detach from the controlling terminal and will spit out huge volumes of information about what it's doing.

Example using a Cisco router to be the endpoint

I have two network connections at my house: one from a DSL provider with a single static IP address and one from another ISP with a block of addresses accessed via a 28.8Kbps modem. I want to continue to use the block of addresses but go through the DSL line to get better speed. That's the whole reason I wrote this (well, not the WHOLE reason but good enough for this discussion).

My DSL line terminates in a FreeBSD box that acts as a firewall and Network Address Translation (NAT) box. Behind the firewall are two networks using RFC1918 addresses: 192.168.100.0 for 100Mbps services and 192.168.10.0 for 10Mbps services. I want the block of addresses to terminate in a single host called George on the 10Mbps network; George provides all my public services. George is a FreeBSD box.

The first step is to configure George. George has an Ethernet card with address 192.168.10.40, which will be NATted by the firewall. George's public address will be 209.31.147.130, which is part of the block 209.31.147.128/28 which my dial-up ISP provides. The other end of the tunnel is a Cisco router at 209.31.144.4. I want George to default its packets through the tunnel, but of course the GRE packets have to go to the router through the DSL line. So I do the following:

  1. Establish a host route for the Cisco router through the DSL router:
    route add 209.31.144.4 192.168.10.1
  2. Establish a default route through the tunnel:
    route delete default
    route add default 209.31.144.4
  3. Bring up the tunnel:
    gre-tun -local 209.31.147.130 -remote 209.31.144.4 -destination 209.31.147.129
Ok, now that George is configured I have to go to the Cisco router and configure it. That's pretty simple; I log into it, go into configuration mode, and enter:
interface Tunnel11
tunnel mode gre
description Testing by Mike Newell
ip address 209.31.147.129 255.255.255.240
ip rip send version 2
ip rip receive version 2
tunnel source 209.31.144.4
tunnel destination 151.200.21.150
tunnel sequence-datagrams
So now I have a point-to-point connection, endpoints 209.31.147.130 (my house) and 209.31.147.129 (my ISP). Packets sent to 209.31.47.130 are routed by the Internet to my ISP where they hit the Cisco router. The Cisco then sends them back out to my firewall (151.200.21.150) which forwards them to George for processing. Works fine. Less filling.

Known Problems

There are some problems and limitations of this implmentation. The major ones that I know about are:
  1. As mentioned above GRE routing fields are not supported. I have no intention of adding support for them.
  2. Also mentioned above checksumming and sequence numbering are not implemented at this time. The program does log sequence number anomolies.
  3. There are some bugs in the debug display information. Maybe I'll fix those. Doesn't affect operation of the tunnel.
  4. Probably I can guess the local endpoint address. Maybe not. Need to think about it.
  5. GRE is an inherently insecure protocol. It provides an easily sniffiable key for validating packets but that's about it. This program also checks the source IP address of packets to try to avoid spoofed packets, but that's not much more protection. You really need to run some authentication protocol (e.g. SSH or PPP) over GRE to get better security.

Questions? Comments? Contact me at MNewell@SpottyDogs.Org.
© 1995, 2008 Michael C. Newell. All rights reserved.