firewatch

I have a LAN. I have a firewall. I allow people w/ registered MACs to get 'net via a DHCP lease. I don't believe in allowing an entire subnet (say 10.0.0.0/24, for example) through the firewall. See the problem here?

The problem was, at the time, there was no easy way to execute some command every time a DHCP lease is given out. For all I know, the latest version of dhcpd incorporates this functionality. I wrote firewatch to do this. At its core, it tails the log file(s) and waits for a DHCP lease to be given out, then adds a set of firewall rules.

Initially, the rules were hardcoded into the script. This worked fine for a few machines. However, when people starting asking things like "hey, could you allow pr0nd through the firewall", editing the script became a real bitch (that also required killing and restarting the script.). I've since moved all the allowed protocols and ports to any external file that gets source everytime a machine gets added to the firewall. Since lease times are relatively short (in my setup anyway), changes will get populated to all machines within a reasonable amount of time.

I have had no problems with the script. Its run for nearly a month straight and has handled added rules for as many as 5 machines without doing anything stupid like eating up all my memory, adding 5000 incorrect rules, or randomly dieing.

Please note that this script is OLD and newer and better solutions exist, namely authpf.

rule_reaper

As previously stated, I'm a bit anal about what I allow through my firewall. After I started writing firewatch, I realized that I needed to incorporate a way to remove rules as leases are expired. I soon discovered that rule removal was an equally ugly beast, so I moved this task elsewhere. Enter rule_reaper. rule_reaper's soul purpose in life is to query the current running firewall ruleset (assuming ipf), and check the hosts contained within said ruleset for life. Checking a host for life was not easy. Ping (be-it ICMP, or TCP-type pings) are not reliable as it is entirely possible that the client we are checking has its own firewall. To check if a host is alive, I use the IP address and then do an arp-ping. arpping sends out and "arp who-has" packet. If I get a response, I take the responding MAC and check it against our records of allowed MACs. If the MAC matches, the rule is kept. If the MAC does not match, this rule and all subsequent rules containing this IP are dropped. If I get no response, the rules are terminated without mercy. I set the script to run (by default) every 5 minutes. This seems to work fairly well. I was having problems at one point. I noticed that some rules would hang around indefinitely. I then tried to remove the rules by hand. No go. Turns out, the kernel was maintaining state on a connection related to this rule. A rule cannot be removed from a running ruleset unless certain conditions relating to the 3-way TCP handshake are met. I'm not entirely clear what these conditions are. All I know is that the connections that appeared to be alive to the kernel that contained old IPs were in fact terminated long ago. I solved this by flushing all states that were not completed by using "ipf -Fs". This seemed to work for a few weeks. I then discovered that I could fill up my state table using garbage traffic. The reason for this was that I was keeping state on _all_ outgoing TCP traffic. Its a much better practive to only keep state on the initial SYN and the following SYN/ACKs. This keeps the state table clean and the clients in check.

Please note that this script is OLD and newer and better solutions exist, namely authpf.

dhcp-leaser

Parses a file containing a csv list of MACs, names, and email addresses and creates a dhcp entry. Takes a base dhcpd config file and kludges it together with the above created client entries. For use in an environment where only specific MACs are allowed to get dhcp leases. Essentially: a makefile.