# Gentoo as inline network protocol analyzer.

## WhiteHat237

Hi there.

I'm trying to place a laptop system running gentoo with two Ethernet interfaces between another windows laptop and the actual network hardware to act as an inline network protocol analyzer, configured to capture packets sent from the windows laptop to the network.  Basically I'd like to create a portable network sniffer that I can place between hosts anywhere for network troubleshooting.

I have all the basics in place.  Kernel has IP masquerading support, iptables NAT support, etc.  Here are the relevant kernel modules that are loaded:

iptable_filter 

ipt_MASQUERADE

iptable_nat

ip_nat

ip_tables

xt_conntrack

x_tables

I only have one iptables rule:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

/proc/sys/net/ipv4/ip_forward contains 1 and /etc/sysctl.conf has the following entries uncommented.

net.ipv4.ip_forward = 1

net.ipv4.conf.default.rp_filter = 1

And here's a snippet from /etc/conf.d/net

```
config_eth0=( "dhcp" )
```

The card actually picks up the following from DHCP.  (192.168.1.147, netmask 255.255.255.0 default GW 192.168.0.1)

```
config_eth1=( "192.168.1.250 netmask 255.255.255.0 brd 192.168.1.255" )
```

In this scenario eth0 is attached to the network infrastructure and eth1 is attached to the windows test laptop

