In this post I will share the iptable script in which we will learn How to protect from port scanning and smurf attack in Linux Server.
Features Of Script :
(1) When a attacker try to port scan your server, first because of iptable attacker will not get any information which port is open. Second the Attacking IP address will be blacklisted for 24 Hour (You can change it in script) . Third , after that attacker will not able to open access anything for eg. even attacker will not see any website running on server via web browser, not able to ssh,telnet also. Means completely restricted.
(2) Protects from smurf attack
(3) Written with the help of IPTABLE hence no System Performance issue like CPU high,Memory usage etc. No third party tool is used
Note: You can add or remove port no. as per your requirement.
Description about Server where we will implement IPTABLE script:
Operating Syetem : CentOS 6.4 (applicable to Red hat and CentOS servers)
IP Address: 192.168.1.4
Now we will create the script
Step 1: Create a bash script with the name of iptablescript.sh
vi /root/iptablescript.sh
Step 2: Now paste the below given script contents in your bash script file iptablescript.sh
#!/bin/sh # # # Script is for stoping Portscan and smurf attack ### first flush all the iptables Rules iptables -F # INPUT iptables Rules # Accept loopback input iptables -A INPUT -i lo -p all -j ACCEPT # allow 3 way handshake iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ### DROPspoofing packets iptables -A INPUT -s 10.0.0.0/8 -j DROP iptables -A INPUT -s 169.254.0.0/16 -j DROP iptables -A INPUT -s 172.16.0.0/12 -j DROP iptables -A INPUT -s 127.0.0.0/8 -j DROP iptables -A INPUT -s 192.168.0.0/24 -j DROP iptables -A INPUT -s 224.0.0.0/4 -j DROP iptables -A INPUT -d 224.0.0.0/4 -j DROP iptables -A INPUT -s 240.0.0.0/5 -j DROP iptables -A INPUT -d 240.0.0.0/5 -j DROP iptables -A INPUT -s 0.0.0.0/8 -j DROP iptables -A INPUT -d 0.0.0.0/8 -j DROP iptables -A INPUT -d 239.255.255.0/24 -j DROP iptables -A INPUT -d 255.255.255.255 -j DROP #for SMURF attack protection iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP iptables -A INPUT -p icmp -m icmp -m limit --limit 1/second -j ACCEPT # Droping all invalid packets iptables -A INPUT -m state --state INVALID -j DROP iptables -A FORWARD -m state --state INVALID -j DROP iptables -A OUTPUT -m state --state INVALID -j DROP # flooding of RST packets, smurf attack Rejection iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT # Protecting portscans # Attacking IP will be locked for 24 hours (3600 x 24 = 86400 Seconds) iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP # Remove attacking IP after 24 hours iptables -A INPUT -m recent --name portscan --remove iptables -A FORWARD -m recent --name portscan --remove # These rules add scanners to the portscan list, and log the attempt. iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "portscan:" iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "portscan:" iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP # Allow the following ports through from outside iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT # Allow ping means ICMP port is open (If you do not want ping replace ACCEPT with REJECT) iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # Lastly reject All INPUT traffic iptables -A INPUT -j REJECT ################# Below are for OUTPUT iptables rules ############################################# ## Allow loopback OUTPUT iptables -A OUTPUT -o lo -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow the following ports through from outside # SMTP = 25 # DNS =53 # HTTP = 80 # HTTPS = 443 # SSH = 22 ### You can also add or remove port no. as per your requirement iptables -A OUTPUT -p tcp -m tcp --dport 25 -j ACCEPT iptables -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT iptables -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT iptables -A OUTPUT -p tcp -m tcp --dport 22 -j ACCEPT # Allow pings iptables -A OUTPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # Lastly Reject all Output traffic iptables -A OUTPUT -j REJECT ## Reject Forwarding traffic iptables -A FORWARD -j REJECT
Step 3: Make the Read Write Execute permission only to root user. (For security)
chmod 700 /root/iptablescript.sh chown root:root /root/iptablescript.sh
Step 4 : Now run the script
sh /root/iptablescript.sh or ./root/iptablescript.sh
Step 6: Now check the IPTABLES rule with following command
iptables -nL
Now we will do testing from remote server to our server where we have implemented the iptable
Step 7: login into any system and try to do port scanning
nmap -sT Server-ip-address eg. nmap -sT 192.168.1.4
Step 8: The result should be now from your system like following types
(a) Not getting any output from nmap
(b) Not able to do telnet to any port for eg. telnet Server-ip-address 22
After running nmap means port scan your ip-address is blacklisted.
You can find your system ip address in message logs in Server with the keyword called portscan.
So login back to your server and check the messages log in /var/log
Note : how to install nmap
In Red Hat and CentOS yum install nmap In Debian and Ubuntu apt-get install nmap
Great script thanks!
Line:
iptables -A INPUT -p icmp -m icmp -m limit –limit 1/second -j ACCEPT
Results in an error:
iptables v1.4.21: icmp: option “–icmp-type” must be specified
It should be:
iptables -A INPUT –protocol icmp –match icmp –icmp-type 8 –match limit –limit 1/second –jump ACCEPT
Hi there,
Thanks for this.
Unfortunately, Smurf Attack is still possible (tested with hping3).
Any idea how to mitigate it?
Hi David,
Thank you for replying with feedback. Currently I am not using hping3, it would be great if you could provide me its result.
In which Operaring System version are you applying the iptable. I also need iptable version number.
Regards
Sharad
how could I add an exception IP (our admin) to that script so we are not locked out
I often do telnet to check if a port is responding
thanks
root@ubuntu:~# ./iptablescript.sh
iptables v1.6.0: icmp: option “–icmp-type” must be specified
Try `iptables -h’ or ‘iptables –help’ for more information.
I am also getting this.
Really great write up, Could I ask you to clarify why
iptables -A INPUT -m recent –name portscan –rcheck –seconds 86400 -j DROP
is required before
iptables -A INPUT -p tcp -m tcp –dport 139 -m recent –name portscan –set -j DROP
Shouldn’t the latter be enough?
Hello Clifford,
You can shuffle but it should be within DROP sections. To understand, I suggest to try the things practically. Do testing things in test machine 🙂
All the best.
Regards
Sharad
HI. I ran your script in my Linux Mint cinnamon . I am behind an office proxy network, and when I ran your script, it gave me the following error-
iptables v1.4.21: icmp: option “–icmp-type” must be specified
Try `iptables -h’ or ‘iptables –help’ for more information.
Also I was unable to access the internet then. So I changed the iptables -A OUTPUT -j REJECT to iptables -A OUTPUT -j ACCEPT .
so 1) what should I do to remove the above error.
2) Being on a proxy network, are there any changes that I should make in the script
3) After running your script too, other users were able to do a port scan on my system. How should I fix it ?
Thanks
Hi Aryan,
As the error specified , “–icmp-type” .
Most probably there is typo or special character is added with iptables.
I rerun the script and it is working for me. Curious to know , if typo is fixed and the script is working for you.
Regards
Sharad
It seems to be the problem with iptables version. I am running this script on Ubuntu 14.04, iptables v1.4.21 and have the same error. Problematic line:
iptables -A INPUT -p icmp -m icmp -m limit –limit 1/second -j ACCEPT
and error is saying that –icmp-type must be specified (and now it’s not)
HI Sharad Chhetri,
Very thank you for sharing this wonderful script. Can I ask you this if not bother you. My scenario is:
-I got 2 interfaces: eth0 (Internal network – LAN) and ppp0 (External – Real IP – pppoe gateway)
-I made rules that bridge 2 interfaces and everything work fine, my LAN network works well, also the gateway. However, my issue is I could not connect to WAN IP (External IP from ppp0 interface) from LAN network,
here is my script
#!/bin/sh
LAN=”eth0″
WAN=”ppp0″
echo “Flushing rules”
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
echo “Done”
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
## Allow loopback OUTPUT
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i $WAN -m state –state ESTABLISHED,RELATED -j ACCEPT
### DROPspoofing packets
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 192.168.0.0/24 -j DROP
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
#for SMURF attack protection
iptables -A INPUT -p icmp -m icmp –icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp –icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -m limit –limit 1/second -j ACCEPT
# Droping all invalid packets
iptables -A INPUT -m state –state INVALID -j DROP
iptables -A FORWARD -m state –state INVALID -j DROP
iptables -A OUTPUT -m state –state INVALID -j DROP
# flooding of RST packets, smurf attack Rejection
iptables -A INPUT -p tcp -m tcp –tcp-flags RST RST -m limit –limit 2/second –limit-burst 2 -j ACCEPT
# Protecting portscans
# Attacking IP will be locked for 15 minutes ( 60 x 15 = 900 Seconds)
iptables -A INPUT -m recent –name portscan –rcheck –seconds 900 -j DROP
iptables -A FORWARD -m recent –name portscan –rcheck –seconds 900 -j DROP
# Remove attacking IP after 15 minutes
iptables -A INPUT -m recent –name portscan –remove
iptables -A FORWARD -m recent –name portscan –remove
# These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT -p tcp -m tcp –dport 139 -m recent –name portscan –set -j LOG –log-prefix “portscan:”
iptables -A INPUT -p tcp -m tcp –dport 139 -m recent –name portscan –set -j DROP
iptables -A FORWARD -p tcp -m tcp –dport 139 -m recent –name portscan –set -j LOG –log-prefix “portscan:”
iptables -A FORWARD -p tcp -m tcp –dport 139 -m recent –name portscan –set -j DROP
# Allow ping means ICMP port is open (If you do not want ping replace ACCEPT with REJECT)
iptables -A INPUT -p icmp -m icmp –icmp-type 8 -j REJECT
# SYN-Flooding Protection
iptables -N syn-flood
iptables -A INPUT -i $WAN -p tcp –syn -j syn-flood
iptables -A syn-flood -m limit –limit 1/s –limit-burst 4 -j RETURN
iptables -A syn-flood -j DROP
# Make sure that new TCP connections are SYN packets
iptables -A INPUT -i $WAN -p tcp ! –syn -m state –state NEW -j DROP
#iptables -A INPUT -j DROP
iptables -A INPUT -j REJECT
#
iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE
iptables -A FORWARD -i $LAN -j ACCEPT
iptables -A INPUT -i $LAN -j ACCEPT
echo “Opening SSH port…”
iptables -A INPUT -p tcp –dport 8888 -j ACCEPT
iptables -A INPUT -p tcp –dport 22 -j ACCEPT
echo “Opening HTTP port…”
iptables -A INPUT -p tcp –dport 80 -j ACCEPT
echo “Opening RDP port…”
iptables -A INPUT -p tcp –dport 3389 -j ACCEPT
iptables -t nat -A PREROUTING -i $WAN -p tcp –dport 22 -j DNAT –to 192.168.10.55:22
iptables -t nat -A PREROUTING -i $WAN -p tcp –dport 80 -j DNAT –to 192.168.10.55:80
iptables -t nat -A PREROUTING -i $WAN -p tcp –dport 3389 -j DNAT –to 192.168.10.5:3389
service iptables save
service iptables restart
iptables-save > rules
Hello Nick,
Allow DNS port in script and try again.Also check /etc/resolv.conf if the DNS ip is correctly given.
Regards
Sharad
Thanks you Sharad for your post and your script, work very well. For Claudia: she must run your script and after iptables-save and service iptalbes restart. Don’t make a copy of the script in the iptables file.
Welcome Gianni,
That is very useful feedback.
Regards
Sharad
Thank you for posting this kind of stuff, saved me a lot of work. Much appreciated.
Welcome Mark,
Regards
Sharad
My VPS runs Centos 5.10. I’ve installed it correctly, but when I run the script I get a host of errors in ssh.
[1] command not found [line 5, also lines 8,9, and thereafter whenever the line is empty]
[2] iptables: no chain/ target/ match by that name
[3] ‘ptables v1.3.5: Invalid target name ACCEPT [also with DROP, REJECT]
[4] try iptables -h or iptables –help for more information
Please advise. Thanks!
Hello Claudia,
As per question, it seems the CentOS 5.10 has different iptables version . In this case we have to check the available options with IPTABLE command. The script has been last tested in CentOS 6.5 .
Regards
Sharad