This is a follow up to a previous question where I asked whether my iptables config is correct.
CentOS 5.3 system.
Intended result: block everything except ping, ssh, Apache, and SSL.
Based on xenoterracide's advice and the other responses to the question (thanks guys), I created this script:
# Establish a clean slate
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F # Flush all rules
iptables -X # Delete all chains
# Disable routing. Drop packets if they reach the end of the chain.
iptables -P FORWARD DROP
# Drop all packets with a bad state
iptables -A INPUT -m state --state INVALID -j DROP
# Accept any packets that have something to do with ones we've sent on outbound
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# Accept any packets coming or going on localhost (this can be very important)
iptables -A INPUT -i lo -j ACCEPT
# Accept ICMP
iptables -A INPUT -p icmp -j ACCEPT
# Allow ssh
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow httpd
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Allow SSL
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Block all other traffic
iptables -A INPUT -j DROP
Now when I list the rules I get...
# iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- any any anywhere anywhere state INVALID
9 612 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
0 0 ACCEPT all -- lo any anywhere anywhere
0 0 ACCEPT icmp -- any any anywhere anywhere
0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh
0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:http
0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:https
0 0 DROP all -- any any anywhere anywhere
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 5 packets, 644 bytes)
pkts bytes target prot opt in out source destination
I ran it and I can still log in, so that's good. Anyone notice anything major out of wack?
Looks good for the most part. The major thing is that you should probably use iptables-save and iptables-restore rather than repeated runs of iptables. The iptables-save/restore method gives you atomic bulk updates (like a database transaction), so you know that nothing can get in (or NOT get in) because your iptables changes were half-finished when the network packets arrived. Making this change will also let you dump the initial ACCEPT policies, so it just sets the preferred policy (preferably to DENY) and then the individual rules (exceptions which are ACCEPTed).
Aside from that, you might want to look at locking down ICMP a bit more (rather than just allowing everything). I've heard that some aspects of ICMP are quite dodgy these days. Personally, I don't think it's worth it, as so much diagnostic and traffic management stuff depends on ICMP.
About womble's "don't use iptables" remark: I wouldn't go so far as to say that you shouldn't use iptables (or iptables-save/restore) directly, but I would recommend looking at FERM instead. It's essentially just iptables, with a more expressive and less repetitive language, plus variable support. For instance, your iptables commands:
Would look more like this in ferm:
Much nicer, huh? ;)
Finally, do NOT run SSH on the default port of 22. Move it to another address (edit the config file, and reload sshd). You can do this even while connected over ssh, but it's best to have another access method when messing with ssh or firewall rules (console-based, as provided by virtual dedicated hosts). Also, look into setting up something like fail2ban eventually. But I wouldn't use it without a fixed IP (on my side) and specific firewall rules to allow me access no matter what, before any blocking that fail2ban does.
Looks good, a personal preference of mine would be to add
to these rules
And change the default policy on INPUT, FORWARD to DROP, making
redundant
I would say that if you're using iptables directly at all, you're not doing it right.