Sunday, August 06, 2006


I live in a world populated by geeks, of whom I am but one instance. We like misusing words. Today's word is "martian." Normally a martian is a packet that we're not expecting. Network protocols are very orderly - there's a time to speak, a time to shut up, a time to listen, and a time to respond. So when someone speaks out of turn, you don't know what to do with it. That's a martian.

Today's martian (well, technically, last night's) was a packet that arrived unexpectedly on my network from a DHCP server Somewhere Out There. This particular DHCP packet created some trauma on my home network, because it was actually in response to something being sent *from* my network, unbeknownst to me. Here's the laybeing's explanation:

On a local area network (LAN), you have packets that are sent from one computer directly to another, and you have packets that are sent from one computer to every computer that's connected to the LAN. These packets are useful when a computer is first trying to get configured, because it doesn't know where the other computers are. Some protocols, like NetBIOS, use broadcasts to announce things as well: "I am here." So that you build a picture of your local network neighborhood dynamically by listening to all the other computers proclaim their presence.

Now, as you can imagine, the more computers there are attached to the network, the more broadcasts you are likely to hear on that network. So generally you try to keep the LAN small. Because I manage my own network, I think of my LAN as being quite small - just the wires within my house, and of course the local WiFi.

However, as it turns out, my network is *not* that small. Because of the way that my Internet Service Provider does routing, my local area network actually covers four states. Not kidding, honest. It doesn't hit every machine in four states, thank goodness, but whenever a DHCP client on my network sends a broadcast, that broadcast is heard in probably twenty to forty homes.

I hadn't noticed this before, because like most networks, my ISP does some filtering. The way filtering works is that you notice where all the computers are that are connected to the LAN. The connection to each computer is called a home run, or a circuit, depending on whether you're speaking ISP-ese or LAN-ese. In the case of a LAN, a home run usually connects to a single computer; in the case of an ISP, the circuit connects to the customer premise, which may be a single computer, or it may be a collection of computers.

All the circuits come in to a central switch. This switch is what does the filtering. If it knows where the individual computer is - to which circuit it is attached - it sends the packet only on that circuit, and not on the others. If it *doesn't* know where the computer is, it has to send it out on all the circuits, just to be sure that it gets where it's going. But usually it knows where all the computers are, so there's no way, by monitoring packets on the circuit that goes to your computer, to tell that this is happening. To you, it appears that your computer is alone on the network.

Or if you're like me, and have more than one computer hooked up, it appears that your computers are in their own isolated network. But they aren't. The way you find this out is to broadcast. Your broadcast goes to all the computers on your home network, but it also goes back to the central switch. The central switch says "oh, this is a broadcast, I have to send it everywhere" and sends it out on each of the circuits.

What happened to me is that one of the other customers connected to the same central switch was running a misconfigured DHCP server. That DHCP server didn't offer service to my DHCP client, but when my client got service from *my* DHCP server, the other DHCP server noticed, and said "hey, wait, you can't do that." And so my client wound up saying "well, okay, I guess I made a mistake, I'll try again." And the result was a continuous stream of DHCP packets, but more importantly it was that my poor computer wasn't able to use the network, because it was being repeatedly denied DHCP service.

There are two ways to fix this. Most people never even run into this problem, because although they have more than one computer at home, they also have a Network Address Translator (NAT). A NAT is a little demon in a box that sits at the gateway to your network (I use the word demon advisedly - NATs are a huge problem in network protocol design because they break the network). What it does is to make it look like all the computers on your network at home are one computer, as far as the outside world is concerned. As a consequence, your home network is now its own local area network, completely isolated from the world.

This is really great if you like being isolated, but as I say, if you're isolated like this, some protocols don't work, and others are a real pain to use. This is why Skype doesn't just connect computer-to-computer, for example. It has to use special NAT traversal protocols to work through your NAT box. So anyway, I don't like NATs. This is why I'm having trouble right now. :')

So the fix for me, since I'm not willing to use a NAT, which breaks things, is to analyze the traffic coming in across my network connection, and traffic going out across it as well, and drop traffic that shouldn't be passing. And since I am running a linux server as a bridge between the outside world and my home network, this is actually possible, using iptables. Here is my iptables configuration:

-A FORWARD -m physdev --physdev-in eth2 -d -j DROP

This file is used as input to iptables-restore, and it's the output of iptables-save. By putting it in my /etc/network/interfaces configuration file, I arrange to have it run every time the network is started, so that this configuration is persistent. Here's what my bridge configuration looks like:

auto br0
iface br0 inet static
bridge_ports eth0 eth2
up iptables-restore </etc/network/nat-table

I've changed the IP addresses in the above configuration to protect the innocent.

Anyway, the iptables file does two things. The first line says "these are regular filters." If it said "*nat*, it would be indicating that these are nat filters. I am reporting this based on what I've observed, not deep knowledge, so don't take this as gospel.

The second line says "if you get a packet that's to, and it comes in on eth2, drop it instead of forwarding it." The third line says "if you get a packet that's *from*, drop it instead of forwarding it."

To understand why this works, you need to know the configuration of the bridge on my linux machine. The way the bridge works is that I have two ethernet cards. One, which is called eth2, is plugged into my DSL modem. The other, which is called eth0, is plugged into my local network. Normally, whenever a packet comes in on eth0, it's repeated on eth2, and when a packet comes in on eth2, it's repeated on eth0. This is how bridges work.

So these two rules state exceptions. First, if I get a packet to the broadcast address from my DSL connection, just drop it. Don't send it to my computers. This prevents the martian from arriving. The second rule says "if you get a packet from, which is the IP address that DHCP clients use before they've been configured, drop it." This prevents the misconfigured DHCP server somewhere in the greater Los Angeles network region from ever hearing a DHCP packet from one of my DHCP clients. So in fact the first rule really isn't necessary, because in theory it should never happen that I receive a DHCP packet if I didn't send one. But I put it there for completeness, because it is actually a minor risk for my DHCP clients to be exposed to martians from beyond the bridge.


Anonymous Patricia said...

DHCP 201?
Your explanations are so clear I believe that if I knew anything at all about DHCP I would understand them easily.

From wizard to guru, huh?

Monday, August 07, 2006 4:01:00 PM  

Post a Comment

<< Home