If I manually configure the windows networking settings and give the windows test laptop an address (192.168.1.251 netmask 255.255.255.0 gateway 192.168.1.250, then it works and it can talk through the gentoo laptop and see all hosts on the network, get out to the net, etc.  At this point I can use wireshark to capture packets on either interface, and things work fine, however, if I configure the windows laptop to use DHCP, it can never get an IP address.  I would like to be able to do this with out having to modify the configuration on the windows laptop.

When I don't manually configure the windows network settings and let it try to automatically configure itself, it tries to obtain an IP address and it sends out a bootp broadcast which is seen by eth1 but never by eth0.  

(tshark -i eth1 -R bootp)

2.987774      0.0.0.0 -> 255.255.255.255 DHCP DHCP Discover - Transaction ID 0x9ce15bd0

I'm guessing that this is because broadcast traffic will not cross between the two interfaces in this configuration.

I'm hoping that all of you Gentoo networking Ninja's will respond to this and let me know what I need to change.

Thanks, WH237...Last edited by WhiteHat237 on Wed May 30, 2007 6:23 pm; edited 2 times in total

----------

## benesm1

I think you need to configure arp proxy; add net.ipv4.conf.all.proxy_arp = 1 to your /etc/sysctl.conf and run sysctl -p.

----------

## Hu

Usually, masquerading is accompanied by a DHCP daemon on the NAT device to issue private addresses out over eth1.  For a really transparent setup, you should try to get this working without masquerading.  It'd be a bit confusing to issue an address to the Windows machine, then have all the traffic coming from the Gentoo machine.

Unfortunately, I don't know how to do a masquerade-free setup.

----------

## sschlueter

 *WhiteHat237 wrote:*   

> I'm guessing that this is because broadcast traffic will not cross between the two interfaces in this configuration.
> 
> 

 

That's true.

The best solution for an "inline network protocol analyzer" is to set up an ethernet bridge. This is truly transparent - no reconfiguration of the windows notebook's network settings neccessary.

Ultra Short Howto: http://www.tldp.org/HOWTO/Ethernet-Bridge-netfilter-HOWTO-3.html

----------

## WhiteHat237

Thanks to all for the quick reply's.

sschlueter, A couple changes were needed before I could follow the bridging guide.  I found this guide which helped me get the kernel setup, and the bridge module loaded:

http://gentoo-wiki.com/HOWTO_setup_a_gentoo_bridge

I had to enable (modular) bridge support in the kernel,

Networking --> Networking Options --> [M] 802.1d ethernet Bridging

I also needed to 

```
emerge net-misc/bridge-utils
```

 package.  After emerging this package it told me that it uses obsolete tools and that I should be using baselayout, so I also emerged the baselayout package.  

What are the differences between using the bridge-utils and baselayout?

----------

## WhiteHat237

After a little more reading, I'm pleased to report that this is working perfectly.  I can capture traffic on individual interfaces eth0, or eth1, and also on the bridge interface, br0.

One small snag I ran into was that when I had the bridge configured with a static IP, (ifconfig br0 192.168.1.250) and a proper default gateway, the gentoo laptop, itself didn't have DNS resolution, despite having a valid /etc/resolv.conf, and both primary and secondary nameservers being reachable via ICMP ping.  The windows box connected to eth1 worked fine and no modification of the network settings was required.

To fix this I just set br0 to use DHCP.  

```
dhcpcd br0
```

The interface came back up with an address and everything works on both machines.  Now I can use this box exactly as I want to.    :Very Happy: 

Thanks to all for your help.

----------

## WhiteHat237

Looks like the Link I referenced above is down.  Here's Google's cache of the page.

Contents

    * 1 The Gentoo 802.1d Bridge Guide

    * 2 Introduction

    * 3 Intended Audience

    * 4 Kernel Support

    * 5 Program Support

    * 6 Bridge Basics

    * 7 Advanced Bridging

    * 8 Manually Creating a Bridge Interface

    * 9 Gentoo Init Scripts

    * 10 Bridging With VLANs

    * 11 Creating 802.11/802.3 Bridges

    * 12 Conclusion

[edit]

The Gentoo 802.1d Bridge Guide

    * Author: Christopher Verges <squirrel@headnut.org>

    * Release Date: 24 Nov 2004 

[edit]

Introduction

As Gentoo seems to gain more popularity as a home-brewed server platform, extending it to act like different network devices is important. In this guide, we will explore how to configure Gentoo as an IEEE 802.1d compatible bridge.

Originally, this guide rested on the Gentoo forums, and gathered some decent comments. For brevity's sake, I am not going to re-post those comments here; but if you have questions, you should check out the original posting to see if your issue has already been addressed.

[edit]

Intended Audience

This document is written for users with a working knowledge of networking. Prerequisite knowledge includes those topics covered in the Gentoo Installation Guide and commands needed to edit common configuration files.

[edit]

Kernel Support

Like many other things in the Layer 2 realm, 802.1d support requires an addition to the kernel. Thankfully, the 2.4 and 2.6 kernels have included this support -- we just need to make sure it gets compiled.

For simplicity, I am going to assume we start with a vanilla 2.6 kernel. Edit the /usr/src/linux/.config file with the following changes:

    To compile 802.1d support as a module:

    CONFIG_BRIDGE=m

    To compile 802.1d support into the kernel:

    CONFIG_BRIDGE=y

Compile the kernel and load the bridging code as necessary. If you compile into the kernel, reboot. If you opt to compile as a module, do not forget to add the module to your /etc/modules.autoload.d/kernel-2.6 file:

    # echo "bridge" >> /etc/modules.autoload.d/kernel-2.6

    # update-modules

    # modprobe bridge

Use the dmesg command to ensure the 802.1d code was loaded successfully. Once it is loaded without errors, continue to the next stage.

[edit]

Program Support

Thanks to the magic of portage, installing the programs to control bridging is easy:

    emerge net-misc/bridge-utils

About three minutes later, depending on the speed of your machine, brctl will be installed and ready to go. The only thing left to do is figure out how to use the program.

    # /sbin/brctl

    commands:

           addbr           <bridge>                add bridge

           addif           <bridge> <device>       add interface to bridge

           delbr           <bridge>                delete bridge

           delif           <bridge> <device>       delete interface from bridge

           show                                    show a list of bridges

           showmacs        <bridge>                show a list of mac addrs

           showstp         <bridge>                show bridge stp info

           setageing       <bridge> <time>         set ageing time

           setbridgeprio   <bridge> <prio>         set bridge priority

           setfd           <bridge> <time>         set bridge forward delay

           setgcint        <bridge> <time>         set garbage collection interval

           sethello        <bridge> <time>         set hello time

           setmaxage       <bridge> <time>         set max message age

           setpathcost     <bridge> <port> <cost>  set path cost

           setportprio     <bridge> <port> <prio>  set port priority

           stp             <bridge> <state>        turn stp on/off

[edit]

Bridge Basics

A bridge is used to connect two collision domains to form a single coherent broadcast domain. Ethernet operates under a principle called CSMA/CD (Carrier Sense Multiple Access / Collision Detection). In simplistic terms, any Ethernet host "listens" to the network when it wants to transmit. It waits until it believes the network is unused (Carrier Sense Multiple Access) and then sends the data.

Because data is not transmitted instantaneously (there is actually a small amount of delay), there exists the potential that two Ethernet hosts send data at the same time. When that happens, it is as if two people talk at once: neither can really understand what the other is saying. This is called a collision in the domain of networking technology. So an Ethernet host continues to listen to the network while it transmits its data. If it doesn't hear what it originally sent, it assumes a collision occured (Collision Detection). It will stop transmitting for some variable amount of time and then start the whole process over again.

The more hosts you have on a given network segment, the greater the chance of a collision occuring. A network segment can be subdivided to decrease the number of hosts that are on a segment together. That is, I can have a LAN that looks like either of the following diagrams. Both operate the same, but the first is a single collision domain, the second has two collision domains.

         ----------------------------------------------------

              |                    |                  |

            Host A               Host B             Host C

         ----------[BRIDGE]----------------------------------

              |                    |                  |

            Host A               Host B             Host C

In the first example, if A and C talk at the same time, a collision occurs. In the second, A and C can talk at the same time without having to worry about their data colliding -- the bridge assumes the role of minimizing collisions! (Note that in the second example, B and C can still create collisions together.)

Ethernet also has this property called a "broadcast." If you know you want to talk to a host on the network, but you're not quite sure WHICH host you want to talk to -- or maybe you want to talk to all of them with the same message -- then you broadcast the message on the network. Broadcasts must be transmitted across collision domains. In the second example from above, if A sends a broadcast, both B and C hear it. Also, if B sends a broadcast, both A and C hear it. But if B sends a message to C, A will not hear it. That is the difference between a broadcast domain (the logical network) and a collision domain (the physical network).

[edit]

Advanced Bridging

Now that we understand the basics about bridging, let's look at a more complex example:

         Host A ------+-------------------+----- Host B

                      |                   |

                      |                   |       Interface 0

                 +--------+          +--------+

                 |  Br 1  |          |  Br 2  |

                 +--------+          +--------+

                      |                   |       Interface 1

                      |                   |

         Host C ------+-------------------+----- Host D

Hosts A and B are on one network segment, and Hosts C and D are on a different segment. The two segments are connected via two bridges, Br1 and Br2, via Interfaces 0 and 1, respectively. (That is, Interface 0 on Br1 and Br2 points to the Host A/B segment, and Interface 1 points to to the Host C/D segment.)

Let's say Host A sends a Layer 2 ARP packet (a broadcast) looking for the address of Host D. Both Br1 and Br2 receive the broadcast packet via Interface 0. Since it is a broadcast, the bridges flood it out every other interface, so Host D receives two copies of the packet from the bridges. It responds using a unicast packet, and the bridges forward the data properly. But something bad has just happened.

When Br1 flooded the broadcast to the wire, Br2 received the packet on Interface 1. (And likewise for Br1 receiving it from Br2.) Since the bridges interpret the packet as "new," they forward the packets out to Interface 0. Wait a second ... the broadcast was already heard on that segment when Host A originally sent it! This loop continues again, where Br1 and Br2 keep forwarding the broadcast from interface to interface like a giant perpetual motion machine. The broadcast packets start eating up all of the available time slices when a host can transmit, causing a denial of service attack. This is not a good thing and is called a "broadcast storm."

When Host D responds with that unicast packet, another troublesome event takes place. Br1 and Br2 know Host A can be found on Interface 0. They learn from the response that Host D can be found on Interface 1. Both bridges receive the response, and both forward it back out Interface 0 to Host A. When Br1 sends it, Br2 receives it; and vice versa.

Since a bridge learns which port a host is on by the source MAC address, they can get confused when they hear the same source MAC on two different interfaces. Br1 and Br2 learned that Host D is on Interface 1 from the response ... but now they think that Host D is on Interface 0 instead because their forwards got confused! Just like in the broadcast storm example that got us started, the bridges continue forwarding these packets ad inifitum, relearning their bridge forwarding tables on every packet. And thus the "unicast flood" is born.

Now, these problems do not exist when a single bridge is involved. It is only when two or more segments are interconnected by two or more bridges. But as we can see, they are very important to discuss. Broadcast storms are infamously known for crashing entire networks. So how do we combat this?

The answer is known as the Spanning Tree Protocol (STP). It acts as a type of routing protocol for bridges, telling them to turn off certain ports that may cause potential loops. The details of STP are well beyond the scope of this document, but I highly suggest reading Michael Norton's article Understanding Spanning Tree Protocol - the Fundamental Bridging Algorithm as an introduction to STP.

Now we are ready to begin building our bridge.

[edit]

Manually Creating a Bridge Interface

Let's say I want to create Br1 from our previous example. eth0 and eth1 will be the interfaces used. Linux requires that we create a new bridge interface that is a summation of the two real interfaces, so let's go ahead and do that:

If you are adding a bridge to a machine you are administering through ssh, and, are currently connected to one of the interfaces you would like to bridge, you should read this section before issuing any commands so that you understand what you are doing. Then go back and combine all of the commands into one, seperated by '&&' or you may have to get physical access in order to finish creating the bridge/regain remote access.

# /sbin/ifconfig eth0 up

# /sbin/ifconfig eth1 up

# /sbin/brctl addbr br0

# /sbin/brctl addif br0 eth0

# /sbin/brctl addif br0 eth1

# /sbin/ifconfig br0 up

This tells brctl to create an interface br0 and then to assign eth0 and eth1 to it. And with those three commands, we have a fully functional bridge. The rest is just tweaking.

By default, STP is disabled under Linux bridging. Let's go ahead and enable this for safe measure:

# /sbin/brctl stp br0 on

Ah, now Br1 is really working well. We don't need to worry about broadcast storms or unicast floods on this bridge anymore.

The only thing lacking is remote administration of the Linux box. eth0 and eth1 are in promiscuous mode to be part of the bridge, so how do we SSH into it? The answer: we assign the bridge interface itself an IP address.

# /sbin/ifconfig br0 192.168.1.2 netmask 255.255.255.0 up

The only thing more perfect would be if we could somehow script all this into an init script.

[edit]

Gentoo Init Scripts

Thanks to the kind developers over the baselayout scripts, we no longer have to patch the init scripts. Also, it seems you no longer have to start the bridging software (/etc/init.d/bridge) as a separate process. It gets fairly simple from here.

Our first step is to modify /etc/conf.d/net to add the bridge configuration. If you look at /etc/conf.d/net.example you'll notice a sample configuration you can use as a template. You'll notice the syntax is similar to the syntax for configuing individual interfaces specifically.

File: /etc/conf.d/net

# Bridging (802.1d)

# For bridging support emerge net-misc/bridge-utils

# To add ports to bridge br0

bridge_br0="eth0 eth1"

# Finally give the bridge an address - dhcp or a static IP

#config_br0=( "dhcp" )

config_br0=( "192.168.1.1 netmask 255.255.255.0" )

Note that for any interfaces that are to be in the bridge, they need to be set to "null." Unexpected results may occur if these ports get configured with an IP. Hence, configure the individual ethernet ports like so:

File: /etc/conf.d/net

# You need to configure the ports to null values so dhcp does not get started

config_eth0=( "null" )

config_eth1=( "null" )

If you have multiple bridges on the network, you'll probably want to turn on stp (discussed above; shown below). You can use similar syntax for other brctl commands:

File: /etc/conf.d/net

# Try to prevent "storms"

brctl_br0=( "stp on" )

Next, create the symbolic links for the extra interface and for br0 init scripts and add them to the default runlevel:

# ln -sf /etc/init.d/net.lo /etc/init.d/net.eth1

# rc-update add net.eth0 default

# rc-update add net.eth1 default

# ln -sf /etc/init.d/net.lo /etc/init.d/net.br0

# rc-update add net.br0 default

# /etc/init.d/net.br0 start

[edit]

Bridging With VLANs

    * Section Author: Eliot Gable <e gable AT@AT gmail dot com>

    * Date: 4/13/2006 

802.1d and 802.1Q can combine seamlessly under a Linux system. Unfortunately, Gentoo does not make configuration easy on us. Using Bash variables, we cannot easily create a device-specific VLAN and specify configuration parameters. To do this, we would need to be able to create a "config_eth0.2" directive in /etc/conf.d/net, which violates the variable rules for Bash. We can, however, circumvent the problem entirely using the vconfig name-type parameter 'VLAN_PLUS_VID_NO_PAD'. Unfortunately, if the same VLAN is used on two interfaces, this method will not work without a helper function to rename the VLAN to something unique on a per-interface basis. Using the preup() function provided by Gentoo, we can issue a series of commands that performs this renaming for us.

File: /etc/conf.d/net

# Bridging (802.1d) with VLANs (802.1q)

# For bridging support emerge net-misc/bridge-utils

# For VLAN support emerge vconfig

preup() {

        VLAN=$(echo "${IFACE}" | grep v)

        if [[ "${VLAN}" ]]; then

                VNUM=$(echo "${IFACE}" | awk -F'v' '{print $2;}')

                # We need to bring the newly created vlan2 device down to rename it

                CMDTMP="CMD=\"ip link set vlan${VNUM} down\""

                eval $CMDTMP && ebegin "$CMD" && $CMD  &>/tmp/error

                ewend $? $(cat /tmp/error && rm -f /tmp/error)

                # Then we rename it to our real interface-specific name

                CMDTMP="CMD=\"ip link set vlan${VNUM} name ${IFACE}\""

                eval $CMDTMP && ebegin "$CMD" && $CMD  &>/tmp/error

                ewend $? $(cat /tmp/error && rm -f /tmp/error)

                # Then we bring the interface back up

                CMDTMP="CMD=\"ip link set ${IFACE} up\""

                eval $CMDTMP && ebegin "$CMD" && $CMD  &>/tmp/error

                ewend $? $(cat /tmp/error && rm -f /tmp/error)

        fi

}

# These depend functions tell Gentoo which order interfaces need to be started

depend_br0() {

        # We need to start _all_ VLAN interfaces before we start a bridged interface!

        need net.e0v2 net.e1v2

}

depend_br1() {

        # We need to start _all_ VLAN interfaces before we start a bridged interface!

        need net.e0v2 net.e1v2

}

depend_e0v2() {

        need net.eth0

}

depend_e1v2() {

        need net.eth1

}

# Add VLAN 2 to both interfaces

vlans_eth0=( "2" )

vlans_eth1=( "2" )

# When we create the VLAN, call it "vlan" followed by the VLAN ID

vconfig_eth0=( "set_name_type VLAN_PLUS_VID_NO_PAD" )

vconfig_eth1=( "set_name_type VLAN_PLUS_VID_NO_PAD" )

# We need this so that the VLAN tagged packets are interpreted properly by our software

vconfig_e0v2=( "set_flag 1" )

vconfig_e1v2=( "set_flag 1" )

# Bridge 0 is VLAN 1 (the default VLAN)

bridge_br0=( "eth0 eth1" )

# Bridge 1 is VLAN 2

bridge_br1=( "e0v2 e1v2" )

# Turn on STP for both VLANs

brctl_br0=( "stp on" )

brctl_br1=( "stp on" )

# We need to set all interfaces to NO IP address

###################################################

# These are our physical interfaces

config_eth0=( "null" )

config_eth1=( "null" )

# This interface is for the temporary vlan2 interface so DHCPCD does not fire

config_vlan2=( "null" )

# These are the final interface-specific names for vlan2

config_e0v2=( "null" )

config_e1v2=( "null" )

###################################################

# We set the actual IP addresses on the bridge interfaces

config_br0=( "192.168.1.2 netmask 255.255.255.0" )

config_br1=( "192.168.2.2 netmask 255.255.255.0" )

routes_br0=( "default via 192.168.1.1" )

As you can see, the basics of bridging with VLAN support is already present. The only problem we have to circumvent is the Bash variable naming problem. Gentoo provides adequate capabilities to do this. Our last step is to create the init.d scripts and add them to the default runlevel:

# cd /etc/init.d

# ln -s net.eth0 net.e0v2

# ln -s net.eth0 net.e1v2

# ln -s net.eth0 net.br0

# ln -s net.eth0 net.br1

# rc-update add net.eth0 default

# rc-update add net.eth1 default

# rc-update add net.e0v2 default

# rc-update add net.e1v2 default

# rc-update add net.br0 default

# rc-update add net.br1 default

Now we can start our bridged interfaces:

# /etc/init.d/net.br0 start

# /etc/init.d/net.br1 start

The bridged interfaces require all VLAN interfaces to start first. If you fail to start your VLAN interfaces before starting a bridged interface, the VLAN interfaces will fail to start. You can start your bridged interfaces in any order, just so long as all VLAN interfaces (e0v2, e1v2, etc) have been started prior to starting a bridged interface.

[edit]

Creating 802.11/802.3 Bridges

Quite simply, Linux does not support this easily. From Jean Tourrilhes' site:

    The conventional Ethernet bridging method (promiscuous sniffing) doesn't work with most wireless LAN standard, because of the header encapsulation and the interactions with link layer retransmissions. In other word, most often, when you use a software bridge on a wireless LAN (such as the Linux bridge on a 802.11 card), it doesn't work (moreover, quite often promiscuous is broken as well). 

    The driver could work around this restriction by creating its own MAC headers (802.11 headers instead of 802.3, and putting the right bits in the right place), but in fact most vendors don't provide the specification on how to this with their hardware (when they don't explicitly prevent it in hardware, to force you to buy their Access Points). (http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Linux.Wireless.usage.html) 

