Opinions on `iptables` Setup

Latest response

In my environment, I'm responsible for deploying a number of network-centric applications that each have a number of port-exceptions that I have to put into my iptables config. Early on in the game, I just hopped into /etc/sysconfig/iptables and added individual rules to the default chains (i.e. INPUT and OUTPUT). Later, I decided, "you know, this would be a lot more organized and easy to track if I put all these rules for application "X" into their own chain and then reference that chain from the default chains. I also started to get into the habit of using the iptables comment-module to make the `iptables -L` output a bit more self-documenting. Between the comments and descriptive chain-names, my iptables configs became a lot easier for both myself and the people I turned the systems over to be able to tell what was going on in the iptables configuration.

 

Lately, I've started experimenting with the multiport module. It allows me to collapse a set of simple port-rules into one multiport rule. Down side is, it costs me some of my "self-documenting" capability (with discreet rules, you can comment each one individually - can't really do that with multiport rules). At any rate, I'm trying to decide what the best route going forward is. Do mutliport rules have any impact on performance - particularly in large rule-sets (that is, is there a performance advantage in multiport rules that might make me want to switch away from the "self-documenting" allowable via discreet, commented rules and/or chains). Overall, how do others organize their rules for functionality, clarity, sanity and supportability?

Responses

performance for the sake of readability and maintainability.

 

That's why I prefer to write my own iptables rules, instead of using some more "user friendly" tool for the task.

 

Thomas

Could you give us an idea of the size of the problem - the number of Rules that you foresee? This could turn out to be a nice exercise on some empericial analysis or semi-automatic optimisation of Rules' order.

I'm with Dhruv -- how many ports are we talking about?

Depending on the above, I might recommend using the multiport module to reduce things as much as possible. I haven't done any benchmarking, so take my opinion as just that (opinion), but the more rules there are, the more time it takes -- collapsing 15 or more port-matching rules into one multiport rule will make things faster. Whether that's measurable with your rulset and your traffic.... I obviously can't say.

With regards to comments: I've always done a mix of adding rules on the fly with the iptables cmd (and using iptables-save) and editing the config files by hand. That said, I generally prefer to manage the config files by hand for the very reason you created this post -- comments. I love my hash-marked comments. In any case, I'm curious to see what others have to say.

We have a couple of classes of servers that tend to have dozens of rules: our enterprise reporting tool servers and our backup servers. These applications' rules are in addition to the standard rulesets every production RHEL system gets to support administrative access methods, remote software push tools and remote monitoring tools.

To support the standard exceptions, those exceptions are put into a set of rule-groups with a standard name. Those standard rule-groups are then set as the first jump-out in the INPUT, FORWARD or OUTPUT chains.

