Bash script commands not working in cron - linux

I have the following bash script to read logs and check for brute force then block violating IP using iptables.
#!/bin/bash
#blah blah run some commands to get the IP
iptables -A INPUT -s $p -j REJECT --reject-with icmp-host-prohibited
echo "BANNED $p FOR $COUNT ATTEMPTS" |wall
I did chmod 755. When I run the command from terminal it works fine. But when I setup a cronjob using crontab -e as root, it gets the IP and echos the "BANNED ..." message to the wall but nothing is added to the iptables list.
PS. I tried both #!/bin/bash and #!/bin/sh but no luck.

Try to provide full path to iptables e.g.
$ which iptables
/sbin/iptables
and than modify your script like that:\
#!/bin/bash
#blah blah run some commands to get the IP
/sbin/iptables -A INPUT -s $p -j REJECT --reject-with icmp-host-prohibited
echo "BANNED $p FOR $COUNT ATTEMPTS" |wall

Try the following solution should work for you:
cat cronjob
* * * * * /path/to/script.sh
Then:
chmod +x cronjob
chmod +x script.sh
/etc/init.d/crond start #redhat based servers like centos
/etc/init.d/cron start #debian based servers like ubuntu
crontab cronjob
NOTE: Sometimes you need to enter full path of IPTABLES command if your rules aren't added to /etc/sysconfig/iptables .

Related

Bash Script Command Not Executing

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.

Block list of ip addresses linux

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

Linux shell script not setting variables with bash -c "$com"

So, I wrote a shell script to kick people off of my wifi, but I'm having trouble getting it to work correctly. The main problem is that when I do bash -c "$com" it does not set the variable like it should. Any help would be appreciated.
echo "You must be connected to the network that you wish to kick the devices off"
gw=`route -n|grep ^0.0.0.0|cut -d' ' -f 10`
sudo nmap -sP $gw-254
long='read -p Enter_the_DEVICE_Bssid'
a=1
end=';'
oend='&'
outside='"'
thesudo='sudo'
num=1
deff='aireplay-ng -0 $number -a $bssid mon0 --ignore-negative-one -c'
read -p "How many devices do you want to kick: " ammount
counter=0
while [ $counter -lt $ammount ];
do
b=device
d1=$b$a
if [ $counter2 -gt $ammount ]
then
com="$com $long $outside$d1$outside"
counter=$(($counter +1))
else
com="$com $long $outside$d1$outside $end"
fi
comfin="$comfin $thesudo $deff $d1 $oend"
a=$(($a +1))
counter=$(($counter +1))
counter2=$(($counter +2))
done
vev="echo done"
comfin="$comfin $vev"
echo $com
bash -c "$com"
#Why does it not set the variables like it should?
echo $device1
echo $device2
echo $device3
#see it dosent say the variables when it is run.
sudo ifconfig wlan0 down
sudo macchanger -m 00:11:22:33:44:55 wlan0
sudo ifconfig wlan0 up
sudo airmon-ng start wlan0
sudo ifconfig mon0 down
sudo macchanger -m 00:11:22:33:44:55 mon0
sudo ifconfig mon0 up
#make sure you dont run it from the file, but from terminal so you can press ctrl z to stop the airodump
echo "make sure you dont run it from the file, but from terminal so you can press ctrl z to stop the airodump"
sleep 2
sudo airodump-ng mon0
read -p "Enter the NETWORK Bssid:" bssid
echo "Ok, its $bssid"
read -p "Do you want to single kick(1) or continuously kick(0)" number
echo "Ok, its $number"
sudo $comfin
sudo ipconfig stop mon0
bash -c "command" runs the command in a new bash process. Variable settings in that process won't have any effect on the original process. If you want to execute a command in the original process's environment, use eval:
eval "$com"
You probably should reconsider your whole approach, though. Dynamically assigning variables is usually a sign of an incorrect design. Instead of having separate variables device1, device2, device3, you should use an array.
read -p 'Enter the device' dev
device[$counter]=$dev

Adding my current IP to whitelist on iptables?

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.

How to use tee with sshpass in shell script

I have a situation that I need to append several lines(ip and hosts) from a file to /etc/hosts.
If I execute the below command
sshpass -p password cat /tmp/hosts |sudo tee -a /etc/hosts
I am getting
sudo: no tty present and no askpass program specified.
Sorry, try again.
sudo: no tty present and no askpass program specified. Sorry, try again.
sudo: no tty present and no askpass program specified. Sorry, try again.
sudo: 3 incorrect password attempts
Any alternatives to this?
How about
sudo -S sh -c 'cat /tmp/hosts >> /etc/hosts' <<< "password"
It's best to contain redirections for sudo within a subshell so that the elevated permissions are applied to opening the destination file.
ref: See https://stackoverflow.com/a/4327123/7552
The error you face comes from the fact that sshpass tries to send the password to cat, not to sudo. Your command line should have, in theory, looked rather like this:
cat /tmp/hosts |sshpass -p password sudo tee -a /etc/hosts
but sshpass does not forward stdin to sudo so this is a dead end. (sudo does forward stdin though that is why something like sudo tee works)
You could do something like this
sshpass -p password sudo echo "Hello"
cat /tmp/hosts | sudo tee -a /etc/hosts
so that the second call to sudo does not require a password.
Another option is to embed the cat and the redirection in a shell script and then just
sshpass -p password sudo ./thescript.sh
Or you can, as #glennjackman wrote, embed the cat and the redirection in a subshell:
sshpass -p password sudo sh -c 'cat /tmp/hosts >> /etc/hosts'
And of course, you can configure sudo to not require passwords.

Resources