Shorewall and Bridged Firewalls

Tom Eastep

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.

2005-02-22



Table of Contents

Background
Requirements
Application
Configuring the Bridge
Configuring Shorewall
Combination Router/Bridge
Limitations
Other Links

Background

Systems where Shorewall runs normally function as routers. In the context of the Open System Interconnect (OSI) reference model, a router operates at layer 3. Beginning with Shorewall version 2.0.1, Shorewall may also be deployed on a GNU Linux System that acts as a bridge. Bridges are layer-2 devices in the OSI model (think of a bridge as an ethernet switch).

Some differences between routers and bridges are:

  1. Routers determine packet destination based on the destination IP address while bridges route traffic based on the destination MAC address in the ethernet frame.

  2. As a consequence of the first difference, routers can be connected to more than one IP network while a bridge may be part of only a single network.

  3. A router cannot forward broadcast packets while a bridge can.

Requirements

In order to use Shorewall as a bridging firewall:

  • Your kernel must contain bridge support (CONFIG_BRIDGE=m or CONFIG_BRIDGE=y).

  • Your kernel must contain Netfilter physdev match support (CONFIG_IP_NF_MATCH_PHYSDEV=m or CONFIG_IP_NF_MATCH_PHYSDEV=y). Physdev match is standard in the 2.6 kernel series but must be patched into the 2.4 kernels (see http://bridge.sf.net). Bering and Bering uCLibc users must find and install ipt_physdev.o for their distribution and add “ipt_physdev” to /etc/modules.

  • Your iptables must contain physdev match support. iptables 1.2.9 and later contain this support.

  • You must have the bridge utilities (bridge-utils) package installed.

  • You must be running Shorewall 2.0.1 Beta 1 or later.

Note that if you need a bridge but do not need to restrict the traffic through the bridge then any version of Shorewall will work. See the Simple Bridge documentation for details.

Application

The following diagram shows a typical application of a bridge/firewall. There is already an existing router in place whose internal interface supports a network and you want to insert a firewall between the router and the systems in the local network. In the example shown, the network uses RFC 1918 addresses but that is not a requirement; the bridge would work exactly the same if public IP addresses were used (remember that the bridge doesn't deal with IP addresses).

There are a several key differences in this setup and a normal Shorewall configuration:

  • The Shorewall system (the Bridge/Firewall) has only a single IP address even though it has two ethernet interfaces! The IP address is configured on the bridge itself rather than on either of the network cards.

  • The systems connected to the LAN are configured with the router's IP address (192.168.1.254 in the above diagram) as their default gateway.

  • traceroute doesn't detect the Bridge/Firewall as an intermediate router.

  • If the router runs a DHCP server, the hosts connected to the LAN can use that server without having dhcrelay running on the Bridge/Firewall.

There are other possibilities here -- there could be a hub or switch between the router and the Bridge/Firewall and there could be other systems connected to that switch. All of the systems on the local side of the router would still be configured with IP addresses in 192.168.1.0/24 as shown below.

Configuring the Bridge

Configuring the bridge itself is quite simple and uses the brctl utility from the bridge-utils package. Bridge configuration information may be found at http://bridge.sf.net.

Unfortunately, Linux distributions don't have good bridge configuration tools and the network configuration GUIs don't detect the presence of bridge devices. Here is an excerpt from a Debian /etc/network/interfaces file for a two-port bridge with a static IP address:

auto br0
iface br0 inet static
        address 192.168.1.253
        netmask 255.255.255.0
        network 192.168.1.0
        broadcast 192.168.1.255
        pre-up /sbin/ip link set eth0 up
        pre-up /sbin/ip link set eth1 up
        pre-up /usr/sbin/brctl addbr br0
        pre-up /usr/sbin/brctl addif br0 eth0
        pre-up /usr/sbin/brctl addif br0 eth1

While it is not a requirement to give the bridge an IP address, doing so allows the bridge/firewall to access other systems and allows the bridge/firewall to be managed remotely. The bridge must also have an IP address for REJECT rules and policies to work correctly — otherwise REJECT behaves the same as DROP. It is also a requirement for bridges to have an IP address if they are part of a bridge/router.

Important

Get your bridge configuration working first, including bridge startup at boot, before you configure and start Shorewall.

The bridge may have its IP address assigned via DHCP. Here's an example of an /etc/sysconfig/network/ifcfg-br0 file from a SuSE™ system:

BOOTPROTO='dhcp'
REMOTE_IPADDR=''
STARTMODE='onboot'
UNIQUE='3hqH.MjuOqWfSZ+C'
WIRELESS='no'
MTU=''

Here's an /etc/sysconfig/network-scripts/ifcfg-br0 file for a Mandrake™ system:

DEVICE=br0
BOOTPROTO=dhcp
ONBOOT=yes

On both the SuSE and Mandrake systems, a separate script is required to configure the bridge itself.

Here are scripts that I used on a Suse™ 9.1 system.

/etc/sysconfig/network/ifcfg-br0

BOOTPROTO='dhcp'
REMOTE_IPADDR=''
STARTMODE='onboot'
UNIQUE='3hqH.MjuOqWfSZ+C'
WIRELESS='no'
MTU=''

/etc/init.d/bridge

#!/bin/sh

################################################################################
#   Script to create a bridge
#
#     (c) 2004 - Tom Eastep ([email protected])
#
#   Modify the following variables to match your configuration
#
#### BEGIN INIT INFO
# Provides:       bridge
# Required-Start: coldplug
# Required-Stop:
# Default-Start:  2 3 5
# Default-Stop:   0 1 6
# Description:    starts and stops a bridge
### END INIT INFO
#
# chkconfig: 2345 05 89
# description: GRE/IP Tunnel
#
################################################################################


PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin

INTERFACES="eth1 eth0"
BRIDGE="br0"
MODULES="tulip"

do_stop() {
    echo "Stopping Bridge $BRIDGE"
    brctl delbr $BRIDGE
    for interface in $INTERFACES; do
        ip link set $interface down
    done
}

do_start() {

      echo "Starting Bridge $BRIDGE"
      for module in $MODULES; do
          modprobe $module
      done

      sleep 5

      for interface in $INTERFACES; do
          ip link set $interface up
      done

      brctl addbr $BRIDGE

      for interface in $INTERFACES; do
          brctl addif $BRIDGE $interface
      done
}

case "$1" in
  start)
      do_start
    ;;
  stop)
      do_stop
    ;;
  restart)
      do_stop
      sleep 1
      do_start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
