Iptables: Invert IP, Protocol, Or Interface Test With !

How do I invert a protocol or ip address test while writing iptables based shell scripts?

The iptables command comes with ! operator. The most of these rules can be preceded by a ! to invert the sense of the match. A match can be:

  1. Source or dest ip address
  2. Interface name
  3. Protocol name etc


The following will match all protocol except UDP:

iptables -A INPUT -p ! UDP

The following match allows IP address range matching and it can be inverted using the ! sign:

iptables -A INPUT -d -j DROP
iptables -A OUTPUT -d ! -J ACCEPT
# we trust so skip it
iptables -A OUTPUT -s ! -J DROP

The exclamation mark inverts the match so this will result is a match if the IP is anything except one in the given range

iptables -A INPUT -s ! -p tcp --dport 80 -J DROP

You can skip your own ip from string test:

iptables -A FORWARD -i eth0 -p tcp ! -s --sport 80 -m string --string '|7F|ELF' -j DROP

Accept port 22 traffic on all interfaces except for eth1 which is connected to the Internet:

iptables -A INPUT -i !eth1 -p tcp --dport 22  -j ACCEPT

Recommended readings:

man iptables

🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 6 comments so far... add one

CategoryList of Unix and Linux commands
Disk space analyzersdf ncdu pydf
File Managementcat cp mkdir tree
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network UtilitiesNetHogs dig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
6 comments… add one
  • Zdenek Styblik Jan 29, 2010 @ 20:04

    Recently, iptables changed syntax in favor of prefixing, so:
    iptables -A INPUT ! -s; << correct
    iptables -A INPUT -s !; << also correct, but iptables warns you this is a deprecated way to do. so it's question for how long is it going to work.
    This prefixing applies for everything, not just source IP address.

  • 🐧 nixCraft Jan 30, 2010 @ 9:06


    You may be right about syntax but most of our systems are running on RHEL 4/5 or CentOS 4/5 and it is not updated by Red Hat. I guess RHEL 6 will come with latest version.

  • Zdenek Styblik Feb 2, 2010 @ 17:04

    Ok, sorry for the post then.

  • Bryan May 5, 2013 @ 14:11

    Wouldn’t you know it? It’s now three years and some days later and now only the prefix ! version of syntax works (squid3). :-P

  • Mr. IP Jun 20, 2015 @ 13:07

    Now it’s 2015

    iptables -A MYCHAIN -i !eth1 -s -j DROP; iptables -L MYCHAIN -n -v


        0     0 DROP       all  --  !eth1  *

    no errors but it doesn’t work

    iptables -A MYCHAIN ! -i eth1 -s -j DROP; iptables -L MYCHAIN -n -v

    also yields:

        0     0 DROP       all  --  !eth1  *

    but this time itworks!

    This is a very bitchy pitfall, take care. Only if you do iptables -L -n -vv with double v, you’ll be able to see the difference between “-i !eth1” and “! -i eth1”.

  • Darius Oct 9, 2015 @ 14:54

    iptables -A INPUT -m set –set ! geoblock src -j DROP
    Using intrapositioned negation (`–option ! this`) is deprecated in favor of extrapositioned (`! –option this`).

    Somebody have any idea what I’m doing worng here ?

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Still have questions? Post it on our forum