Two Wrongs

(don't make a right)

Securing a Debian Laptop with a Firewall

by ~kqr

I'll quickly walk you through the process I used when configuring the firewall on my Debian laptop.

But Why?

Why care about a firewall for a laptop in the first place? Aren't most laptops protected by the firewall in the router of the local network they're attached to? Well, yes, but there are two problems not covered by the router firewall:

  • Security. I frequently connect my laptop to untrusted networks, and I don't want to invite someone on the same physical network as me to do something funny. The router firewall only protects me from threats outside the network. This is not just wild paranoia: I often connect to university networks with thousands of students – at least a few may have a malicious curiosity.
  • Privacy. I sometimes use applications which I know are of the kind where they "phone home" and report usage statistics and such. I'm well aware I can't catch all – or even a majority – of these, but I want to do what little I can.

The basic idea of a firewall is to deny everything except the few things you know you want and need.

Requirements Analysis

So to figure out what I want and need, I sat down and thought a bit about what kind of networked applications I use. I arrived at a fairly short list, actually: ssh/mosh, web browser (http and https) and, incredibly rarely, Spotify. Most of the other things (email, large downloads, music, irc and so on) I do on one of my servers, accessed through ssh.

However, lots of programs communicate locally through the loopback interface, so I'll need to allow that too.

Given this, the following connection types need to be allowed:

  1. all on the loopback interface
  2. all established incoming and outgoing
  3. all incoming and outgoing tcp on port 22 (this is ssh to and from my laptop)
  4. all outgoing tcp with remote port 80 (this is http)
  5. all outgoing udp with remote port 123 (this is ntp)
  6. all outgoing tcp and udp with remote port 443 (this is https as well as encrypted dns)
  7. all outgoing udp with remote port from 60000 to 61000 (this is mosh)

That's it! To begin with, anyway. I will continuously update this list as I realise I need more things.

As you see, I run encrypted dns over port 443. If you don't, you may want to add outgoing tcp with remote port 53 to your list.

iptables Commands

The following commands are the ones I used to encode the above rules.

# allow anything on localhost
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT

# allow already established
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# allow ssh to and from laptop
sudo iptables -A INPUT -i wlan0 -p tcp -m tcp --sport 22 -j ACCEPT
sudo iptables -A INPUT -i wlan0 -p tcp -m tcp --dport 22 -j ACCEPT
sudo iptables -A OUTPUT -o wlan0 -p tcp -m tcp --sport 22 -j ACCEPT
sudo iptables -A OUTPUT -o wlan0 -p tcp -m tcp --dport 22 -j ACCEPT

# allow outgoing http, https and dnscrypt requests
sudo iptables -A OUTPUT -o wlan0 -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -A OUTPUT -o wlan0 -p tcp -m tcp --dport 443 -j ACCEPT
sudo iptables -A OUTPUT -o wlan0 -p udp -m udp --dport 443 -j ACCEPT

# allow outgoing ntp requests
sudo iptables -A OUTPUT -o wlan0 -p udp -m udp --dport 123 -j ACCEPT

# allow outgoing bittorrent requests (i'm a bit hazy on this... hopefully it works)
sudo iptables -A OUTPUT -o wlan0 -p tcp -m tcp --dport 6881:6999 -j ACCEPT
sudo iptables -A OUTPUT -o wlan0 -p udp -m udp --dport 6881:6999 -j ACCEPT

# allow outgoing connection to mosh remote
sudo iptables -A OUTPUT -o wlan0 -p udp -m udp --dport 60000:61000 -j ACCEPT

# "default reject" instead of "default drop" to make troubleshooting easier
sudo iptables -A INPUT -j REJECT
sudo iptables -A OUTPUT -j REJECT

# my laptop has no business forwarding packets
sudo iptables -A FORWARD -j REJECT

# I don't use ipv6 and it's buggy and exploitable
sudo ip6tables -A FORWARD -j REJECT
sudo ip6tables -A INPUT -j REJECT
sudo ip6tables -A OUTPUT -j REJECT

Linux Configuration

I also borrowed some additional configuration commands from Praveen Kumar, namely these:

echo 1 | sudo tee /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
for iter in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 | sudo tee $iter; done
for iter in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 | sudo tee $iter; done
for iter in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 | sudo tee $iter; done
echo 1 | sudo tee /proc/sys/net/ipv4/tcp_syncookies

You can read more about each in Kumars article.

More

If you have any further suggestions, I'd be happy to evaluate them. This is highly interesting to me. Please send me an email with your ideas!

If you enjoyed this article, you might like others tagged with