Tunneling Between Firewalls

Consider a large department which encompasses multiple subnets in several buildings. If this department wanted to put Windows 98 and/or Windows NT clients behind the logical firewall and still do "domain login", they'd run into problems because Microsoft WINS and domain login protocols don't NAT. One solution is to put a Microsoft WINS server and Domain Controller on each subnet with a 10.x.y.z address (so clients can communicate with them directly without using NAT).

A more economical solution is to put a single WINS server and Domain Controller behind one firewall and tunnel the private (10.x.y.z) traffic between private subnets. With the tunnels in place, it appears to clients that the multiple 10.x.y.z private subnets are routed to each other (behind the firewall).

The software package recommended to create these "ipsec" tunnels is called "FreeS/WAN" (or more recently "Openswan") and below are the instructions you need to use it. (For more detail, look in "/usr/share/doc/freeswan/doc/" on your gibraltar system or see the FreeS/WAN homepage and/or the Openswan homepage. if you aren't using gibraltar). In the text below, the name "FreeS/WAN" refers to either version.

Because FreeS/WAN encrypts data it sends through tunnels, in some cases it may be necessary to use a lighter-weight, non-encrypting tunnel mechanism. If you think you may not want or can't afford encryption, see Tunneling Between Firewalls Without Encryption.

Setting Up an Encrypted IPSec Tunnel

  1. FreeS/WAN is currently known to work with Gibraltar 0.98c, 0.99.3a, 0.99.4, 0.99.5, 0.99.6a, 0.99.7a, 0.99.8a, 1.0, 1.1, 2.0, 2.1, 2.2, 2.3, 2.4.1 and 2.5. You can tell which version of gibraltar you are running by typing: "cat /etc/gibraltar_version".

  2. Type: "grep Revision /usr/local/sbin/tables" and make sure your firewall rules were generated by revision 1.70 or higher of the web-based rule generator. If not, upload and regenerate them.

  3. Generate unique host key information on each logical firewall box which is to participate in tunneling by typing (on each firewall):
        echo : RSA={ | tr = '\011' > /tmp/key
        ipsec rsasigkey --verbose --random /dev/urandom 2048 >> /tmp/key
        echo =} | tr = '\011' >> /tmp/key
    Then insert the contents of "/tmp/key" into "/etc/ipsec.secrets" in place of the ": RSA" line and any indented lines which follow it.

    Here is an example completed "/etc/ipsec.secrets file":

    # This file holds shared secrets or RSA private keys for inter-Pluto
    # authentication.  See ipsec_pluto(8) manpage, and HTML documentation.
    # RSA private key for this host, authenticating it to any other host
    # which knows the public part.  Suitable public keys, for ipsec.conf, DNS,
    # or configuration of other implementations, can be extracted conveniently
    # with "ipsec showhostkey".
    : RSA	{
    	# RSA 2048 bits   fw135   Wed Feb  5 15:39:28 2003
    	# for signatures only, UNSAFE FOR ENCRYPTION
    	#IN KEY 0x4200 4 1 AQN/5dVltWfdVltWfcd6xK...
    	# (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
    	Modulus: 0x7fe5d565b567dc77a7dc77ac4abf2c...
    	PublicExponent: 0x03
    	# everything after this point is secret
    	PrivateExponent: 0x1550f8e648f8e648e6a4be...
    	Prime1: 0xe78ad9bf5f75e25f75e2653f945e510...
    	Prime2: 0x8d6852fc7da8d705a8d705ce86e1c6d...
    	Exponent1: 0x9a5c912a3fa3ec437fec437fb83e...
    	Exponent2: 0x5e458ca853c5a853c5e4ae89af41...
    	Coefficient: 0x70e812167fc2167fc63fbb5c10...
    # do not change the indenting of that "}"

  4. Name and describe the endpoints of each of your tunnels in "/etc/ipsec.conf". That file should be identical on each of your firewall boxes. FreeS/WAN will automatically figure out, based on the contents of "/etc/ipsec.secrets", which tunnels and endpoints to create on each box. The values for "leftrsasigkey=" and "rightrsasigkey=" are found in the "#pubkey=" entry in the "/etc/ipsec.secrets" file of the respective hosts. You can extract and format it most easily by typing:
    "ipsec showhostkey --left" or "ipsec showhostkey --right".
    Note also there is a hex form which begins "0x" and a more compact form which begins "0s". Either will work.

    Here is an example /etc/ipsec.conf file with one tunnel (between and

    Unfortunately, beginning with Gibraltar 0.99.8, the characters in red below MUST be present but for older versions of Gibraltar they must NOT be present.

    version 2
    # /etc/ipsec.conf - FreeS/WAN IPSEC configuration file
    # basic configuration
    config setup
    # defaults for subsequent connection descriptions
    conn %default
    # specific tunnels
    conn sample1
            # Left gateway, subnet behind it, next hop toward right (router).
            # Right gateway, subnet behind it, next hop toward left (router).

  5. You must start (or restart) FreeS/WAN on each tunnel endpoint. Type: "ipsec setup --start" (or restart if it is already running) and ignore the bind() error which relates to an IP/V6 socket you don't have. You should see some progress gobbledygook including "ISAKMP SA established" followed by "IPsec SA established".

    NOTE: Traffic to or from a tunnel endpoint box itself doesn't go through the tunnel (see the FreeS/WAN docs for why). This means you must test the tunnel with actual clients or by forcing traffic through the tunnel with something like:     traceroute -s
    for the sample connection above.

    When you have your tunnels working, you can uncomment the line in "/etc/runlevel.conf" which starts "ipsec" (FreeS/WAN) when gibraltar is rebooted. (Remove the initial "#" to uncomment the line). Don't do this until you're sure the tunnels will start or your boot may hang. (You may want to keep a backup config floppy with ipsec commented out just in case :).

    For the record, when the sample1 tunnel above is in operation, this is what "netstat -rn" shows when run on host

    Kernel IP routing table
    Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface   U        40 0          0 eth0   U        40 0          0 ipsec0   UG       40 0          0 ipsec0   U        40 0          0 eth0         UG       40 0          0 eth0

  6. If you've run uw-setup revision 1.29 or newer, you no longer need to stop FreeS/WAN before running gui-paste.

Setting Up an IPSec Tunnel Using X.509 Certificates Instead of Host Keys

Beginning with version 0.99.5, Gibraltar systems generate self-signed X.509 certificates when you first boot them (unconfigured) which can be used instead of the host keys described above. There are both advantages and disadvantages to doing this but, for the record, here is a procedure (which may change) which seems to work.

  1. Same as #1 above except version must be 0.99.5 or newer (unless you manually generate the certificates or a future version of "uw-setup" does it for you).

  2. Same as #2 above.

  3. If present, delete the host key formatted as per step #3 above from "/etc/ipsec.secrets" and replace it with the line below:
    : RSA /etc/ipsec.d/private/gibraltarKey.pem

  4. Create "/etc/ipsec.conf" as in step #4 above except use "leftcert=cacerts/hostname.pem" in place of "leftrsasigkey=" and copy each "/etc/ipsec.d/gibraltarCert.pem" file to "/etc/ipsec.d/cacerts/hostname.pem" on all participating Gibraltar systems. Same for "rightcert".

  5. Same as #5 above.

  6. Same as #6 above.

  7. Note that the default list of files in uw-restore does not currently include X.509 certificates so you would need to arrange to restore them yourself unless/until that changes.

Tunneling Between Firewalls Without Encryption

A Logical Firewall with a 1GHz Pentium 3 can probably encrypt and tunnel somewhere in the neighborhood of 40-80 megabits/sec. If your througput needs exceed your firewall's CPU's capacity AND you are tunneling between two campus subnets (where security of the intersubnet infrastructure is not of concern), you may be interested in a lighter-weight unencrypted tunnel described below (through which a 1GHz Pentium 3 can tunnel in the neighborhood of 250 megabits/sec).

Unencrypted Tunnel Overview - (DRAFT)

Basically, to setup an unencrypted tunnel, you need to arrange to execute two commands on each end of each tunnel every time the firewall is booted:

where A.B.C.D refers to the public/routable IP address of the LFW on which the commands are executed and W.X.Y.Z refers to the public/routable IP address of the LFW at the other end of the tunnel. # is a small number (or letter) you choose arbitrarily to give each tunnel's virtual device a unique name. Note that even though there is no ipsec involved, you name the virtual network interfaces ipsec-# so the firewall rules which apply to ipsec tunnels will work without modification.

To cause the tunnel setup commands to be executed automatically when the firewall boots, you'll want to put them into an executable script named: "/usr/local/sbin/tunnel" (for example):

case "$1" in
    ip tunnel add ipsec-1 local remote mode ipip
    ifconfig ipsec-1 pointopoint netmask
    ip tunnel del ipsec-1
  *) echo Usage: $0 'start|stop' 1>&2 ;;
and add this line near the end of "/etc/runlevel.conf" (after the "arplog" line) to run them when the firewall starts:
98      -       2,3,4,5         /usr/local/sbin/tunnel

To start your tunnels manually, type: "tunnel start" and to stop them manually, type: "tunnel stop".

Corey Satten
Email -- corey @ u.washington.edu
Web -- http://staff.washington.edu/corey/
Date -- Mon Jan 28 12:27:08 PST 2008