Tunnels

A tunnel is simply a means of packets being wrapped up and sent within another packet to another FireBrick, and then unwrapped and sent on its way. Tunnels are used for many purposes, but mainly to allow private network addresses to be carried between two internet connected FireBricks allowing a large virtual private network (VPN) to be established.

In filtering, etc, an interface of tunnel refers to any tunnel. Routing allows a specific tunnel to be selected as the destination for specific traffic.

Where a tunnel goes

A tunnel is defined with a name, and an IP address. It also has a reference which is the number of the tunnel at the other end. Both ends must define the tunnel, and it works both ways.

Packets sent to the tunnel by the routing rules are wrapped up and sent to the specified IP address.

What protocol tunnels use

Once wrapped up, the packet is sent using a UDP port 1 packet. This allows it to be set up on other firewalls and routers to allow this packet through to the FireBrick at the far end. UDP has been chosen because it will work with a wide variety of routers, filters, firewalls, and internet providers. Some internet providers may filter traffic to or from UDP port 1 - so such filters will need to be disabled.

IP Security

A FireBrick will only accept traffic on a tunnel if it is from the specified IP address (see dynamic addresses below). This provides some degree of security, and allows a convenient and fast tunnel to be set up between two know and trusted IP addresses.

Authentication

If specified, a secret is used on all packets. This slows the packets down slightly, but ensures that the packet is not changed, and is from the correct origin. The secret is used to construct an MD5 encryption check pattern (signature) on the packet. Any change or incorrect secret key and the packet will not be accepted.

Note however that contents of the packets going via a tunnel are not hidden.

Dynamic addresses

One end of a tunnel can have the IP left blank. This allows dynamic tunnels. In such cases it is recommended that secrets are used to ensure the authenticity of the packets received. Once a packet is received, replies are sent to the last IP and port from which they came.

This is specifically to allow for traffic originating from behind address translating (NAT) routers and internet services, and is why UDP was chosen as a common translatable protocol. This works best when data is always initiated from the dynamic end, such that replies will come back through the translation correctly. In such cases it is usually sensible to run keep-alives to ensure the NAT router does not drop the link (see below).

Fragments / MTU

Wrapping up your packet in another packet makes it bigger, and there is a limit to the size of packets that can be handled by ethernet (about 1500 bytes). This means that if a large packet is sent, then it will get too big when wrapped up.

The FireBrick handles this by splitting large packets in to small pieces (about 500 bytes each) and sending these pieces to the other FireBrick where they are put back together and continue as a single packet. This is not the same as IP fragmentation. This system has the disadvantage that if one piece is dropped, then the whole packet is dropped, so it is not that efficient. It also has extra overhead as each packet has an authentication signature and IP and UDP headers.

You can control some of the tunnel settings (MTU and don't segment ) per tunnel and separately for each end of a tunnel. The MTU is the maximum size of the outgoing tunnel packet. This is, by default, 576, but can be set as high as 1500. A packet size of 576 should never be broken in to smaller bits on the way. To make most efficient use of a link, you can set this higher to reduce the chance of packets being broken up. The two ends do not need to have the same setting. It can also be used where the network in between has optimal packet sizes - for example ADSL carries large 1500 byte packets in two parts and puts them back together itself, so setting an MTU lower (say 1450) will ensure tunnel packets are not slowed down further in transit.

If your computers can handle "path MTU discovery", then you can also select don't segment. This causes large packets to be discarded and an error message to be sent back to the sending computer telling it to send things in smaller chunks. This does not work on all computers, but where it does, it will ensure that packets are not broken up unnecessarily. This does work and has been tested with Linux 2.4 kernels. If you use this feature, then you will need to set an MTU of more than 576, as the MTU reported in the ICMP error will be the size before the packet is wrapped up and so less than 576. Most computers will not accept an MTU of less than 576 and will still use 576 as the maximum packet size. When using don't segment set the MTU to at least 606 if you are not using a secret, or at least 622 if you are not.

Keep Alives

A tunnel has a state of being up or down. The tunnel is up if it has received any valid tunnel packets from the far end in the last 5 seconds. You can mark a tunnel to send keep-alive packets. These ensure that something (data or a keep-alive) is sent at least every second, and so the tunnel stays up. This is particularly useful for ensuring any router or link in between stays in operation. If keep-alives are being sent then keep-alives are automatically sent back in the same way. Where keep-alives are sent, one is sent at least every 10 seconds. The keep-alives also advise if the far end can see data (if it is up), and this allows you catch the situation where both ends are sending data but one end is not receiving it. You can also mark a tunnel as expecting data regularly, such that if it stops receiving it will log the tunnel as having gone down and also cancel any dynamic IP address/port in use.

A typical situation would have a dynamic linked unit sending keep alives and the other end expecting them.

Technical Details

The tunnelling protocol uses UDP port 1 packets, with one of two packet formats (single and multi-segment). In each format the first byte in the UDP payload is of the form SFPPVVV where S indicates the packet is signed, F indicates the last segment, PP indicates the part (0, 1 or 2) and VVVV is the version (2). The second byte is a tunnel reference - which tunnel at the far end to use, and starts from 1.

For signed packets, a 16 byte MD5 signature is at the end of the packet. This is a signature of the whole UDP payload up to this signature, followed by the secret. The signature covers the UDP payload only so does not include IP or port numbers as they could change in transit via NAT, etc.

For packets that will fit in the sending MTU, the packet is sent in one go. In this case the tunnel reference is followed by the data in the packet, and then 30 bytes (before any MD5 signature) of header data. To reassemble the packet, simply move 30 bytes from the end to the start of the packet. This is a light weight tunnelling system which does not involve moving much data in the packet (only 30 bytes). These packets have F=1 (final) and PP=0 (first part).

For packets that will not fit, then the next two bytes after the tunnel reference are a cycling packet reference. Then there are up to 512 bytes of data. The packet may be in 2 parts (F=0/PP=0 and F=1/PP=1) or 3 parts (F=0/PP=0, F=0/PP=1, and F=1/PP=2) all with the same packet reference. All but the final packet are exactly 512 bytes. This is not as efficient because data has to be moved in the packet, and the 2 or 3 parts have to be reassembled. All segments in a packet are expected to arrive within 2 seconds.

For keep alive pakcets, F=0/PP=3 and one byte follows the tunnel refernce with flags XXXXXSU1. U mean the tunnel is up, and S means that keep alive sending is enabled in the config and so replies should be sent.

Debug level logging on the FireBrick will report if there are any unexpected tunnel packets received, etc.