<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<article>
  <!--$Id$-->

  <articleinfo>
    <title>Shorewall and Bridged Firewalls</title>

    <authorgroup>
      <author>
        <firstname>Tom</firstname>

        <surname>Eastep</surname>
      </author>
    </authorgroup>

    <pubdate><?dbtimestamp format="Y/m/d"?></pubdate>

    <copyright>
      <year>2004</year>

      <year>2005</year>

      <year>2006</year>

      <holder>Thomas M. Eastep</holder>
    </copyright>

    <legalnotice>
      <para>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
      <quote><ulink url="GnuCopyright.htm">GNU Free Documentation
      License</ulink></quote>.</para>
    </legalnotice>
  </articleinfo>

  <caution>
    <para><emphasis role="bold">This article applies to Shorewall 3.0 and
    later. If you are running a version of Shorewall earlier than Shorewall
    3.0.0 then please see the documentation for that
    release.</emphasis></para>
  </caution>

  <section>
    <title>Background</title>

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

    <para>Some differences between routers and bridges are:</para>

    <orderedlist>
      <listitem>
        <para>Routers determine packet destination based on the destination IP
        address while bridges route traffic based on the destination MAC
        address in the ethernet frame.</para>
      </listitem>

      <listitem>
        <para>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.</para>
      </listitem>

      <listitem>
        <para>In most configurations, routers don't forward broadcast packets
        while a bridges do.</para>

        <note>
          <para>Section 4 of RFC 1812 describes the conditions under which a
          router may or must forward broadcasts.</para>
        </note>
      </listitem>
    </orderedlist>
  </section>

  <section>
    <title>Requirements</title>

    <warning>
      <para><emphasis role="bold">SUPPORT FOR BRIDGING AS DESCRIBED IN THIS
      ARTICLE MIGHT BE DISCONTINUED IN THE FUTURE.</emphasis> The underlying
      Netfilter features that Shorewall Bridge/Firewall support relies on are
      being removed and it is not certain whether Shorewall will be able to
      continue to support bridge/firewalls in the way described here.</para>

      <para>In <ulink url="NewBridge.html">another article</ulink>, I describe
      how to configure a bridge/firewall which will work with future kernel
      versions.</para>
    </warning>

    <para>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 <ulink url="SimpleBridge.html">Simple Bridge documentation</ulink> for
    details.</para>

    <para>In order to use Shorewall as a bridging firewall:</para>

    <itemizedlist>
      <listitem>
        <para>Your kernel must contain bridge support (CONFIG_BRIDGE=m or
        CONFIG_BRIDGE=y).</para>
      </listitem>

      <listitem>
        <para>Your kernel must contain bridge/netfilter integration
        (CONFIG_BRIDGE_NETFILTER=y).</para>
      </listitem>

      <listitem>
        <para>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 <ulink
        url="http://bridge.sf.net">http://bridge.sf.net</ulink>). Bering and
        Bering uCLibc users must find and install ipt_physdev.o for their
        distribution and add <quote>ipt_physdev</quote> to
        /etc/modules.</para>
      </listitem>

      <listitem>
        <para>Your iptables must contain physdev match support. iptables 1.2.9
        and later contain this support.</para>
      </listitem>

      <listitem>
        <para>You must have the bridge utilities (bridge-utils) package
        installed.</para>
      </listitem>
    </itemizedlist>
  </section>

  <section>
    <title>Application</title>

    <para>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).</para>

    <graphic fileref="images/bridge.png" />

    <para>There are a several key differences in this setup and a normal
    Shorewall configuration:</para>

    <itemizedlist>
      <listitem>
        <para>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.</para>
      </listitem>

      <listitem>
        <para>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.</para>
      </listitem>

      <listitem>
        <para><command>traceroute</command> doesn't detect the Bridge/Firewall
        as an intermediate router.</para>
      </listitem>

      <listitem>
        <para>If the router runs a DHCP server, the hosts connected to the LAN
        can use that server without having <command>dhcrelay</command> running
        on the Bridge/Firewall.</para>
      </listitem>
    </itemizedlist>

    <warning>
      <para>Inserting a bridge/firewall between a router and a set of local
      hosts only works if those local hosts form a single IP network. In the
      above diagram, all of the hosts in the loc zone are in the
      192.168.1.0/24 network. If the router is routing between several local
      networks through the same physical interface (there are multiple IP
      networks sharing the same LAN), then inserting a bridge/firewall between
      the router and the local LAN won't work.</para>
    </warning>

    <para>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 <emphasis role="bold">router</emphasis> would still be configured with
    IP addresses in 192.168.1.0/24 as shown below.<graphic
    fileref="images/bridge3.png" /></para>
  </section>

  <section>
    <title>Configuring the Bridge</title>

    <para>Configuring the bridge itself is quite simple and uses the
    <command>brctl</command> utility from the bridge-utils package. Bridge
    configuration information may be found at <ulink
    url="http://bridge.sf.net">http://bridge.sf.net</ulink>.</para>

    <para>Unfortunately, many 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
    <filename>/etc/network/interfaces</filename> file for a two-port bridge
    with a static IP address:</para>

    <blockquote>
      <programlisting>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</programlisting>
    </blockquote>

    <para>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 <link
    linkend="bridge-router">bridge/router</link>.</para>

    <important>
      <para>Get your bridge configuration working first, including bridge
      startup at boot, before you configure and start Shorewall.</para>
    </important>

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

    <blockquote>
      <programlisting>BOOTPROTO='dhcp'
