How to protect from port scanning and smurf attack in Linux Server by iptables

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

21 thoughts on “How to protect from port scanning and smurf attack in Linux Server by iptables”

  1. 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

    Reply
    • 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

      Reply
  2. 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

    Reply
  3. root@ubuntu:~# ./iptablescript.sh
    iptables v1.6.0: icmp: option “–icmp-type” must be specified

    Try `iptables -h’ or ‘iptables –help’ for more information.

    Reply
  4. 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?

    Reply
    • 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

      Reply
  5. 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

    Reply
    • 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

      Reply
      • 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)

        Reply
  6. 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

    Reply
  7. 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.

    Reply
  8. 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!

    Reply
    • 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

      Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.