Hello everyone , Myself harsh , working on botnet detection using ryu and ML. I am able to detect botnet traffic using various features , linke src_ip , tp-src, dst-ip , tp-dst, duration .... , I need in help in mitigation where when we identify the botnet traffic we must drop the flow or drop all those packets , so is there any way of thing it ? detection code is pasted below , and thankyou in advance !!!!!!!!
####################swith code################### #master from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_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 ethernet from ryu.lib.packet import ether_types from ryu.lib.packet import in_proto from ryu.lib.packet import ipv4 from ryu.lib.packet import icmp from ryu.lib.packet import tcp from ryu.lib.packet import udp from ryu.lib.packet import sctp from ryu.lib.packet import igmp 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 = {} @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 match = parser.OFPMatch() actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions) def add_flow(self, datapath, priority, match, actions, buffer_id=None, idle=0, hard=0): ofproto = datapath.ofproto parser = datapath.ofproto_parser inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] if buffer_id: mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, idle_timeout=idle, hard_timeout=hard, priority=priority, match=match, instructions=inst) else: mod = parser.OFPFlowMod(datapath=datapath, priority=priority, idle_timeout=idle, hard_timeout=hard, match=match, instructions=inst) datapath.send_msg(mod) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def _packet_in_handler(self, ev): 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: return dst = eth.dst src = eth.src dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) # 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: out_port = ofproto.OFPP_FLOOD actions = [parser.OFPActionOutput(out_port)] # install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: # check IP Protocol and create a match for IP if eth.ethertype == ether_types.ETH_TYPE_IP: ip = pkt.get_protocol(ipv4.ipv4) srcip = ip.src dstip = ip.dst protocol = ip.proto # if ICMP Protocol if protocol == in_proto.IPPROTO_ICMP: i = pkt.get_protocol(icmp.icmp) match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP, ipv4_src=srcip, ipv4_dst=dstip, ip_proto=protocol,icmpv4_code=i.code, icmpv4_type=i.type) # if TCP Protocol elif protocol == in_proto.IPPROTO_TCP: t = pkt.get_protocol(tcp.tcp) match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP, ipv4_src=srcip, ipv4_dst=dstip, ip_proto=protocol, tcp_src=t.src_port, tcp_dst=t.dst_port,) # If UDP Protocol elif protocol == in_proto.IPPROTO_UDP: u = pkt.get_protocol(udp.udp) match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP, ipv4_src=srcip, ipv4_dst=dstip, ip_proto=protocol, udp_src=u.src_port, udp_dst=u.dst_port,) # If IGMP Protocol elif protocol == in_proto.IPPROTO_IGMP: g = pkt.get_protocol(igmp.igmp) match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP, ipv4_src=srcip, ipv4_dst=dstip, ip_proto=protocol) # If SCTP Protocol elif protocol == in_proto.IPPROTO_SCTP: s = pkt.get_protocol(sctp.sctp) match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP, ipv4_src=srcip, ipv4_dst=dstip, ip_proto=protocol, scpt_src=s.src_port, sctp_dst=s.dst_port,) # verify if we have a valid buffer_id, if yes avoid to send both # flow_mod & packet_out if msg.buffer_id != ofproto.OFP_NO_BUFFER: self.add_flow(datapath, 1, match, actions, msg.buffer_id, idle=20, hard=100) return else: self.add_flow(datapath, 1, match, actions, idle=20, hard=100) 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) ########################################################## ########### detection module ################################ 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(10) 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("PredictFlowStatsfile.csv","w") file0.write('ip_src,tp_src,ip_dst,tp_dst,ip_proto,flow_duration_sec,flags,packet_count,byte_count,packet_count_per_second,byte_count_per_second\n') body = ev.msg.body tp_src = 0 tp_dst = 0 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'] try: packet_count_per_second = stat.packet_count/stat.duration_sec except: packet_count_per_second = 0 try: byte_count_per_second = stat.byte_count/stat.duration_sec except: byte_count_per_second = 0 file0.write("{},{},{},{},{},{},{},{},{},{},{}\n" .format(ip_src, tp_src,ip_dst, tp_dst, stat.match['ip_proto'],stat.duration_sec, stat.flags, stat.packet_count,stat.byte_count, packet_count_per_second,byte_count_per_second,)) file0.close() def flow_training(self): self.logger.info("Flow Training ...") flow_dataset = pd.read_csv('FlowStatsfile.csv') flow_dataset.iloc[:, 0] = flow_dataset.iloc[:, 0].str.replace('.', '') flow_dataset.iloc[:, 3] = flow_dataset.iloc[:, 3].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.20, random_state=0) classifier = RandomForestClassifier(n_estimators=10, 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('PredictFlowStatsfile.csv') pdf = copy.deepcopy(predict_flow_dataset) predict_flow_dataset.iloc[:, 3] = predict_flow_dataset.iloc[:, 3].str.replace('.', '') predict_flow_dataset.iloc[:, 0] = predict_flow_dataset.iloc[:, 0].str.replace('.', '') #pdf.iloc[:, 2] = pdf.iloc[:, 2].str.replace('.', '') #pdf.iloc[:, 0] = pdf.iloc[:, 0].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 botnet_trafic = 0 for i in y_flow_pred: if i == 0: legitimate_trafic = legitimate_trafic + 1 else: botnet_trafic = botnet_trafic + 1 victim = pdf.iloc[i, 2]#%20 attacker = pdf.iloc[i, 0]#%20 self.logger.info ("------------------------------------------------------------------------------") if (legitimate_trafic/len(y_flow_pred)*100) > 80: print("legitimate trafic ...",legitimate_trafic/len(y_flow_pred)) else: print("botnet trafic ...",botnet_trafic/len(y_flow_pred)) print("Attacker IP: {}".format(attacker)) self.logger.info ("------------------------------------------------------------------------------") file0 = open("PredictFlowStatsfile.csv","w") file0.write('ip_src,tp_src,ip_dst,tp_dst,ip_proto,flow_duration_sec,flags,packet_count,byte_count,packet_count_per_second,byte_count_per_second,\n') file0.close() except: pass ########################################################### please any help in mitigation , or remove flows with bad traffic ( botnet traffic ) it will be a ton of help. thank you so much in advance !!! -- Best Regards, Harsh Verdhan Singh M.Tech (CSE) PDPM-IIITDM, Jabalpur
_______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel