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.