Configure iptables over SSH without getting locked out?

I need to provision servers via SSH, and in the process, configure iptables. More precisely, I want to run the following commands in this order:

iptables -F
iptables -P INPUT DROP
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT 
iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT 
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
iptables -t nat -A PREROUTING -p tcp --dport 25 -j REDIRECT --to-port 5000
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000
iptables -A INPUT -j DROP
iptables-save

How do I accomplish that without getting locked out? Can I apply those in batch?


I would probably save the rules in a new file, i.e /etc/iptables/new.rules and use the command iptables-apply to test them:

iptables-apply -t 180 new.rules

This way, the rules will be active for 180 seconds (-t = time) but not be saved unless you confirm the connection is still working as expected. In case of no interaction after 180 seconds, the rules will be reverted back to the previous state.


I assume the reason you think you'll be locked out is that you put in the default DROP rule before configuring the ACCEPT rules.

Run the commands through a single shell command like:

bash -c 'iptables -F; iptables -P INPUT DROP; ...'

The entire string will be sent and read before being processed and then the rules will be applied. Since the commands don't require input, they'll all process, and when you're done you'll still have access.


I usually do this:

1) I backup the old iptables configuration file:

cp /etc/sysconfig/iptables /etc/sysconfig/iptables.bak

2) Before trying the new settings I execute this command to make sure I can connect back if something in the new settings locks me out (basically I replace the old rules after 10/15 minutes):

echo "mv /etc/sysconfig/iptables.bak /etc/sysconfig/iptables && service iptables restart" | at now + 15min

3) Now I can safely modify iptables rules. If something goes bad I can connect back in 15 minutes.


If you want to avoid the situation that you are locked out for a moment (and avoid the risk that the firewall setup fails due to errors) a technical alternative is to avoid the table flush for INPUT. Replace iptables -F or iptables -F INPUT by

iptables -I INPUT 1 -p tcp -m tcp --dport 22 -j ACCEPT
while iptables -D 2 INPUT; do
  :
done
for chain in $(iptables -L -n | awk '/^Chain/ && $2 != "INPUT" { print $2 }'); do
  iptables -F "$chain"
done

Then define the rules as usual (just -A for INPUT though, no -I INPUT 1, please) and in the end remove the connection safety rule: iptables -D INPUT 1