esac
exit 0

Axel Westerhold has contributed this example of configuring a bridge with a static IP address on a Fedora System (Core 1 and Core 2 Test 1). Note that these files also configure the bridge itself so there is no need for a separate bridge config script.

/etc/sysconfig/network-scripts/ifcfg-br0:

DEVICE=br0
TYPE=Bridge
IPADDR=192.168.50.14
NETMASK=255.255.255.0
ONBOOT=yes

/etc/sysconfig/network-scripts/ifcfg-eth0:

DEVICE=eth0
TYPE=ETHER
BRIDGE=br0
ONBOOT=yes

/etc/sysconfig/network-scripts/ifcfg-eth1:

DEVICE=eth1
TYPE=ETHER
BRIDGE=br0
ONBOOT=yes

Florin Grad at Mandrake™ provides this script for configuring a bridge:

#!/bin/sh
# chkconfig: 2345 05 89
# description: Layer 2 Bridge
#

[ -f /etc/sysconfig/bridge ] && . /etc/sysconfig/bridge

PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin

do_stop() {
    echo "Stopping Bridge"
    for i in $INTERFACES $BRIDGE_INTERFACE ; do
    	ip link set $i down
    done
    brctl delbr $BRIDGE_INTERFACE
}

do_start() {

   echo "Starting Bridge"
   for i in $INTERFACES ; do
        ip link set $i up
   done
   brctl addbr br0
   for i in $INTERFACES ; do
        ip link set $i up
        brctl addif br0 $i 
   done
   ifup $BRIDGE_INTERFACE 
}

case "$1" in
  start)
      do_start
    ;;
  stop)
      do_stop
    ;;
  restart)
      do_stop
      sleep 1
      do_start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
esac
exit 0

The /etc/sysconfig/bridge file:

BRIDGE_INTERFACE=br0          #The name of your Bridge
INTERFACES="eth0 eth1"        #The physical interfaces to be bridged

