The only major hole I can see is IPv6. You'll need ip6tables for that. If any of your services listen on IPv6 (and many of them, including ssh, listen on IPv6 by default) then an attacker can use that to completely bypass all the rules you have above. Networks will use IPv6 in preference to IPv4 when it is available.

Assuming your OUTPUT policy is DROP, you have restricted IPv4 pretty well.

Skipping the RELATED option could mean that you get timeout rather than instant rejects when a service goes down and stops listening as I understand TCP RST packets are neither NEW or ESTABLISHED in this context.


To answer the update on your question: For when it's not only used by you.

No matter how careful we all are, the possibility always remains that we've missed something or we are momentarily careless and we allow someone else some measure of control over our box. The first thing an attacker will do once they have a toe-hold is to download a privilege escalation kit, a rootkit, their command and control system and whatever they actually want to run on the box. Restricting outbound connections means they can't download that privilege escalation kit meaning they are stuck running as the Apache user or the Git user or whatever they managed to attack. Without root privileges, they can't hide and they can't modify the firewall. This won't stop an attacker forever but it might stop him for long enough for you to notice he's there or frustrate him enough that he gives up and goes somewhere easier.

The rules above mean that a remote file inclusion attack will only work if the remote file is hosted on SSL. If you put an proxy server in between this box and the internet and have it only allow certain URL patterns, you can stop RFI in its tracks while still allowing normal operation. This is defense in depth.


In addition to the comments posted by the other guys about missing OUTPUT chain and repeated ESTABLISHED rules, you can restrict protocols such as SSH (TCP/port 22) to specific IPs if applicable.

To check your setup, you can try NMAP to check for open ports. This can be more useful in case your firewall rules becomes more complicated.


You should run the script from a pre-up line in /etc/network/interfaces (see man 5 interfaces)so that the firewall rules are in place BEFORE the network is available and services are started. rc.local is the very last thing run, so there is an unnecessary window of time where things are unprotected.

Its also wise to keep in mind that this type of thing you are doing is not some kind of magic bullet. If there are other services you are staring but are trying to prevent access to, you shouldn't be starting them in the first place. If the idea here is to prevent access to services which you don't intend to start, this is implying that there are untrustworthy people already doing stuff on your machine? In which case you've already lost, and its safe to assume that at the point that you have malicious users running code on your box, that your firewall rules could also be manipulated.


i open-sourced iptables-boilerplate on github some days ago. its essentially a good set of predefined iptable-rules and is extensivly commented.

maybe using and reading could help you