The eventual goal is to bridge a wireless network to a wired network. Fortunately, this is exactly what an access point does. There are several out there from which to choose. If you have lots of money or need VLAN/QoS support, the Cisco Aironet 1100 and Aironet 1200 access points are a great investment. If your budget is more of a requirement, the Linksys WAP54G or WRT54G are cheap and quite effective. (The Linksys Cable/DSL "routers" can easily be turned into a regular access point via a single selection box in the configuration.)

So rather than trying to hack a Linux 802.11/802.3 bridge together, spend the $100 and save yourself a lot of headaches.

I don't know if the above is just old or what, but this wiki article goes step-by-step through building just such a bridge: HOWTO Building a Wireless Access Point

01-15-2007: Bridging wireless and wired network worked as described for me with D-Link DWL-G520 card and madwifi-ng.

03-23-2007: Bridging wireless and wired networks did not work with a Linksys WAP54G Access Point and a Linksys WMP54G in the Gentoo machine

[edit]

Conclusion

While Gentoo has enjoyed lots of attention in the matters of 802.1q VLANs and Layer 3 routers/firewalls, bridging support is has been relatively ignored. Hopefully, this document has remedied some of that.

I recommend using a Linux bridge in the special case of a transparent proxy server. Read Chapter 7 in the Transparent Proxy with Linux and Squid mini-HOWTO by Daniel Kiracofe. Otherwise, I generally prefer specialized hardware. My flavor of choice is the Cisco Catalyst 2950, though just about any Layer 2 switch would handle the job. (The Catalyst supports STP and VLANs along with remote management features.)

You can use 802.1d in combination with other features like Linux 802.1q VLANs, firewalling, Linux Channel Bonding, and Squid for a flexible and complete solution in any network. Start with the basics and expand outwards.</nowiki>

Retrieved from "http://gentoo-wiki.com/HOWTO_setup_a_gentoo_bridge"

----------

