I have been trying to put together a basic server iptables script that will work for most sites just running a basic webserver using HTTP(S) and SSH (ports 80, 443, & 22). After all, most VPS only need these starting ports rules and can add mail or game ports later as need.
So far I have the following ruleset and I was wondering if anyone knows of a better script or any improvements that could be added.
*filter
# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT
# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allows all outbound traffic
# You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT
# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
# Allows SSH connections (only 4 attempts by an IP every 3 minutes, drop the rest)
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j DROP
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT
COMMIT
iptables is one of the most important parts of securing your box (also see fail2ban) and yet there are many people like myself that have trouble understanding everything that goes into making a secure basic firewall for our servers.
What is the most secure way to only open the basic ports needed for a webserver?
Update: cyberciti.biz has another iptables script that looks pretty good.
Also, rather than using Denyhosts or fail2ban you could use iptables itself to block bad repeated attempts at SSH.
The most secure way to work with iptables is close everything and only open what you need. I'm kind of distracted, so I always try to be as lazy as possible, so I do not make mistakes which can lead the server to be unsecure.
I use this one, only a little bit of varible assignment must be done in order to make it work.
I've been using it for some time , and any kind of modification will be very appreciated if it makes it easier to administrate.
This looks pretty good, but you could tighten things down a little bit more. The -s flag is the source IP or domain name, and you add "-s 198.23.12.32" or whatever your IP address is to only allow SSH from your source IP. You can also choose a range of source IPs by using CIDR style notation.
You should use caution when logging denied calls. Your server's IP address will get scanned by bots, script kiddies, etc, and the log file could get large rather quickly. Unless you're trying to diagnose a specific problem that you think might be related to someone trying to break your firewall, I would remove this option.
You could also tie in fail2ban to iptables for a pseudo-IDS. fail2ban will scan your log files and can block an IP if they attempt to force their way into your system. For example, if a certain IP address fails to login to SSH 5 times, you can lock them out for an entire day. It also works on FTP and lots of others (including bad bots hitting Apache).I use it on all of my servers to provide some extra cushion from brute-force attacks.
I would say this is a pretty good firewall, except that it is geared towards stopping inbound traffic, and not focused on egress or outbound traffic. It is in many cases just as important to focus on connections outbound from a box as those inbound. In the unfortunate case that the machine is actually exploited, it would be nice to be able to prevent downloading additional root kits, or connecting to command and control nodes, or whatever.
BillThor started talking about this above, but I'm just answering with specific examples. One of the nice things about iptables is that it can remember connection state, this can have performance implications on heavily trafficked sites but you could change your inbound access on http/https to only allow reply on established connections for example, or specifically limit certain unprivileged users from having outbound access at all. Then your outbound rules would have RELATED,ESTABLISHED clauses which would prevent a whole host of ancillary attacks and slow down the ones that require a secondary stage to actually exploit a box, which is very common.
Finally, I would say that it is better to set your iptables policy -P DROP rather than have an appended REJECT at the end. It is mostly a matter of preference, but can reduce mistakes when appending to chains with existing rules instead of inserting or flushing/resetting.
Take a look at Shorewall. The single interface default configuration would be a good starting point. It is easy to configure, and has macros for things like SSH and Web access. It can be configure to lock down the server to the desired level when the firewall is shutdown. With Shorewall-lite, you can run a firewall build on another server. Logging is easy to configure to the desired level.
For a basic HTTP server you want open incoming access to port 80 and port 443 if you use HTTPS. SSH incoming access from a few restricted addresses is usually desired. You may want to lock down outgoing access as well. Open the firewall to required servers and services only. NTP and DNS should be opened, as well as a channel to fetch patches.