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:
- Source or dest ip address
- Interface name
- Protocol name etc
Examples
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 192.168.0.0/24 -j DROP iptables -A OUTPUT -d ! 202.54.1.2 -J ACCEPT # we trust 202.54.1.5 so skip it iptables -A OUTPUT -s ! 202.54.1.5 -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 192.168.1.0/24:
iptables -A INPUT -s ! 192.168.1.0/24 -p tcp --dport 80 -J DROP
You can skip your own ip from string test:
iptables -A FORWARD -i eth0 -p tcp ! -s 192.168.1.2 --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
🐧 6 comments so far... add one ↓
Category | List of Unix and Linux commands |
---|---|
File Management | cat |
Firewall | Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04 |
Network Utilities | dig • host • ip • nmap |
OpenVPN | CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04 |
Package Manager | apk • apt |
Processes Management | bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time |
Searching | grep • whereis • which |
User Information | groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w |
WireGuard VPN | Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04 |
Recently, iptables changed syntax in favor of prefixing, so:
iptables -A INPUT ! -s 192.168.1.0/24; << correct
iptables -A INPUT -s ! 192.168.1.0/24; << 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.
Zdenek,
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.
Ok, sorry for the post then.
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
Now it’s 2015
yields:
no errors but it doesn’t work
also yields:
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”.
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 ?