Firewalls part 3
Another issue with firewalls which isn't always on radar is that dropping (or the correct thing which is rejecting) a packet is a pretty substantial thing to do. It's kind of like the death penalty. The justice system has a wide range of punishments and while the consensus in the US is that there are crimes which justify the death penalty most do not. When we build firewalls we tend to be heavy handed in that regard and if there is a well define policy then it's the safest thing to do.
I watch my logs too much and every now and then I see an IP doing "too much," so I whois him, it's some random ISP somewhere serving up DHCP, depending on my temperment at the time, maybe I'll nmap him to see what I can learn and based on that I might make some new firewall rules. This is my "hacker computer geek security response" someone is poking me so what do I do? I poke right back, it's not like I'm showing someone a gun on an Los Angeles freeway.. Mind you, I'm also a software engineer and not a network guy but I've got some hammers and my network has some nails. As I get older, wiser and have less time to just screw around I find myself responding this way less frequently but regardless I still don't particularly like it when someone creates enough traffic on my firewall for me to notice and I'm not about to simply start dropping packets because I don't like them, a more mature response is needed. It's even more ironic, they might have been responding in kind and I'm pretty sure that I've scanned someone and caused them to scan me right back before, sort of a high tech submarine collision.
I also happen to be the victim of working on an IDS/IPS project for a couple years. You'll have to give me a couple of beers to get my complete feelings on the subject, for here I'll just say that they can be nice tools to provide more visibility in to a network, making sense of that visibility is a different matter and acting on it is something else that is still all together different. One of the overriding themes from that episode was how for many customers an IPS is a much larger hammer than they usually need and we routinely feed them a bunch of BS about "tuning," like we were helping them put a really large "racing muffler" on their Honda Civic rather than breaking in the Cadillac that we had told them we were selling them, and that they need to figure out what is on their network before they start just blocking stuff regardless of the policy that they didn't have to begin with... I'll shut up before I compromise my professionalism too much more than I did by working at that place in the first place. A different response is needed, much more so with IDS/IPS type products.
So what do we do? Rate limiting. At a glance this may not seem like a resonse. If you're actively being attacked and possibly exploited, slowing the data flow down doesn't really "fix the problem." However if you have questionable data about a situation such as an alert from an IDS, your network is critical for business (or maybe it's just not critical because it's at home) or you simply don't know what the traffic is and you don't get a good feeling about it then rate limiting is much better than the death penalty.
Linux provides a fairly robust and full featured set of tools for this, even better, they integrate very nicely with the firewall. Once you've created some traffic shaping policies you can easily make firewall rules to shape packets based on IP, protocol, flags and port and anything you'd put in your firewall.
Foregive the slop, I just cranked this out and it's not optimal..
# Define some match bits for different types of rate limiting.
MATCH1="111"
MATCH2="222"
IPTABLES=/sbin/iptables
$IPTABLES -n RATELIMITRULES
$IPTABLES -n RATELIMIT1
$IPTABLES -n RATELIMIT2
# For packets on both interfaces limit them to "rate 1" by setting match 1
$IPTABLES -I RATELIMIT1 -t mangle -i eth0 -j MARK --set-mark $MATCH1
$IPTABLES -I RATELIMIT1 -t mangle -i eth1 -j MARK --set-mark $MATCH1
# For packets on both interfaces limit them to "rate 2" by setting match 2
$IPTABLES -I RATELIMIT2 -t mangle -i eth0 -j MARK --set-mark $MATCH2
$IPTABLES -I RATELIMIT2 -t mangle -i eth1 -j MARK --set-mark $MATCH2
# Tell packets that are forward to go through the RATELIMITRULES table.
$IPTABLES -t mangle -I FORWARD -j RATELIMITRULES
The in the RATELIMITRULES table you can place rules for IPs you wish to rate limit, I created 2 different rates as punishments, RATELIMIT1 and RATELIMIT2, one is really slow and one is just kind of slow. A rule might look like this:
$IPTABLES -I RATELIMITRULES -s www.badguy.com -j RATELIMIT2
Now how do we set up the actual rate limiting? Your kernel needs queuing disciplines. I'll explain the many options there in a future article.
TC=/sbin/tc
$TC qdisc del dev eth0 root
$TC qdisc del dev eth1 root
## This part is lame, I made is completely symmetrical which probably isn't what's wanted.
$TC qdisc add dev eth0 root handle 1: htb default 30
$TC qdisc add dev eth1 root handle 1: htb default 30
# Define your network pipe
$TC class add dev eth0 parent 1: classid 1:1 htb rate 100mbit burst 100mbit
$TC class add dev eth1 parent 1: classid 1:1 htb rate 100mbit burst 100mbit
# Define a 15kbit pipe.
$TC class add dev eth0 parent 1:1 classid 1:10 htb rate 15kbit burst 15kbit
$TC class add dev eth1 parent 1:1 classid 1:10 htb rate 15kbit burst 15kbit
# This pipe is only 4kbit
$TC class add dev eth1 parent 1:1 classid 1:20 htb rate 4kbit burst 4kbit
$TC class add dev eth0 parent 1:1 classid 1:20 htb rate 4kbit burst 4kbit
## Here is the magic, it hooks the queues up to the firewall match.
$TC filter add dev eth1 protocol ip parent 1:0 prio 1 handle ${MATCH1} fw flowid 1:20
$TC filter add dev eth0 protocol ip parent 1:0 prio 1 handle ${MATCH1} fw flowid 1:20
$TC filter add dev eth1 protocol ip parent 1:0 prio 1 handle ${MATCH2} fw flowid 1:10
$TC filter add dev eth0 protocol ip parent 1:0 prio 1 handle ${MATCH2} fw flowid 1:10

