Monday, October 25, 2010

Ten minute host firewall, Part 1

Summary: Create a simple but effective host firewall for your machine in ten minutes or less.

One of my friends finds himself in a very annoying situation: he started a new job and now has a Windows machine on his desk. Worse yet, he's not allowed, by corporate policy, to wipe it clean and install Linux on it "for security reasons". Being that we both live up here in Seattle, close to the belly of the beast itself, it's not surprising that the Microsoft FUD machine is strong.

The IT department grudgingly agreed that he could use Linux if he had an adequate firewall installed. They intend to port scan him and, if all ports refuse inbound connections, they'll consider his machine secure.

Now this is not my definition of a very secure firewall.[1] However it is immeasurably better than no firewall rules at all, and it takes no more than a few minutes to set it up.

First, let's assume we're on a 2.4 kernel that has Netfilter (iptables) support compiled in. I'll assume you're using a 2.4 kernel for these examples, but I've restricted myself to commands that can be munged into their ipchains counterparts, meaning I've ignored Netfilter's ability to do connection tracking and the like. If you want to create a more secure firewall, then there are various pre-canned firewall scripts you can use, or you can read up on Netfilter's finer details online or in books such as Ziegler's "Linux Firewalls".

In this minimal setup, we want to allow all outbound access, and deny all inbound access that isn't in response to one of our outbound connections. This is surprisingly easy to manage.

We'll be adding rules to the INPUT chain. First, let's make the default rule (the 'policy') be to to DROP packets. This throws away the packet without informing the sender.

# iptables -P INPUT DROP
You now have a very secure machine - nothing can get in. Perhaps we should open things up a bit...

There are three protocols we'll want to support, TCP, UDP, and ICMP. TCP is the IP protocol that does the majority of the work on the Internet. It's a connection-based protocol that underlies all the major services, such as web (HTTP/HTTPS), mail (SMTP, POP, IMAP), remote login (SSH), and file transfer (FTP).

Any TCP connection has the oft-mentioned "three way handshake". The machine that wants to create a connection sends a packet to the destination with the SYN (synchronise) flag set. The server responds with a packet that has both SYN and ACK (acknowledge) set, and thereafter the SYN bit is never seen again. If we configure our firewall ACLs to drop any packets which contain the SYN bit without that ACK, we can prevent the first packet of TCP connections from reaching our machine, and no TCP connections can be created at all.

Iptables[2] can selectively block packets based on the SYN flag using the --syn flag, for example:

# iptables -A INPUT -p tcp ! --syn -j ACCEPT
Voila! No machines can connect to your machine with TCP, but you can make outbound connections and the associated packets will be allowed back in. You can't be a server (no SSH to your machine, for example) but all outbound TCP stuff should work fairly well.
Well, that's true about most 'well behaved' TCP-based protocols. Some protocols like to use more than one port. FTP is the classic example of a bastardly-designed protocol. Each time you type 'get', 'put', or 'ls' a new TCP connection is initiated to snag the data.

Note also that even though outsiders can't connect to your TCP ports, scanning tools such as Nmap will be able to see that the port is open if they are used in any mode other than straight TCP connection scanning. Newer Nmap versions use stealth scanning by default when run as root.

If the protocol you use wants to have the client (your newly firewalled machine) make an additional connection to the server, then your --syn firewall won't be a problem. However if it wants to have the server contact the client, these connections will be denied.

Protocols that create these ephemeral side connections include many P2P protocols, and most notably FTP. Most of these offer both a 'client connects to server' and 'server connects back to client' option. In the case of FTP, the former is called "Passive", while the latter is called "Active". Active was the original (really annoying for firewalls and proxies) model, and Passive has been favoured for some time now. Most FTP clients let you choose Passive if it's not already the default. For example typing pftp instead of ftp on the command line, or including --passive-ftp as an argument to wget.[3]
 
Now, to be a bit more restrictive, let's block UDP as well. UDP is a connectionless protocol, so it's harder to proxy and firewall. However it's also less commonly used. DNS is the the most important UDP protocol. Without DNS you're going to need to memorise many IP addresses, so we best open this up.

DNS servers live on UDP port 53.[4] Our machine will need to send packets to port 53 on one or more DNS servers, and receive packets that come from port UDP 53. So, restricting on the source port (the port on the DNS server) you'd have

# iptables -A INPUT -p udp --source-port 53 -j ACCEPT
This will allow any DNS servers to reply to you, which may be helpful if you get your DNS servers from DHCP and want to be lazy. If you want to hard code your DNS server's IP addresses to be most restrictive, you can use the following

# iptables -A INPUT --source DNS.SVR1.IP.ADDR -p udp --source-port 53 -j ACCEPT
  # iptables -A INPUT --source DNS.SVR2.IP.ADDR -p udp --source-port 53 -j ACCEPT
If your machine needs to get an IP address from the network using BOOTP or DHCP, then you'll need the following rule as well:

# iptables -A INPUT -p udp --destination-port 68 -j ACCEPT
 more @ http://www.hackinglinuxexposed.com/articles/20030703.html

No comments:

Post a Comment