So you want to set up a firewall...
Let's say you have a server that is on a network and you want to only allow access to specific services, such as SSH, HTTP, and DNS. And you want this firewall to persist between reboots. Oh yeah, and you want it to work with both IPv4 and IPv6. This is an easy problem!
We're going to make a few assumptions:
- You are running Linux -- distro doesn't matter
- You have iptables installed, though this usually comes with the default installation of your operating system. You can see if it is available by running iptables --list.
- You can run commands as root. iptables will only run as root.
- Your IPv4 address is 1.2.3.4. (Please substitute your IPv4 address as appropriate.)
Creating a firewall with iptables is simple: you run the iptables command a few times, each time telling it a new rule, and it applies them, in order, to any packet that comes in. So if you first tell iptables to drop all packets and then tell it on the next command to accept some types of packets, the second command will never really run because the packets were all dropped in the first step.
First we are going to flush all of the rules that are present so we can start fresh:
The next rule, a very basic rule, will allow any existing and established connection:iptables -F
Then we are going to accept any connection that comes from localhost or from ourselves:iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
It might be very useful to allow incoming ICMP requests. This will allow ping and traceroute on both sides of your interface -- incoming and outgoing -- to work successfully. For iptables this would look like this:iptables -A INPUT -s 127.0.0.1 -j ACCEPT iptables -A INPUT -s 1.2.3.4 -j ACCEPT
For ICMP, this is the only instance where the -p flag is different between IPv4 and IPv6. Everywhere else you can pretty much replace iptables with ip6tables and it will work. That makes the IPv6 statement it look like this:iptables -A INPUT -p icmp -j ACCEPT
Once we've done those basic steps, we want to decide which ports we want to allow in. As listed above, we want to allow SSH, HTTP and DNS. In this example we are going to use the names of the ports, but it is very simple to replace "ssh" or "domain" with "22" and "53", respectively. Let's open up a few ports:ip6tables -A INPUT -p icmpv6 -j ACCEPT
However, we want to limit people from connecting to our SSH server too quickly. To do that, we can restrict new connections on port 22 when the remote address has made more than four connections in sixty seconds:iptables -A INPUT -p tcp --dport ssh -j ACCEPT iptables -A INPUT -p tcp --dport domain -j ACCEPT iptables -A INPUT -p udp --dport domain -j ACCEPT iptables -A INPUT -p tcp --dport http -j ACCEPT iptables -A INPUT -p tcp --dport https -j ACCEPT
iptables -I INPUT -p tcp --dport 22 \
-m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 22 \
-m state --state NEW -m recent \
--update --seconds 60 --hitcount 4 -j DROP
Finally, after allowing in all of the above connections, we want to drop anything else:Now that we've done this, our server will only accept outside connections on ports 22, 53, 80 and 443. But when we reboot, you will quickly find that everything was lost! Saving your firewall between reboots depends on the system. On Redhat-like systems -- CentOS, RHEL, Fedora -- this capability is built in:iptables -A INPUT -j DROP
On Debian, you have to set it up yourself:/etc/init.d/iptables save
Then force the firewall to reload on the next boot by editing /etc/rc.local and adding this simple line:mkdir /etc/firewall iptables-save > /etc/firewall/ipv4.conf
Now you've got a simple firewall set up.iptables-restore < /etc/firewall/ipv4.conf
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Any instructions provided in this essay are provided as-is with no warranty whatsoever and the author bears no liability resulting from any and all uses of this work. Use at your own risk.
© Copyright 2002 - 2012 Paul Lockaby. All rights reserved.