I am installing a new centos 5.4 server and I would like to have a set of clean rules for mu iptables to startup.

What would be the good rules to start with?

Is this a good starting point :

# Allow outgoing traffic and disallow any passthroughs

iptables -P INPUT DROP
iptables -P FORWARD DROP

# Allow traffic already established to continue

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow ssh, ftp and web services

iptables -A INPUT -p tcp --dport ssh -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport ftp -i eth0 -j ACCEPT
iptables -A INPUT -p udp --dport ftp -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport ftp-data -i eth0 -j ACCEPT
iptables -A INPUT -p udp --dport ftp-data -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -i eth0 -j ACCEPT

# Allow local loopback services

iptables -A INPUT -i lo -j ACCEPT

# Allow pings

iptables -I INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -I INPUT -p icmp --icmp-type source-quench -j ACCEPT
iptables -I INPUT -p icmp --icmp-type time-exceeded -j ACCEPT

For what is this rule :

iptables -A INPUT -p tcp --dport domain -i eth0 -j ACCEPT


It will be a web server with FTP (required), apache, SSH, mysql.

  • I use this simple rule .... Close everything and work backwards and open up what is needed. For a web server, port 80/443 are typically the only public facing services. Block everything else or limit access - for example limit ssh to specified IPs or private network. Dec 5 '11 at 20:17

Your IPTables rules seem to be mostly appropriate for your server. But I would suggest a couple of possible changes:

  • Unless you need to allow SSH, MySQL, and FTP access from the entire Internet, it would be much more secure to use the '--source' option to restrict access on those ports from certain approved IP addresses, only. For instance, to only allow SSH access from the IP address, you'd change the 5th rule to 'iptables -A INPUT -p tcp --dport ssh --source -i eth0 -j ACCEPT'. You'll probably need to add a separate rule for each individual IP address that you want to allow, see this question for more info on that: iptables multiple source IPs.

  • Unless this machine is running a DNS server, you'll probably want to block access to the 'domain' (53) port. To do this, just remove the line 'iptables -A INPUT -p tcp --dport domain -i eth0 -j ACCEPT'. (This should also answer your final question, BTW.) If you are actually running a DNS server, though, leave this rule in place.

  • If you need to allow remote MySQL client access over the network, you'll need to add the line 'iptables -A INPUT -p tcp --dport 3306 -i eth0 -j ACCEPT' to open up external access to the standard MySQL port. But DON'T do this unless it's really necessary--if you only need local MySQL access (for a PHP app running under Apache, say), you don't need to provide remote MySQL access. And unless you want to risk getting hacked, if you do open port 3306 to the network, make sure that you require strong passwords for all of the MySQL user accounts, and that your MySQL server packages are up-to-date.

  • One of your comments ('Allow ssh, dns, ldap, ftp and web services') mentions LDAP services, but there is no such rule in your configuration. This happens to me a lot when I copy an example configuration and modify it. It won't affect the function, but I would fix the comment, since misleading comments can cause indirectly by confusing you or another admin in the future.

In my experience, it's hard to come up with a perfect set of IPTables rules, but I think you're definitely on the right track. Also, good luck with learning more about IPTables--these rules can seem complex at first, but it's a very helpful skill for any Linux sysadmin to have.

  • 1
    Instead of allowing remote MySQL access through the firewall you can just make sure that everyone who needs access to the MySQL server has the right to make SSH port forwards.
    – ptman
    Mar 3 '10 at 18:15
  • SSH port forwards are a potential alternative to opening the port and locking down the MySQL permissions. But unless he's dealing with sensitive data and/or he's a high-profile target (which would make the encryption features of SSH useful), I don't see the advantage. After all, SSH tunneling has its own disadvantages, including: setup/config hassles; increased CPU utilization, and limiting bandwidth (due to OpenSSH's static buffer size). And what if he doesn't want all of his remote MySQL clients to have local logins? Mar 3 '10 at 19:14
  • As far as comments not matching the rules goes, the ICMP rules allow traceroutes, PMTU discovery, and other useful messages but they don't allow pings (echo-request and echo-reply). Mar 3 '10 at 20:53
  • Gerald, that's a good catch, I didn't even notice that. He should probably either change the comment to note that ping is NOT permitted, or he should add rules allowing ICMP echo request/reply traffic. Mar 8 '10 at 17:36

