I need to delete some rules with same comment.
For example I have rules with comment = "test it", so i can get list of them like this:
sudo iptables -t nat -L | grep 'test it'
But how can i delete all PREROUTING rules with comment 'test it'?
UPD:
As #hek2mgl said, i can do something like this:
sudo bash -c "iptables-save > iptables.backup"
sed -i '/PREROUTING.*--comment.* "test it"/d' iptables.backup
sudo iptables-restore < iptables.backup
sudo rm iptables.backup
But between save and restore could be changes in iptables, so after restore there will be problems =/
You can use the following command:
iptables-save | sed -r '/PREROUTING.*comment.*test it/s/-A/iptables -D/e'
iptables-save will return iptables commands that can be executed to return the current state of the firewall after a reboot or whatever.
Meaning it will contain lines like:
...
-A PREROUTING -p tcp -m tcp --dport 25 -j ACCEPT -m comment --comment "test it"
...
The sed command searches for lines containing PREROUTING.*comment.*test it (should be good enough) and prepends the term iptablesplus replaces -A by -D since -D deletes a rule. The result of the replacement operation get's then executed using the e command. The e command is a GNU extension to sed.
Note: If you want to print the command in addition to simply executing it you can use s/-A/iptables -D/pe.
Yet another way to Remove by comment:
NOWRULES=$(iptables --line-number -nL INPUT | grep comment_here | awk '{print $1}' | tac)
for rul in $NOWRULES; do /sbin/iptables -D INPUT $rul; sleep 0.1; done
The best way to remove comment-based rules from iptables is:
iptables-save | grep -v COMMENT | iptables-restore
it cleans all rules with matching comment. As for me, I use this method to add ruleset that needs to be completely removed later.
If you neeed only PREROUTING chain to be touched, add some prefix or suffix to your comment like preroute_COMMENT upon rule creation to make difference inside COMMENT identified ruleset
Related
I want to delete all iptables DROP rules from a bash script.
This is my script:
#!/bin/bash
# Remove all DROPs.
######################################################################
#_____________________________________________________________________
iptables="/sbin/iptables"
######################################################################
#_____________________________________________________________________
echo "[*] Removing all DROPs ..."
IFS_OLD=$IFS
IFS=$'\n'
rule_list=$(${iptables} -S | grep 'DROP$')
for drop_rule in ${rule_list}; do
undrop_rule=$(printf -- "${drop_rule}\n" | sed 's#^-A#-D#')
printf "[-] ${iptables} ${undrop_rule}\n"
${iptables} -v ${undrop_rule}
[ $? == 1 ] && echo "[E] Unable to delete DROP rule." && exit 1
done
IFS=$IFS_OLD
######################################################################
#_____________________________________________________________________
printf '\n\n'
${iptables} -S
######################################################################
#_____________________________________________________________________
But the output is:
[*] Removing all DROPs ...
[-] /sbin/iptables -D INPUT -s 209.126.1.2/32 -i eth0 -j DROP
all opt -- in * out * 0.0.0.0/0 -> 0.0.0.0/0
iptables: Bad rule (does a matching rule exist in that chain?).
[E] Unable to delete DROP rule.
Why ?
If I run manually the command:
/sbin/iptables -D INPUT -s 209.126.1.2/32 -i eth0 -j DROP
it work.
Thanks, BuDuS.
In your script, your IFS is still set to a newline by the time the iptables is executed. Hence bash can't word-split your command arguments.
I would set back IFS=$IFS_OLD as soon as the modified value is not needed anymore, which is probably after the assignement to rule_list.
I use the tail command on apache2 access_log, then by piping that output to cut I can get the ip address in real time, but then I need to process each line in real time with iptables.
I try to do that this way:
tail -f access_log | cut -d' ' -f 1 | xargs iptables -A INPUT -j DROP -s
But it does not work.
How to call iptables for each line in real time?
I need help with the following Bash v4.1.2 script.
#!/bin/bash
IP=$1
IPTABLES=/sbin/iptables
$IPTABLES -I INPUT -s $IP -j DROP
echo $IPTABLES -I INPUT -s $IP -j DROP |wall
The variables, IP and IPTABLES, get populated in the echo but the line above is not executed. The echo outputs...
/sbin/iptables -I INPUT -s 1.2.3.4 -j DROP
...which is syntactically correct and works if executed manually.
I don't know Bash so I'm struggling to debug this elementary script. I see some scenarios where commands are left bare as I have mine and some that are wrapped in $() (with and without quotes). I've also tried using backticks and quoting various parts of the command. The echo piped through wall only exists for debugging.
I found a basically identical post at Bash script commands not working in cron. My script is not running from cron though.
=== EDIT ===
Added for #Barmar
[root#server tmp]# bash -x /bin/netfilter-drop.sh
+ IP=1.2.3.4
+ IPTABLES=/sbin/iptables
+ /sbin/iptables -I INPUT -s 1.2.3.4 -j DROP
+ wall
+ echo /sbin/iptables -I INPUT -s 1.2.3.4 -j DROP
[root#server tmp]#
Broadcast message from root#server (Thu Dec 29 12:46:44 2016):
/sbin/iptables -I INPUT -s 1.2.3.4 -j DROP
^C
[root#server tmp]#
I had initially only given sudo access to run the posted Bash script. The problem was not the script, rather it was permissions. I needed to give additional sudo access to run iptables in my sudoers. Fixed.
I'm running Kali on a computer that has port forwarding so I can access it while away from my desk. Upon looking at /var/log/auth.log I find a number of IP addresses that have been trying to log in which I don't recognise. I've managed to extract all the IPs and put them in a file, and want to run a script to block them using iptables. So far, I've come up with this, but it's not working:
#!/bin/bash
NUMBEROFIPS=cat "ipaddresses.txt" | wc -l
for i in `seq 0 $NUMBEROFIPS`;
do
IP=awk 'NR==$i' ipaddresses.txt
iptables -A INPUT -s $IP -j DROP
done
What am I doing wrong?
I suggest:
#!/bin/bash
while IFS= read -r ip; do
iptables -A INPUT -s "$ip" -j DROP
done < ipaddresses.txt
or
xargs -I {} iptables -A INPUT -s {} -j DROP < ipaddresses.txt
I'm pretty new to setting up game server but I want to block rcon to every ip except the ones that are whitelisted.
First I'm gonna use this trhough SSH:
iptables -A INPUT -p tcp --destination-port 27015 -j LOG --log-prefix "SRCDS-RCON " -m limit --limit 1/m --limit-burst 1
iptables -A INPUT -p tcp --destination-port 27015 -j DROP
After that I want that when a user runs a bash script or something similar, it detects the user IP and add it to the whitelist automatically.
How can I do this?
Assuming :
the bash script is run on the server
the users logs in using ssh
You could create an ipset :
First, add this rule in iptables :
iptables -A INPUT -i eth0 -m set --match-set whitelist src -p tcp --destination-port 27015 -j ACCEPT
Then create a set :
sudo ipset -N whilelist iphash
Finally, add a script like this, using SSH_CONNECTION environment variable :
#!/bin/bash
USER_IP=$(echo $SSH_CONNECTION | cut -f1 -d' ')
sudo ipset -A whitelist $USER_IP
You could even add those two lines at the end of /root/.bash_profile so it gets done automagically when someone connects as root.
However, this assumes your friends are connecting as root via ssh. Since this is not desirable, you could use a temporary directory to hold the ip addresses, and add a cron job to fill the ipset hash :
Create /etc/cron.d/check_ipset with :
* * * * * root /usr/local/bin/check_ipset
Create /usr/local/bin/check_ipset (and chmod 700) :
#!/bin/bash
for i in `cat /tmp/ipset_pending | sort -u`; do
ipset -A whitelist $i
done
cat /dev/null > /tmp/ipset_pending
Add this to every user's .bash_profile :
...
echo $SSH_CONNECTION | cut -f1 -d' ' >> /tmp/ipset_pending
...
Didn't test, so YMMV, but this should be close enough.