Below is the result of iptables-save
from a Ubuntu Linux server. My question is, is there anything wrong or sub-optimal about it?
For example I believe the rules are processed in order, so should the rules for ports 80 and 3306 (www/mysql) be moved to the top?
Also, what do the rules after the DROP do? They seem similar to rules further above.
# Generated by iptables-save v1.4.1.1 on Sun Feb 13 16:11:59 2011
*filter
:INPUT DROP [1:52]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [496336:22258327]
-A INPUT -p tcp -m tcp --dport 10000 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -m state --state NEW -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -m state --state NEW -j ACCEPT
-A INPUT -p udp -m udp --dport 69 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 69 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 110 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 143 -m state --state NEW -j ACCEPT
-A INPUT -p udp -m udp --dport 123 -m state --state NEW -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 20 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 21 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 3306 -m state --state NEW -j ACCEPT
-A INPUT -p udp -m udp --dport 3306 -m state --state NEW -j ACCEPT
-A INPUT -j DROP
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Sun Feb 13 16:11:59 2011
I would probably move the
RELATED,ESTABLISHED ... ACCEPT
rule on the INPUT chain to the very top of that chain. Unless most of your connections are extremely short-lived, I'd wager that the vast majority of incoming packets are going to be part of a connection and should be ACCEPTed by that rule.To get a better feel for where packets are landing in your ruleset, you can run this:
and pay particular attention to the packet and byte counts. You will probably notice that the rule I mentioned above has claimed the most packets by a rather large margin. If any other rules have matched a significant number of packets, you could optimize your ruleset by moving them up ahead of less "popular" rules.
Finally, I notice that your OUTPUT chain has ACCEPT policy. That makes the ACCEPT rules on the OUTPUT chain redundant, and they should be removed. Similarly, since your INPUT chain policy is DROP, the final DROP rule on the INPUT chain is unnecessary.
In general arranging the rules so that you exit the firewall quickly is a good thing. If most of the traffic is to ports 80 and 3306 then they should as you suggest be higher up the list for the INPUT table.
Iptables works on tables. You have 3, INPUT, FORWARD and OUTPUT. The DROP command is in the INPUT table. The rules after the DROP are for the OUTPUT chain so they will be processed for outgoing packets only. They could be removed as the policy on the OUTPUT table is to ACCEPT and they are ACCEPT rules.
-A INPUT -p tcp -m tcp --dport 10000 -j ACCEPT
not divided into NEW / REL, EST as others?--state NEW
is redundant, why making CPU decides whether it wasNEW
each time(?). You'd better create additional chain 'INPUT.NEW', and use single-A INPUT -m state --state NEW -j INPUT.NEW
to pipe packets into it.-m multiport
.RELATED
anyway.NEW,RELATED,ESTABLISHED
. Permit it w/o sub-dividing.Looks good. I would drop the accept on port 20 as it should be handled as a related packet to an FTP connection. I usually put port 123 as the first check to minimize latency for NTP.
For the OUTPUT chain only DROP or REJECT rules would make sense. The existing output rules don't do anything but duplicate the policy.
You may want to look at your counters and adjust the ordering of rules accordingly.
Consider using different chains for new connections on each interface.
Consider logging non-accepted packets.
Using a tool like Shorewall to build the firewall might make it easier to get everything in place.
Rather than using one explicit rule per protocol/port combination, I'd strongly suggest using
ipset
.Make 2 sets, one each for TCP and UDP:
Populate each set:
You can then simplify your port-related rules into just 2 rules:
Note: I'm removing
-m state --state NEW
matches. I mean, what for? After the-m state --state RELATED,ESTABLISHED
rule, all packets are either NEW or INVALID.Note 2: Ubuntu's
ipset
package is bollixed; you must download and install from source. I've explained how in my blog. You can read it here: http://pepoluan.posterous.com/powertip-howto-install-ipset-on-ubuntu .