I need a script to add a users workstation ip to /etc/sysconfig/iptables and then run a service iptables reload. I need the same type of script for removing this rule from iptables.

I found the code below on a different forum.
It's somewhat what I need to do. It includes add and remove options, but instead of adduser it needs to reflect the iptable rule such as
iptables -I INPUT 1 -p tcp -s xxx.xxx.xx.xxx --dport 22 -m comment --**comment "testing for user1" -j ACCEPT.

The ip address itself needs to be passed as a parameter, so I can execute as

I am using RHEL version 6.4.
Any feedback is appreciated.


  echo "########## MENU ############\n"
  options=("add_user" "delete_user" "exit")
  select opt in "${options[@]}"
    case $opt in
      while [ 1 ]
        echo "1. Add user manually"
        echo "2. Add user via TXT file"
        read -p "Enter your choice" ch
        case $ch in 
            read -p "Enter user name : " useradd
            read -p "Enter user password:" passwd
            echo -e "Successfully added the user"
          if [ $(id -u) -eq 0 ]; then
            for row in `more $1`
              egrep "^$username" /etc/passwd >/dev/null
              if [ $? -eq 0 ]; then
                echo "$username exists!"
                exit 1
                pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
                useradd -m -p $pass $username
                [ $? -eq 0 ] && echo "User has been added to system!" || echo "Failed to add a user!"    
            echo "Only root may add a user to the system"
            exit 2
      read -p "Enter a User name to delete "UNAME
      userdel $UNAME
      echo "User $UNAME has been deleted"            
  • For some reason, the entire script didn't populate. Here is what I mean to enter:
    – user68384
    May 30, 2014 at 17:22

3 Answers 3


I've dealt with this a little differently. I keep a static iptables configuration that has jumps to special (initially empty) chains.