REMOTE_IPADDR=''
STARTMODE='onboot'
UNIQUE='3hqH.MjuOqWfSZ+C'
WIRELESS='no'
MTU=''</programlisting>
    </blockquote>

    <para>Here's an /etc/sysconfig/network-scripts/ifcfg-br0 file for a
    <trademark>Mandriva</trademark> system:</para>

    <blockquote>
      <programlisting>DEVICE=br0
BOOTPROTO=dhcp
ONBOOT=yes</programlisting>
    </blockquote>

    <para>On both the <trademark>SUSE</trademark> and Mandriva systems, a
    separate script is required to configure the bridge itself.</para>

    <para>Here are scripts that I used on a <trademark>SUSE</trademark> 9.1
    system.</para>

    <blockquote>
      <para><filename>/etc/sysconfig/network/ifcfg-br0</filename></para>

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

      <para><filename>/etc/init.d/bridge</filename><programlisting>#!/bin/sh

################################################################################
#   Script to create a bridge
#
#     (c) 2004 - Tom Eastep (teastep@shorewall.net)
#
#   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</programlisting></para>
    </blockquote>

    <para>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.</para>

    <blockquote>
      <para><filename>/etc/sysconfig/network-scripts/ifcfg-br0:</filename></para>

      <programlisting>DEVICE=br0
TYPE=Bridge
IPADDR=192.168.50.14
NETMASK=255.255.255.0
ONBOOT=yes</programlisting>

      <para><filename>/etc/sysconfig/network-scripts/ifcfg-eth0:</filename><programlisting>DEVICE=eth0
TYPE=ETHER
BRIDGE=br0
ONBOOT=yes</programlisting><filename>/etc/sysconfig/network-scripts/ifcfg-eth1:</filename><programlisting>DEVICE=eth1
TYPE=ETHER
BRIDGE=br0
ONBOOT=yes</programlisting></para>
    </blockquote>

    <para>Florin Grad at <trademark>Mandriva</trademark> provides this script
    for configuring a bridge:</para>

    <blockquote>
      <programlisting>#!/bin/sh
# chkconfig: 2345 05 89
# description: Layer 2 Bridge
#

[ -f /etc/sysconfig/bridge ] &amp;&amp; . /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</programlisting>

      <para>The <filename>/etc/sysconfig/bridge file</filename>:</para>

      <programlisting>BRIDGE_INTERFACE=br0          #The name of your Bridge
INTERFACES="eth0 eth1"        #The physical interfaces to be bridged</programlisting>
    </blockquote>

    <para>Andrzej Szelachowski contributed the following.</para>

    <blockquote>
      <programlisting>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 </programlisting>
    </blockquote>

    <para>Joshua Schmidlkofer writes:</para>

    <blockquote>
      <programlisting>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_&lt;bridge&gt;_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" </programlisting>
    </blockquote>

    <para>Users who successfully configure bridges on other distributions,
    with static or dynamic IP addresses, are encouraged to send <ulink
    url="mailto:webmaster@shorewall.net">me</ulink> their configuration so I
    can post it here.</para>
  </section>

  <section>
    <title>Configuring Shorewall</title>

    <para>Bridging in Shorewall is enabled using the BRIDGING option in
    <filename>/etc/shorewall/shorewall.conf</filename>:</para>

    <programlisting>BRIDGING=Yes</programlisting>

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

    <programlisting>#ZONE   TYPE            OPTIONS
fw      firewall
net     ipv4
loc     ipv4
#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE</programlisting>

    <para>A conventional two-zone policy file is appropriate here —
    <filename>/etc/shorewall/policy</filename>:</para>

    <programlisting>#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</programlisting>

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

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

    <para>The zones are defined using the
    <filename>/etc/shorewall/hosts</filename> file. Assuming that the router
    is connected to <filename class="devicefile">eth0</filename> and the
    switch to <filename class="devicefile">eth1</filename>:</para>

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

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

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

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

  <section id="bridge-router">
    <title>Combination Router/Bridge</title>

    <para>A system running Shorewall doesn't have to be exclusively a bridge
    or a router -- it can act as both. Here's an example:<graphic
    fileref="images/bridge2.png" /></para>

    <para>This is basically the same setup as shown in the <ulink
    url="shorewall_setup_guide.htm">Shorewall Setup Guide</ulink> 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:</para>

    <orderedlist>
      <listitem>
        <para>The <filename>/etc/shorewall/proxyarp</filename> file is empty
        in this configuration.</para>
      </listitem>

      <listitem>
        <para>The <filename>/etc/shorewall/interfaces</filename> file is as
        follows:<programlisting>#ZONE    INTERFACE      BROADCAST     OPTIONS
-        br0            detect        routefilter
loc      eth1           detect</programlisting></para>
      </listitem>

      <listitem>
        <para>The <filename>/etc/shorewall/hosts</filename> file would
        have:</para>

        <programlisting>#ZONE    HOSTS                        OPTIONS
net      br0:eth0
dmz      br0:eth2</programlisting>
      </listitem>

      <listitem>
        <para>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.</para>
      </listitem>
    </orderedlist>
  </section>

  <section>
    <title>Limitations</title>

    <para>Bridging doesn't work with some wireless cards — see <ulink
    url="http://bridge.sf.net">http://bridge.sf.net</ulink>.</para>
  </section>

  <section>
    <title>Other Links</title>

    <itemizedlist>
      <listitem>
        <para><ulink
        url="http://wiki.buenosaireslibre.org/HowTos_2fBridgedFirewall">Here
        is an article in Spanish </ulink>detailing bridging a public and local
        network using Shorewall. This is another router/bridge
        configuration.</para>
      </listitem>
    </itemizedlist>
  </section>
</article>