In general, since I know that the most frequently-hit exceptions are associated with the application, I put the application's exceptions into their own rule-set(s). I then reference that applications' rule-set(s) as the first jump-out in the INPUT, FORWARD or OUTPUT chains (ahead of the standard rule-groups' jump-outs). I figure that it cuts down on the number of rules processed, makes things a tad more self-documenting and protects my applications' rules against changes to the enterprise standard rulesets.

While I'm up for using the multiport directive, where it makes sense (e.g., grouping all of the HTTP/HTTPS-related rules into one multiport rule), I'm not really looking to collapse everything into an unwieldy multiport rule. I make use of iptables comments to help SAs figure out "what the heck is this rule supposed to do" - too much collapsing would tend to work counter to the self-documenting. So, mostly asking the question to see if there was any more ways to optimize things - it's mostly an academic question

Well, if you are as much into readability as I am, and have a relatively straight forward firewall ruleset, then you may like firehol. It's a little known iptables generator that really makes firewalls manageable. It is incredibly important to limit outgoing traffic; something which very few people do. I feel as if there is little point in firewalls (when you have minimal services running) unless this is done. Firehol makes this really easy.

It also crucially allows you to test firewalls for 30 seconds; which can save one from being locked out with a bad rule. Just type "service firehol try"; and if you don't type "commit" within 30 seconds (eg. if the new firewall rules cut you off); it will revert back to the previous firewall state. Very handy.

It also makes iptables log unmatched (and thus autoblocked) packets (that can be kept in /var/log/firewall.log); which is useful to see when you are scratching your head wondering if the firewall is blocking a new app. 

As for the configuration, take this example of a web server:

# Web server firewall configuration
version 5
MAIL_SERVERS="mail.someplace.com mail2.someplace.com"
DNS_SERVERS="4.2.2.2 8.8.8.8"
SYSLOG_SERVERS="syslog.someplace.com"
IT_ADMIN_DATACENTER_DUDES="172.27.1.23 172.27.1.24"
IT_ADMIN_NETWORK="192.168.14.0/24"
WEB_SITES="xmlrpc.rhn.redhat.com rhn.redhat.com"
BLACKLIST="1.2.3.4"
# You can import an external file with variables with:
# source /etc/firehol/yourfile.conf

# Custom app, say incoming TCP ports 5601-5699 & UDP port 7000. Normal outgoing ports.
server_myweirdapp_ports="tcp/5601:5699 udp/7000"
client_myweirdapp_ports="default"

# Prefix "firehol:" to the logs
FIREHOL_LOG_PREFIX="firehol: "

# Blacklist IPs
blacklist full $BLACKLIST

interface eth0 lan
   # The following line protects against invalid fragments,
   # syn-floods (default 100 conns/sec), icmp-floods, malformed xmas, etc.
   protection strong

   # Incoming requests

   server ssh accept src "${IT_ADMIN_DATACENTER_DUDES} ${IT_ADMIN_NETWORK}" 
   server http accept
   server https accept
   server myweirdapp accept
   server ping accept

   # Outgoing requests
   client dns accept dst "${DNS_SERVERS}"
   client smtp accept dst "${MAIL_SERVERS}"
   client syslog accept dst "${SYSLOG_SERVERS}"
   client "http https" accept dst "${WEB_SITES}"

Wasn't that easy? Compare the above with a similar iptables script. You can also add your own iptables commands (eg. say a port redirect) at the end of the config file if firehol doesn't have a ready-made syntax for it.

If you're using a linux machine as a gateway; it's pretty easy as well:

...
# The following can only access POP3/IMAP/SMTP
MAIL_ONLY_IPS="10.2.13.4 10.2.13.9"
# The following can access everything
UNRESTRICTED_IPS="10.2.13.20"
interface eth0 lan
   server ssh accept src "$it_admin_ips"
   server squid accept
interface eth1 internet
   protection strong
   client all accept
router lan2internet inface eth0 outface eth1
   masquerade
   route "pop3 imap smtp" accept src "$MAIL_ONLY_IPS"
   route all accept src "$UNRESTRICTED_IPS"
...

Firehol hasn't been updated in years, but I haven't come across any bugs yet. It is also something that Red Hat would probably not vouch for; but it really is just a generator rather than a daemon. It also may not generate the most optimal rulesets; but I think for most servers the kernel CPU usage for the packet filter would be negligible.

Installing firehol in RHEL6 is easy. Install the firehol RPM. The configuration file is kept in /etc/firehol/firehol.conf. You can add firehol to the startup by using "chkconfig --add firehol". Remember to use "/etc/init.d/firehol try" to apply the firewall rules, which will preview the rules for 30 seconds while asking you to type "commit".

Firehol will log anything that is not matched by the configuration file. This is useful when finding out if something is being unnecessarily blocked. However, this often fills /var/log/messages with logs of packets, so you can add this to your firehol.conf:

# Prefix "firehol:" to the logs
FIREHOL_LOG_PREFIX="firehol: "

and create a separate log for this using rsyslog, by creating a file named /etc/rsyslog.d/firehol.conf :

:msg, startswith, "'firehol: " -/var/log/firewall.log
& ~

and then reloading rsyslog. You can add a logrotate script to keep the log sizes manageable (/etc/logrotate.d/firewall):

/var/log/firewall.log
{
   sharedscripts
   postrotate
      /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
   endscript
}

Firehol is easy enough to be understandable through examples. The only complex bit is adding unusual ports. If it is not mentioned here http://firehol.sourceforge.net/services.html , you will need to add this for incoming requests:
server_something_ports="tcp/1234"
client_something_ports="default"

Then you can use "something" as a service. Eg. "server something accept". See this for more info on adding services with multiple ports or protocols:
http://firehol.sourceforge.net/adding.html

I've seen some complex 300+ line iptables scripts translated into a few lines in firehol; it could make your life easier.

 

For the sake of "functionality, clarity, sanity and supportability," I would probably hesitate using multiport in a setup like yours. It has a limit of 15 ports (and a Range counts as two ports, the man page says) and its use only limited to certain cases. Documented Rules are priceless in times of trouble, and will save countless man-minutes over a greater period. Having said that, I would be tempted to think it is faster than a chain with 15 Rules. But do you need the extra nanoseconds? (Some businesses do!)

I would also give a think about how many rules, in %, would I really reduce by using multiports wherever possible.

Don't really have the latitude to load packages that: A) don't come from either the OS vendor or from the hosted application's vendor; and, most importanty, B) are given the thumbs-up by our security group.

Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.