I then update those special chain asynchronously through a cron job. You could loop over a secondary data source that only has the ip addresses/hostnames and flushes and updates the chain every N minutes (or better, don't flush and delete the obsolete rules...)

This insulates your system's iptables a little by reducing the scope of what your automation is editing.

Note: You can edit the active rules in one of two ways:

 -D, --delete chain rule-specification
 -D, --delete chain rulenum
              Delete  one or more rules from the selected chain.  There are two versions of this command: the rule can be specified as a num-
              ber in the chain (starting at 1 for the first rule) or a rule to match.

If you use rulenumber, you dump the rules and pick which rule number based on its number. NOTE! This has an inherent race condition! If you specify rule-specification, you just specify all the same parameters that the rule has and it will be selected for deletion.

  • rrauenza, thank you very much for your feedback.
    – user68384
    May 30, 2014 at 18:31

There are no exact comparable tools to add or remove a single rule from the iptables ruleset.

Personally I'd use iptables-save to emit the current ruleset to a temporary file, then you can modify it using tools like awk or grep (for example use grep -v "$WORKSTATION_IP" to strip any potential duplicate already there, and then cat "$NEWRULE" >> $TMPFILE to append the new rule), then use iptables-restore to push the updated ruleset.

I'm not sure whether service iptables restart is required after a restore. I would expect not, but the man page is not explicit so I'd experiment.

You could write functions that simulate what you want. Maybe something like:

function add_iptables_rule {
    cat <(iptables-save) <(echo "$@") | iptables-restore

function del_iptables_rule {
    iptables-save | grep -v "$@" | iptables-restore

Automating this is a pretty risky however. Be very careful to test thoroughly. I'd start with iptables-save > /etc/iptables.backup so you can always go back to square one.

I like the idea of augmenting this approach by using separate rule chains as suggested by @rrauenza in a separate answer to limit the scope of your automation. Less to go wrong.


  • Bob, thank you very much for your feedback.
    – user68384
    May 30, 2014 at 18:30

Here the container in a simplified way... You need to fill with the code you want

# ----------------------------------------------------------------------- #
#   Here below it prints the help function                                #
#   Each time in printf                                                   #
#     (-) "\n" is a newline                                               #
#     (-) "\t" is tab (some spaces)                                       #
#   $0 is the the name that you give to the script                        #
#   $1 is the 1st parameter passed to script or function. In this case:   #
#     (+) Out of any function $1 is the 1st parameter given to the script #
#     (+) Inside a function $1 is the 1st given to the function           #
#                                                                         #
# ------------------------- # ------------------------------------------- #
                            #                                             #
Print_Help(){               #  Here it starts the function Print_Help()   #
    printf  "\n$1\n\n"      #  Here you are inside a function and $1 is   #
    printf  "SYNOPSIS \n"   #   the 1st parameter given to the function   #
                            #------------------------#                    #
    printf  "\t $0 [OPTION] [IP]\n\n"                # ------------------ #
    printf  "\t $0 -a   # to add     \n"   # <- hash(#) chars   #
    printf  "\t $0 -r   # to remove\n\n"   # <-   out of the    #
}                           #     ^                  #    "double quote"  #
                            # --- | ---------------- #  ----------------- #
                            #     +-- those hash(#) chars are inside the   #
                            #         "double quote" and they will be      #
                            #          printed as normal letters.          #
                            # ------------------------------------------- # 

  echo $IP #  Put here the code to add rule
  #  iptables -I INPUT 1 -p tcp -s $IP --dport 22 -m comment --**comment "testing for user1" -j ACCEPT.
  service iptables reload  # you need to run as root (or with sudo) 
  exit 0

  echo $IP  #  Put here the code to remove rule
  service iptables reload  # you need to run as root (or with sudo)
  exit 0 

if [[  $# != 2 ]] ;then #if the number of parameter is not 2
   #  Here we call the help function with 
   #+ "a single parameter in double quote" in this case:
   #+ "Error wrong number of parameters for $0"  
    Print_Help "Error wrong number of parameters for $0"
    exit 1

if [[ "$1" == "-a" ]] ; then  Add_Function  ; fi
if [[ "$1" == "-r" ]] ; then  Remove_Function  ; fi
# Here below we call again the help function with 
# "another single parameter in double quote" in this case
# "Error Unknown option $1 for $0 "  
# In the "main" $1 is the 1st parameter that you pass to the script
 Print_Help "Error Unknown option $1 for $0 "  
exit 2    

This is only an example to become familiar with shell script and selections. You can run it with a command line like sudo /bin/bash script.sh -a nnn.mmm.ooo.ppp, or -r, where nnn.mmm.ooo.ppp is the IP that you want to use. If you change the permission (e.g. chmod u+x script.sh) you can run with sudo ./script.sh -a nnn.mmm.ooo.ppp.

You have to fill the function with the code you need.
You can add other functions relative to other options. In that case maybe is more clean to use the case ... esac construction, as in the code proposed by Cristopher that includes some features that you will find useful as you finish the testing phase. From the check to see if the script is executed by root, in an interactive shell or not so to decide where to redirect messages, the definition of current date... Start by checking what you need and add all the optional step by step.

From man bash you can get a lot of interesting tips.
From the section COMMENTS:

In a non-interactive shell, or an interactive shell in which the interactive_comments option to the shopt builtin is enabled (see SHELL BUILTIN COMMANDS below), a word beginning with # causes that word and all remaining characters on that line to be ignored. An interactive shell without the interactive_comments option enabled does not allow comments. The interactive_comments option is on by default in interactive shells.

From the section QUOTING:

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows:

         **\n     new line**  
         **\t     horizontal tab**  
         \v     vertical tab  
         \\     backslash  
         \'     single quote  
         \"     double quote  
  • Hastur, thank you very much for the feedback. I am trying all suggestions that have been given.
    – user68384
    May 30, 2014 at 18:35
  • Put the pieces together and Up the answers you will find useful... I run to eat ;)
    – Hastur
    May 30, 2014 at 18:37
  • Haster, thank you. I have tried to put the pieces together, but I can't seem to make it work. For example, if I had ip address, where would it actually go in this script ? Would it go after echo $IP # Put here the code to add rule ? If so, can I then run the add function to this script as ./script -a ?
    – user68384
    May 30, 2014 at 19:16
  • Haster, I believe where you put the text "Put here the code to add rule" is where the command iptables -I INPUT 8 -p tcp -s $ --dport 22 -m comment --comment "testing for user1" -j ACCEPT should go ? Is this correct for adding a rule ?
    – user68384
    May 30, 2014 at 21:59
  • Yes you should write your code over there (instead of echo $IP). In the example you did you should write iptables -I INPUT 8 -p tcp -s $IP --dport 22 -m comment --comment "testing for user1" -j ACCEPT, note $IP is valid only in this example script and it filled with the value taken from the command line ( /bin/bash script.sh -a
    – Hastur
    May 31, 2014 at 16:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .