예제 #1
0
class HadoopSSHController(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    _CONTEXTS = {
        'dpset': dpset.DPSet,
    }

    def __init__(self, *args, **kwargs):
        super(HadoopSSHController, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
        self.dpset = kwargs['dpset']
        self.datapaths = {}
        # create thread for traffic monitoring
        # self.monitor_thread = hub.spawn(self._monitor)
        self.hostname_list = {}
        self.dpid_datapathObj = {}
        self.ssh_learning = {}
        self.ssh_track_list = {}
        self.util = Utilites()
        # self._update_switch_dpid_list()

    ###################################################################
    # ofp_event.EventOFPSwitchFeatures
    ####################################################################
    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        # self._update_switch_dpid_list()
        self.logger.debug("switch_features_handler: ")
        datapath = ev.msg.datapath
        dpid = datapath.id
        # save datapath object into dpid_datapath
        # here dpid is a integer, not Hex number
        self.dpid_datapathObj[dpid] = ev.msg.datapath

    ###################################################################
    # EventOFPPacketIn handler
    ####################################################################
    @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
        pkt = packet.Packet(data=msg.data)
        pkt_ethernet = pkt.get_protocol(ethernet.ethernet)
        eth = pkt.get_protocols(ethernet.ethernet)[0]
        dst_mac = eth.dst
        if dst_mac == LLDP_MAC_NEAREST_BRIDGE:
            return

        if not pkt_ethernet:
            return
        else:
            pass
            self.logger.debug("HadoopSSHController: Packet-In:")
            # self.logger.info("\tether_packet: at %s %s " % (self.util.hostname_Check(datapath.id), pkt_ethernet))

        pkt_arp = pkt.get_protocol(arp.arp)
        if pkt_arp:
            return

        pkt_tcp = pkt.get_protocol(tcp.tcp)
        # pkt_udp = pkt.get_protocol(udp.udp)
        if pkt_tcp:
            # self.logger.info("\tTCP_packet: at %s %s " % (self.util.hostname_Check(datapath.id), pkt_tcp))
            pkt_ipv4 = pkt.get_protocol(ipv4.ipv4)
            src_ip = pkt_ipv4.src
            dst_ip = pkt_ipv4.dst
            in_port = msg.match['in_port']
            src_mac = eth.src
            # parser = datapath.ofproto_parser
            if pkt_tcp:
                src_port = pkt_tcp.src_port
                dst_port = pkt_tcp.dst_port
            if str(dst_port) == '22':
                key = (src_ip, dst_ip, src_mac, dst_mac, dst_port)
                self.logger.debug("HadoopSSHController: Packet-In:")

                if key not in self.ssh_learning.keys():
                    self.logger.info("\t############################# SSH Traffic #####################################")
                    self.logger.info("\tAt %s from %s to %s from src_port %s to dst_port %s from  port %s src_mac %s dst_mac %s" %
                                     (self.util.hostname_Check(datapath.id), src_ip, dst_ip, src_port, dst_port, in_port, src_mac, dst_mac))
                    # this valuw will be used at a timer, This entry will be cleard after 1 second
                    value = time.time()
                    self.ssh_learning[key] = value
                elif key in self.ssh_learning.keys():
                    if time.time() - self.ssh_learning[key] >= SSH_KEY_LEARNING_TIMER:
                        self.logger.info("\t(src_ip, dst_ip, src_mac, dst_mac, dst_port, in_port) TIMEOUT from self.ssh_learning dict!!!")
                        del self.ssh_learning[key]
                        self.ssh_learning[key] = time.time()
                    else:
                        return
                else:
                    return
                src_dpid_name = self.util.hostname_Check(datapath.id)
                # self.logger.info("\tInstall SSH flow between IP address %s and %s \n\tsleeping for 5 s ........................" % (src_ip, dst_ip))
                time.sleep(5)
                # find dstination datapath id from host_tracker file
                dst_dpid_name = self.util.return_dst_dpid_hostname(dst_ip, dst_mac)
                if dst_dpid_name == None:
                    self.logger.info("\tcould not find destination switch..............")
                    return

                self.logger.info("\tInstall SSH flow between %s and %s" % (src_dpid_name, dst_dpid_name))

                # Now only consider two end hosts
                hosts = [src_mac, dst_mac]
                # find shortest path between two switches, a list of hostnames ['s1','s2','s3']
                shortest_path = self.util.return_shortest_path(src_dpid_name, dst_dpid_name)
                self.logger.info("\tShortestPath between %s and %s is %s" % (src_dpid_name, dst_dpid_name, shortest_path))
                # self.logger.info("\tWrite to SSH Log")
                final_named_list = ""
                if len(self.ssh_track_list.keys()) < SSH_TRACK_LIMIT:
                    self.ssh_track_list[(src_mac, dst_mac, src_ip, dst_ip, src_port, dst_port)] = shortest_path
                # elif(src_mac, dst_mac, src_ip, dst_ip, src_port, dst_port) not in self.ssh_track_list.keys():
                #     self.ssh_track_list = {}
                #     self.ssh_track_list[(src_mac, dst_mac, src_ip, dst_ip, src_port, dst_port)] = shortest_path
                with open(OFP_SSH_LOG, 'w') as inp:
                    for key in self.ssh_track_list.keys():
                        shortest_path_name_list = [self.util.hostname_Check(i) for i in shortest_path]
                    for i in shortest_path_name_list:
                        final_named_list = final_named_list + " " + i
                    inp.write("%s %s" % (key, final_named_list))

                if len(shortest_path) == 1:
                    self.util.install_flows_for_same_switch(
                        shortest_path, 'TCP', src_ip, dst_ip, src_mac, dst_mac, src_port, dst_port, self.dpid_datapathObj, SSH_IDLE_TIMER, SSH_HARD_TIMER)
                else:
                    # install flows between hosts and switch
                    self.install_flows_for_hosts_and_attached_switches(hosts, shortest_path, src_ip, dst_ip, src_port, dst_port, src_mac, dst_mac, msg)

                # install flow for the rest of switches if the length of shortest path is greater than 2
                if len(shortest_path) > 2:
                    self.util.install_flows_for_rest_of_switches(
                        shortest_path, 'TCP', SSH_PRIORITY, src_ip, dst_ip, src_mac, dst_mac, self.dpid_datapathObj, SSH_IDLE_TIMER, SSH_HARD_TIMER)

    def install_flows_for_hosts_and_attached_switches(self, hosts, shortest_path, src_ip, dst_ip, src_port, dst_port, src_mac, dst_mac, msg):
        count = 0
        for h_mac in hosts:
            if count < len(hosts) and count == 0:
                self.util.install_flow_between_host_and_switch_for_TCP_UDP(
                    h_mac, 'TCP', SSH_PRIORITY, shortest_path[count:count + 2],
                    count, src_ip, dst_ip, src_port, dst_port, src_mac, dst_mac, self.dpid_datapathObj, SSH_IDLE_TIMER, SSH_HARD_TIMER,  msg)
                count += 1
            elif count < len(hosts) and count == 1:
                self.util.install_flow_between_host_and_switch_for_TCP_UDP(
                    h_mac, 'TCP', SSH_PRIORITY, list([shortest_path[len(shortest_path) - 1], shortest_path[len(shortest_path) - 2]]),
                    count, src_ip, dst_ip, src_port, dst_port, src_mac, dst_mac, self.dpid_datapathObj, SSH_IDLE_TIMER, SSH_HARD_TIMER, msg)
                count += 1