Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I need to add a rule to iptables to block connections to a tcp port from the Internet.

Since my script may be called multiple times and there is not a script to delete the rule, I want to check if an iptables rule already exists before inserting it - otherwise there will be a lot of dup rules in the INPUT chain.

How can I check if an iptables rule already exists?

share|improve this question

migrated from stackoverflow.com Nov 22 '11 at 3:14

This question came from our site for professional and enthusiast programmers.

3 Answers 3

up vote 11 down vote accepted

There is a new -C --check option in recent iptables versions.

# iptables -C INPUT -p tcp --dport 8080 --jump ACCEPT
iptables: Bad rule (does a matching rule exist in that chain?).
# echo $?
1

# iptables -A INPUT -p tcp --dport 8080 --jump ACCEPT

# iptables -C INPUT -p tcp --dport 8080 --jump ACCEPT
# echo $?
0

For older iptables versions, I would use Garrett suggestion :

# iptables-save | grep -- "-A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT"
share|improve this answer

Just list and search for it?

iptables --list | grep $ip

... or however you have the rule specified. If you use grep -q it won't output anything, and you can just check the return value with $?

share|improve this answer
3  
I would suggest iptables-save|grep $ip instead as it is a more easily parseable format, especially in a script. You can check the exact syntax of the command too if you want. –  Garrett Nov 22 '11 at 4:21
    
Neither of these actually answers the question, because iptables-save|grep $ip could very well match multiple rules. Possibly iptables-save could be used to check for the complete rule specification, but that's still a bit of a hack: the format returned by iptables-save may not match exactly the rule in the script. iptables-save may generate the options in a different order, add things (like -m tcp), and so forth. –  larsks Jun 24 '12 at 1:45

The new -C option is not satisfactory, because it is open to a time-of-check-to-time-of-use (TOCTTOU) race condition. If two processes try to add the same rule at around the same time, -C will not protect them from adding it twice.

So, it is really no better than the grep solution. An accurate text processing job over the output of iptables-save can work as reliably as -C, since that output is a reliable snapshot of the state of the tables.

What is needed is an --ensure option which atomically checks and adds a rule only if it doesn't already exist. Moreover, it would be nice if the rule is moved to the correct position where a new rule would be inserted if it did not exist already (--ensure-move). For instance if iptables -I 1 is used to create a rule at the head of a chain, but that rule exists already in the seventh position, then the existing rule should move to the first position.

Without these features, I think a feasible workaround is to write a shell script loop based on this pseudo code:

while true ; do
  # delete all copies of the rule first

  while copies_of_rule_exist ; do
    iptables -D $RULE
  done

  # now try to add the rule

  iptables -A $RULE # or -I 

  # At this point there may be duplicates due to races.
  # Bail out of loop if there is exactly one, otherwise
  # start again.
  if exactly_one_copy_of_rule_exists ; then
    break;
  fi
done

This code could spin around; it does not guarantee that two or more racers will be out within a fixed number of iterations. Some randomized exponential backoff sleeps could be added to help with that.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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