Estrella Brillante
Estrella Brillante

Reputation: 19

how to Drop packet in ryu controller after detecting DDoS using ML

hi i'm working on project to detect and mitigate ddos on sdn using maching learning. the simulation was done by ryu controller and mininet. my question is that i was able to detect the attck but i'm really strugling with mitigation i want to drop the packet after detecting that this is a ddos attack i tryed some solutions but it didn't work for me so can anyone here help me to drop these packets just after detecting DDoS and i'll be thankfull for that.

this is my app:

'''

def __init__(self, *args, **kwargs):
    super(SimpleMonitor13, self).__init__(*args, **kwargs)
    self.datapaths = {}
    self.monitor_thread = hub.spawn(self._monitor)

    start = datetime.now()

    self.flow_training()

    end = datetime.now()
    print("Training time: ", (end-start))

    

@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 datapath.id not 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 _monitor(self):
    while True:
        for dp in self.datapaths.values():
            self._request_stats(dp)
        hub.sleep(5)
        self.flow_predict()

def _request_stats(self, datapath):
    self.logger.debug('send stats request: %016x', datapath.id)
   
    parser = datapath.ofproto_parser

    req = parser.OFPFlowStatsRequest(datapath)
    datapath.send_msg(req)

   

@set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
def _flow_stats_reply_handler(self, ev):
    file0 = open("Prediction.csv", "w")
    file0.write('timestamp,datapath_id,flow_id,ip_src,tp_src,ip_dst,tp_dst,ip_proto,icmp_code,         icmp_type,flow_duration_sec,flow_duration_nsec,idle_timeout,hard_timeout,flags, packet_count,byte_count,packet_count_per_second,packet_count_per_nsecond,byte_count_per_second,byte_count_per_nsecond\n')

    body = ev.msg.body

    
    timestamp = datetime.now()
    timestamp = timestamp.timestamp()
    icmp_code = -1
    icmp_type = -1
    tp_src = 0
    tp_dst = 0

   

    body = ev.msg.body
    for stat in sorted([flow for flow in body if (flow.priority == 1)], key=lambda flow:
                       (flow.match['eth_type'], flow.match['ipv4_src'], flow.match['ipv4_dst'], flow.match['ip_proto'])):

        ip_src = stat.match['ipv4_src']
        ip_dst = stat.match['ipv4_dst']
        ip_proto = stat.match['ip_proto']

        if stat.match['ip_proto'] == 1:
            icmp_code = stat.match['icmpv4_code']
            icmp_type = stat.match['icmpv4_type']

        elif stat.match['ip_proto'] == 6:
            tp_src = stat.match['tcp_src']
            tp_dst = stat.match['tcp_dst']

        elif stat.match['ip_proto'] == 17:
            tp_src = stat.match['udp_src']
            tp_dst = stat.match['udp_dst']

        flow_id = str(ip_src) + str(tp_src) + str(ip_dst) + \
            str(tp_dst) + str(ip_proto)

        try:
            packet_count_per_second = stat.packet_count/stat.duration_sec
            packet_count_per_nsecond = stat.packet_count/stat.duration_nsec
        except:
            packet_count_per_second = 0
            packet_count_per_nsecond = 0

        try:
            byte_count_per_second = stat.byte_count/stat.duration_sec
            byte_count_per_nsecond = stat.byte_count/stat.duration_nsec
        except:
            byte_count_per_second = 0
            byte_count_per_nsecond = 0

       
        file0.write("{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}\n"
            .format(timestamp, ev.msg.datapath.id, flow_id, ip_src, tp_src,ip_dst, tp_dst,
                    stat.match['ip_proto'],icmp_code,icmp_type,
                    stat.duration_sec, stat.duration_nsec,
                    stat.idle_timeout, stat.hard_timeout,
                    stat.flags, stat.packet_count,stat.byte_count,
                    packet_count_per_second,packet_count_per_nsecond,
                    byte_count_per_second,byte_count_per_nsecond))
        
    file0.close()
def flow_training(self):
    self.logger.info("Flow Training ...")
    flow_dataset = pd.read_csv('Dataset.csv')

    flow_dataset.iloc[:, 2] = flow_dataset.iloc[:, 2].str.replace('.', '')
    flow_dataset.iloc[:, 3] = flow_dataset.iloc[:, 3].str.replace('.', '')
    flow_dataset.iloc[:, 5] = flow_dataset.iloc[:, 5].str.replace('.', '')

    X_flow = flow_dataset.iloc[:, :-1].values
    X_flow = X_flow.astype('float64')

    y_flow = flow_dataset.iloc[:, -1].values

    X_flow_train, X_flow_test, y_flow_train, y_flow_test = train_test_split(
        X_flow, y_flow, test_size=0.25, random_state=0)

    classifier = DecisionTreeClassifier(
        criterion='entropy', random_state=0)
    self.flow_model = classifier.fit(X_flow_train, y_flow_train)

    y_flow_pred = self.flow_model.predict(X_flow_test)

    self.logger.info("------------------------------------------------------------------------------")

    self.logger.info("confusion matrix")
    cm = confusion_matrix(y_flow_test, y_flow_pred)
    self.logger.info(cm)

    acc = accuracy_score(y_flow_test, y_flow_pred)

    self.logger.info("succes accuracy = {0:.2f} %".format(acc*100))
    fail = 1.0 - acc
    self.logger.info("fail accuracy = {0:.2f} %".format(fail*100))
    self.logger.info("------------------------------------------------------------------------------")

def flow_predict(self):
    try:
        predict_flow_dataset = pd.read_csv('Prediction.csv')

        predict_flow_dataset.iloc[:, 2] = predict_flow_dataset.iloc[:, 2].str.replace(
            '.', '')
        predict_flow_dataset.iloc[:, 3] = predict_flow_dataset.iloc[:, 3].str.replace(
            '.', '')
        predict_flow_dataset.iloc[:, 5] = predict_flow_dataset.iloc[:, 5].str.replace(
            '.', '')

        X_predict_flow = predict_flow_dataset.iloc[:, :].values
        X_predict_flow = X_predict_flow.astype('float64')

        y_flow_pred = self.flow_model.predict(X_predict_flow)

        legitimate_trafic = 0
        ddos_trafic = 0

        for i in y_flow_pred:
            if i == 0:
                legitimate_trafic = legitimate_trafic + 1
            else:
                ddos_trafic = ddos_trafic + 1
                victim = int(predict_flow_dataset.iloc[i, 5]) % 20

        self.logger.info("------------------------------------------------------------------------------")
        if (legitimate_trafic/len(y_flow_pred)*100) > 80:
            self.logger.info("legitimate trafic ...")
        else:
            self.logger.info("ddos trafic ...")
            self.logger.info("victim is host: h{}".format(victim))

        self.logger.info("------------------------------------------------------------------------------")

        file0 = open("Prediction.csv", "w")

        file0.write('timestamp,datapath_id,flow_id,ip_src,tp_src,ip_dst,tp_dst,ip_proto,icmp_code,         icmp_type,flow_duration_sec,flow_duration_nsec,idle_timeout,hard_timeout,flags, packet_count,byte_count,packet_count_per_second,packet_count_per_nsecond,byte_count_per_second,byte_count_per_nsecond\n')
        file0.close()

    except:
        pass

'''

Upvotes: 0

Views: 468

Answers (2)

N Khan
N Khan

Reputation: 1

You need to add eth_src to your prediction dataset Then,do the same steps of extracting the victim host to extract the attacker host (if I==1): victim = , attacker_eth=


  1. Once you have the Ethernet src, you can use add_flow() function to add block to the flow table.

*** I tried several times. Would you mind sharing your code. Thank You.

Upvotes: 0

Candy
Candy

Reputation: 1

You need to add eth_src to your prediction dataset Then,do the same steps of extracting the victim host to extract the attacker host (if I==1): victim = , attacker_eth=

Once you got the Ethernet src, you can use add_flow() function to add block to the flow table. If you need more details tell me

Upvotes: 0

Related Questions