Andrzej Szelachowski contributed the following.

Here is how I configured bridge in Slackware:

1) I had to compile bridge-utils (It's not in the standard distribution)
2) I've created rc.bridge in /etc/rc.d:

#########################
#! /bin/sh

ifconfig eth0 0.0.0.0
ifconfig eth1 0.0.0.0
#ifconfig lo 127.0.0.1 #this line should be uncommented if you don't use rc.inet1

brctl addbr most

brctl addif most eth0
brctl addif most eth1

ifconfig most 192.168.1.31 netmask 255.255.255.0 up 
#route add default gw 192.168.1.1 metric 1 #this line should be uncommented if
                                           #you don't use rc.inet1
#########################

3) I made rc.brige executable and added the following line to /etc/rc.d/rc.local

/etc/rc.d/rc.bridge 

Joshua Schmidlkofer writes:

Bridge Setup for Gentoo

#install bridge-utils
emerge bridge-utils

## create a link for net.br0
cd /etc/init.d
ln -s net.eth0 net.br0

# Remove net.eth*, add net.br0 and bridge.
rc-update del net.eth0
rc-update del net.eth1
rc-update add net.br0 default
rc-update add bridge boot



/etc/conf.d/bridge:

  #bridge contains the name of each bridge you want created.
  bridge="br0"

  # bridge_<bridge>_devices contains the devices to use at bridge startup.
  bridge_br0_devices="eth0 eth1"

/etc/conf.d/net

   iface_br0="10.0.0.1     broadcast 10.0.0.255 netmask 255.255.255.0"
   #for dhcp:
   #iface_br0="dhcp"
   #comment this out if you use dhcp.
   gateway="eth0/10.0.0.1" 

Users who successfully configure bridges on other distributions, with static or dynamic IP addresses, are encouraged to send me their configuration so I can post it here.

Configuring Shorewall

Bridging in Shorewall is enabled using the BRIDGING option in /etc/shorewall/shorewall.conf:

BRIDGING=Yes

In the scenario pictured above, there would probably be two zones defined -- one for the internet and one for the local LAN so in /etc/shorewall/zones:

#ZONE   DISPLAY         COMMENTS
net     Net             Internet
loc     Local           Local networks
#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE

A conventional two-zone policy file is appropriate here — /etc/shorewall/policy:

#SOURCE     DEST        POLICY        LOG       LIMIT:BURST
loc         net         ACCEPT
net         all         DROP          info
all         all         REJECT        info
#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE

Only the bridge device itself is configured with an IP address so only that device is defined to Shorewall in /etc/shorewall/interfaces:

#ZONE    INTERFACE      BROADCAST       OPTIONS
-       br0             192.168.1.255
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE

The zones are defined using the /etc/shorewall/hosts file. Assuming that the router is connected to eth0 and the switch to eth1:

#ZONE           HOST(S)                         OPTIONS
net             br0:eth0
loc             br0:eth1
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS LINE -- DO NOT REMOVE

When Shorewall is stopped, you want to allow only local traffic through the bridge — /etc/shorewall/routestopped:

#INTERFACE      HOST(S)         OPTIONS
br0             192.168.1.0/24  routeback
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE

The /etc/shorewall/rules file from the two-interface sample is a good place to start for defining a set of firewall rules.

Combination Router/Bridge

A system running Shorewall doesn't have to be exclusively a bridge or a router -- it can act as both. Here's an example:

This is basically the same setup as shown in the Shorewall Setup Guide with the exception that the DMZ is bridged rather than using Proxy ARP. Changes in the configuration shown in the Setup Guide are as follows:

  1. The /etc/shorewall/proxyarp file is empty in this configuration.

  2. The /etc/shorewall/interfaces file is as follows:

    #ZONE    INTERFACE      BROADCAST     OPTIONS
    -        br0            detect        routefilter
    loc      eth1           detect
  3. The /etc/shorewall/hosts file would have:

    #ZONE    HOSTS                        OPTIONS
    net      br0:eth0
    dmz      br0:eth2
  4. The DMZ systems need a route to the 192.168.201.0/24 network via 192.0.2.176 to enable them to communicate with the local network.

Limitations

Bridging doesn't work with some wireless cards — see http://bridge.sf.net.

Other Links