Definitely look to restrict your outbound traffic too.

I've seen plenty of cases where PHP exploits result in someone using 'curl' or 'wget' to fetch malicious code from elsewhere, then execute it on your server to join to a botnet.

If you do not expect Apache (as an example) to need to talk to other websites itself, restrict the traffic and save yourself a little pain down the line!


These rules are ready to be imported via "iptables-restore":

:INPUT DROP [20:2036]
:OUTPUT ACCEPT [93:16260]
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT -m comment --comment "allow ICMP: echo-reply"
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT -m comment --comment "allow ICMP: echo-request"
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT -m comment --comment "allow ICMP: destination-unreachable"
-A INPUT -p icmp -m icmp --icmp-type 4 -j ACCEPT -m comment --comment "allow ICMP: source-quench"
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT  -m comment --comment "allow ICMP: time-exceeded"
-A INPUT -i lo -j ACCEPT -m comment --comment "allow input from the loop-back adapter"
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT -m comment --comment "allow SSH: ssh"
-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT -m comment --comment "allow DNS: domain"
-A INPUT -i eth0 -p tcp -m udp --dport 53 -j ACCEPT -m comment --comment "allow DNS: domain"
-A INPUT -i eth0 -p tcp -m tcp --dport 21 -j ACCEPT -m comment --comment "allow FTP: ftp"
-A INPUT -i eth0 -p udp -m udp --dport 21 -j ACCEPT -m comment --comment "allow FTP: ftp"
-A INPUT -i eth0 -p tcp -m tcp --dport 20 -j ACCEPT -m comment --comment "allow FTP: ftp-data"
-A INPUT -i eth0 -p udp -m udp --dport 20 -j ACCEPT -m comment --comment "allow FTP: ftp-data"
-A INPUT -i eth0 -p tcp -m tcp --dport 3306 -j ACCEPT -m comment --comment "allow MariaDB/MySQL: mysql"
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT -m comment --comment "allow HTTP (apache/nxing/lighttpd)"
-A INPUT -i eth0 -p tcp -m tcp --dport 443 -j ACCEPT -m comment --comment "allow HTTPS (apache/nxing/lighttpd)"
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT  -m comment --comment "allow already established connections"

And just for the record...these default policies should be set too, IF the above iptables-restore is not used:

iptables -P INPUT DROP
iptables -P FORWARD DROP
  • I've edited your post -- StackOverflow is a question/answer format. Please read the FAQ: stackoverflow.com/faq Jul 10 '13 at 10:39
  • 1
    This will introduce performance issues, since the stateful rule appears last here, and should appear first since it matches the vast majority of packets. Jul 10 '13 at 19:13

Why do you allow ftp and dns? Does your server provide those services? FTP shouldn't really be used, except for some very specific use cases, use SFTP instead (not FTPS). Also, why specify all the other ports by symbolic names and http by numeric 80? Did you just copy this from somewhere else? No copying and advise is going to make up for lack of understanding. Make sure you understand TCP, IP, firewalls, and the protocols of the services you are going to provide.

  • I don't mean to offend, ptman, but I think your answer could be seen as being somewhat discourteous and condescending. Also, you aren't really answering the question. If the asker lacks understanding, don't you think it would be better to speak respectfully, and to give him some specific education on the topic? Mar 3 '10 at 17:09
  • You are probably correct. My comments can sound negative, but weren't meant as such. I was trying to list questions that would trigger relevant thought processes. And since I don't know the base level of understand I didn't start writing a textbook. But you are absolutely correct about the unhelpful tone. Luckily you've written a much more helpful answer.
    – ptman
    Mar 3 '10 at 18:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.