28

I have this iptable rules:

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N fail2ban-ssh
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -j DROP
-A fail2ban-ssh -s xx.xxx.xx.xx/32 -j REJECT --reject-with icmp-port-unreachable
-A fail2ban-ssh -j RETURN
-A fail2ban-ssh -j RETURN

The lines

-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh

and

-A fail2ban-ssh -j RETURN

seems to be duplicated or written twice. How can I remove the duplicate?

0

8 Answers 8

21

List with line numbers and delete by number.

iptables --line-numbers --list

Then delete one rule using it's line number. Then repeat (line numbers change for following rules when one is deleted so re-list before deleting another).

iptables -D INPUT 6
2
  • 2
    Thanks for this buddy! Will accept this in a matter of minutes. Sep 15, 2014 at 13:48
  • Will this remain persistent after a reboot? Nov 16, 2016 at 17:05
23
iptables-save | uniq | iptables-restore

That is all you need really.

5
  • 8
    AFAICT, this will only remove adjacent duplicates. It will fail to remove non-adjacent duplicates.
    – user61015
    Jan 16, 2018 at 3:36
  • @sampablokuper Then just pipe to sort -u before uniq. Oct 19, 2020 at 21:58
  • 3
    @SkippyleGrandGourou you need to be careful about sorting everything. In the example above, would that not reorder the -j RETURN to before the -s xx.xxx.xx.xx/32 -j REJECT rule, meaning the latter rule would never be seen?
    – mwfearnley
    Oct 29, 2021 at 9:30
  • 2
    @mwfearnley Ha ! You’re right, indeed. Oct 29, 2021 at 13:46
  • 1
    @SkippyleGrandGourou sort's -u flag already removes duplicates, so there's no need to use uniq at all after that.
    – nullromo
    Feb 15 at 22:07
6

If you only want to delete double lines that are directly one after another you can export, unify and reimport it with

mkdir ~/tmp
iptables-save > ~/tmp/iptables.conf
uniq /tmp/iptables.conf > ~/tmp/iptables_new.conf
iptables-restore < ~/tmp/iptables_new.conf

If you want to delete other lines use an editor on ~/tmp/iptables.conf before you reimport it the same way.

Check your new rules with

iptables-save
2
  • If stripping adjacent duplicates is what you seek, then Ricky Neff's answer is more secure, because it avoids exposing firewall the rules to other users who have access to /tmp.
    – user61015
    Jan 16, 2018 at 18:10
  • 1
    thx, you are right, you shouldn't use /tmp cause it is world-readable. I changed it to ~/tmp
    – rubo77
    Jan 16, 2018 at 19:17
4

A comment to fail2ban: fail2ban seems to add its iptables rules itself. So you should not store these rules with e.g. iptables-save. Then after a reboot the rules will be doubled (your saved rule + the rule added by fail2ban).

3

Delete all duplicated lines except COMMIT

/sbin/iptables-save | awk '!COMMIT||!x[$0]++' | /sbin/iptables-restore
2
  • Didn't made any changes with "!COMMIT||" part! But in my iptables-save I had COMMIT only at the bottom. So it worked perfectly. But still wondering what was wrong.
    – user109764
    Feb 10, 2021 at 15:49
  • Shouldn't it be awk '/COMMIT/||... to keep the COMMIT lines? I think !COMMIT would keep every line, since the COMMIT variable is never set.
    – mwfearnley
    Oct 29, 2021 at 9:26
0

I am using such a small bash script which runs through cron.

     #!/bin/bash 
         readarray -t tabl_lines <<< "$(iptables -nL INPUT --line-number | grep "fail2ban-ssh")"
            i=''
            for tline in "${tabl_lines[@]}"
            do 
            #skip the first result
            if [ -n "$i" ]; then
            sudo iptables -D INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
            # if necessary, you can erase and other rules, 
            # because they usually repeat the same number of times
            # sudo iptables -D INPUT -p tcp -m multiport --dports 21 -j fail2ban-vsftpd
save_iptables=yes
            else 
            i=start_remove
            fi
            done
if [ "$save_iptables" == "yes" ]; then
/sbin/service iptables save
fi
0

Kudos to Igor for his script. I feel it's useful:

#!/bin/sh
/sbin/service iptables save
/sbin/iptables-save | awk '/^COMMIT$/ { delete x; }; !x[$0]++' > /tmp/iptables.conf
/sbin/iptables -F
/sbin/iptables-restore < /tmp/iptables.conf
/sbin/service iptables save
/sbin/service iptables restart
if [ -f /tmp/iptables.conf ] ; then /bin/rm -f /tmp/iptables.conf ; fi

Caveat: works only on Redhat / Centos, or other distro with iptables service. Thus my shorted mod for cron/one time use is:

#!/bin/sh
/sbin/iptables-save | awk '/^COMMIT$/ { delete x; }; !x[$0]++' > /tmp/iptables.conf
/sbin/iptables -F
/sbin/iptables-restore < /tmp/iptables.conf
if [ -f /tmp/iptables.conf ] ; then /bin/rm -f /tmp/iptables.conf ; fi
0

Here's an improved version using awk. This removes all duplicates in the -A rules, keep the rest of the strucuture correct, which is probably what you want :

iptables-save|awk '{if(/^-A /){if (!a[$0]++)print $0}else if (!/^-A /){print $0}}'|iptables-restore

You must log in to answer this question.

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