Beispiel #1
0
 def __reset_switch(self,dp):
     assert (dp is not None),"Datapath Object is Not set. "
     
     ofproto = dp.ofproto
     parser = dp.ofproto_parser
     flow_mod = dp.ofproto_parser.OFPFlowMod(dp,0,0,0,
                                             ofproto.OFPFC_DELETE,
                                             0,0,1,
                                             ofproto.OFPCML_NO_BUFFER,
                                             ofproto.OFPP_ANY,
                                             ofproto.OFPG_ANY,
                                             )
     logging.info("Deleting all Flow Table entries..." )
     dp.send_msg(flow_mod)
     
     # 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. 
     
     const = Construct()
     
     actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                       ofproto.OFPCML_NO_BUFFER)]
     const.add_flow(datapath = dp, actions = actions, priority=0)
     
     actions = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
     const.add_flow(datapath = dp, actions = actions, priority=10000, eth_type=ETH_TYPE_LLDP)
    def __reset_switch(self, dp):
        assert (dp is not None), "Datapath Object is Not set. "

        ofproto = dp.ofproto
        parser = dp.ofproto_parser
        flow_mod = dp.ofproto_parser.OFPFlowMod(
            dp,
            0,
            0,
            0,
            ofproto.OFPFC_DELETE,
            0,
            0,
            1,
            ofproto.OFPCML_NO_BUFFER,
            ofproto.OFPP_ANY,
            ofproto.OFPG_ANY,
        )
        logging.info("deleting all flow table entries in the tables :")
        dp.send_msg(flow_mod)

        const = Construct()

        actions = [
            parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                   ofproto.OFPCML_NO_BUFFER)
        ]
        const.add_flow(datapath=dp, actions=actions, priority=0)

        actions = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
        const.add_flow(datapath=dp,
                       actions=actions,
                       priority=10000,
                       eth_type=ETH_TYPE_LLDP)
Beispiel #3
0
 def __reset_switch(self,dp):
     assert (dp is not None),"Datapath Object is Not set. "
     
     ofproto = dp.ofproto
     parser = dp.ofproto_parser
     flow_mod = dp.ofproto_parser.OFPFlowMod(dp,0,0,0,
                                             ofproto.OFPFC_DELETE,
                                             0,0,1,
                                             ofproto.OFPCML_NO_BUFFER,
                                             ofproto.OFPP_ANY,
                                             ofproto.OFPG_ANY,
                                             )
     logging.info("deleting all flow table entries in the tables :" )
     dp.send_msg(flow_mod)
     
     const = Construct()
     
     actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                       ofproto.OFPCML_NO_BUFFER)]
     const.add_flow(datapath = dp, actions = actions, priority=0)
     
     actions = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
     const.add_flow(datapath = dp, actions = actions, priority=10000, eth_type=ETH_TYPE_LLDP)
Beispiel #4
0
    def __reset_switch(self, dp):
        assert (dp is not None), "Datapath Object is Not set. "

        ofproto = dp.ofproto
        parser = dp.ofproto_parser
        flow_mod = dp.ofproto_parser.OFPFlowMod(
            dp,
            0,
            0,
            0,
            ofproto.OFPFC_DELETE,
            0,
            0,
            1,
            ofproto.OFPCML_NO_BUFFER,
            ofproto.OFPP_ANY,
            ofproto.OFPG_ANY,
        )
        logging.info("Deleting all Flow Table entries...")
        dp.send_msg(flow_mod)

        # 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.

        const = Construct()

        actions = [
            parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                   ofproto.OFPCML_NO_BUFFER)
        ]
        const.add_flow(datapath=dp, actions=actions, priority=0)

        actions = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
        const.add_flow(datapath=dp,
                       actions=actions,
                       priority=10000,
                       eth_type=ETH_TYPE_LLDP)
Beispiel #5
0
class SecureFirewall(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    inner_policy = {}
    sendpkt = SendPacket()
    flow = Construct()
    current_time = Incoming_packet_time()

    def __init__(self, *args, **kwargs):
        super(SecureFirewall, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
        parser = parse_firewall()
        self.inner_policy = parser.parse()
        self.logger.info("dict is ready")

    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
    def handler_datapath(self, ev):
        SwitchInfo(ev)

    """
        Handles incoming packets. Decode them
        and check for suitable Firewall Rules.
    """

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        try:
            pkt = packet.Packet(msg.data)
            eth = pkt.get_protocols(ethernet.ethernet)[0]
            ethtype = eth.ethertype

            out_port = self.port_learn(datapath, eth, in_port)
            action_fwd_to_out_port = [parser.OFPActionOutput(out_port)]
            action_drop = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
            actions_default = action_fwd_to_out_port

            if (out_port != ofproto.OFPP_FLOOD) and (ethtype == ETH_TYPE_IP):
                ipo = pkt.get_protocols(ipv4.ipv4)[0]

                # Check for ICMP
                if (ipo.proto == IPPROTO_ICMP):
                    flag1 = 0
                    icmpob = pkt.get_protocol(icmp.icmp)

                    # Check if this is PING
                    if ((icmpob.type == ICMP_PING)
                            and self.inner_policy.has_key(ipo.src)):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if temp[i][0] == ipo.dst:
                                xyz = temp[i]
                                if ((xyz[1] == 'ICMP') and (xyz[4] == 'PING')
                                        and (xyz[5] == 'ALLOW')):
                                    flag1 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.logger.info(
                                        "%s  ->  %s : PING PACKET ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_ICMP,
                                                       icmpv4_type=ICMP_PING,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst)
                                    break

                    # Check if it is PONG
                    elif ((icmpob.type == ICMP_PONG)
                          and (self.inner_policy.has_key(ipo.src))):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if temp[i][0] == ipo.dst:
                                xyz = temp[i]
                                if ((xyz[1] == 'ICMP') and (xyz[4] == 'PONG')
                                        and (xyz[5] == 'ALLOW')):
                                    flag1 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.logger.info(
                                        "%s  ->  %s : PONG PACKET ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_ICMP,
                                                       icmpv4_type=ICMP_PONG,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst)
                                    self.current_time.time()
                                    self.logger.info("\n")
                                    break

                    # What if no match found ?
                    if (flag1 == 0):
                        actions_default = action_drop
                        self.logger.info("%s  ->  %s : ICMP BLOCKED" %
                                         (ipo.src, ipo.dst))
                        self.flow.add_flow(datapath=datapath,
                                           actions=actions_default,
                                           priority=1001,
                                           in_port=in_port,
                                           eth_type=ETH_TYPE_IP,
                                           ip_proto=IPPROTO_ICMP,
                                           icmpv4_type=icmpob.type,
                                           ipv4_src=ipo.src,
                                           ipv4_dst=ipo.dst)

                # Check for TCP
                elif (ipo.proto == IPPROTO_TCP):
                    tcpo = pkt.get_protocol(tcp.tcp)
                    flag2 = 0

                    # TCP packet and Firewall rule
                    if self.inner_policy.has_key(ipo.src):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if ((temp[i][0] == ipo.dst)
                                    and (temp[i][1] == 'TCP')
                                    and (int(temp[i][2]) == tcpo.src_port)
                                    and (int(temp[i][3]) == tcpo.dst_port)
                                    and (temp[i][4].upper() == 'ANY')
                                    and (temp[i][5] == 'ALLOW')):
                                flag2 = 1
                                actions_default = action_fwd_to_out_port
                                self.logger.info(
                                    "%s  ->  %s : TCP PACKET ALLOWED" %
                                    (ipo.src, ipo.dst))
                                self.current_time.time()
                                self.logger.info("\n")
                                break
                            elif (((tcpo.bits & TCP_ACK) == TCP_ACK)
                                  and (temp[i][0] == ipo.dst)
                                  and (temp[i][1] == 'TCP')
                                  and (int(temp[i][2]) == tcpo.src_port)
                                  and (int(temp[i][3]) == tcpo.dst_port)
                                  and (temp[i][4].upper() == 'ACK')
                                  and (temp[i][5] == 'ALLOW')):
                                flag2 = 1
                                actions_default = action_fwd_to_out_port
                                self.logger.info(
                                    "%s  ->  %s : TCP PACKET ALLOWED" %
                                    (ipo.src, ipo.dst))
                                self.current_time.time()
                                self.logger.info("\n")
                                break

                    # If match found then add Flow Table rules
                    if (flag2 != 0):
                        self.flow.add_flow(datapath=datapath,
                                           actions=actions_default,
                                           priority=1001,
                                           in_port=in_port,
                                           eth_type=ETH_TYPE_IP,
                                           ip_proto=IPPROTO_TCP,
                                           ipv4_src=ipo.src,
                                           ipv4_dst=ipo.dst,
                                           tcp_src=tcpo.src_port,
                                           tcp_dst=tcpo.dst_port)

                    # What if no match found ?
                    else:
                        actions_default = action_drop
                        self.logger.info("%s  ->  %s : BLOCKED" %
                                         (ipo.src, ipo.dst))

                # Check for UDP
                elif (ipo.proto == IPPROTO_UDP):
                    udpo = pkt.get_protocol(udp.udp)
                    flag3 = 0
                    if self.inner_policy.has_key(ipo.src):
                        temp3 = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp3)):
                            if temp3[i][0] == ipo.dst:
                                xyz = temp3[i]
                                if ((xyz[1] == 'UDP')
                                        and (int(xyz[2]) == udpo.src_port)
                                        and (int(xyz[3]) == udpo.dst_port)
                                        and (xyz[5] == 'ALLOW')):
                                    flag3 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.logger.info(
                                        "%s  ->  %s: UDP ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_UDP,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst,
                                                       udp_src=udpo.src_port,
                                                       udp_dst=udpo.dst_port)
                                    self.current_time.time()
                                    self.logger.info("\n")
                                    break

                    # What if no match found ?
                    if (flag3 == 0):
                        actions_default = action_drop
                        self.logger.info("%s  ->  %s : BLOCKED" %
                                         (ipo.src, ipo.dst))
                        self.flow.add_flow(datapath=datapath,
                                           actions=actions_default,
                                           priority=1001,
                                           in_port=in_port,
                                           eth_type=ETH_TYPE_IP,
                                           ip_proto=IPPROTO_UDP,
                                           ipv4_src=ipo.src,
                                           ipv4_dst=ipo.dst,
                                           udp_src=udpo.src_port,
                                           udp_dst=udpo.dst_port)

                # If not ICMP, TCP or UDP then drop..!
                else:
                    self.logger.info("Wrong IP protocol found")
                    actions_default = action_drop

            # Handling ARP Rules.
            elif (ethtype == ETH_TYPE_ARP):
                self.arp_handling(datapath, out_port, eth, in_port)
                actions_default = action_fwd_to_out_port

            # If packet is not IP or ARP then drop..!
            else:
                actions_default = action_drop

        except Exception as err:
            self.logger.info("MYERROR: %s", err.message)
            action_drop = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
            actions_default = action_drop

        finally:
            self.sendpkt.send(datapath, msg, in_port, actions_default)

    """
        Add ARP rules on Flow Tables
    """

    def arp_handling(self, datapath, out_port, eth_obj, in_port):
        if (out_port != datapath.ofproto.OFPP_FLOOD):
            actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
            self.flow.add_flow(datapath=datapath,
                               actions=actions,
                               priority=1000,
                               in_port=in_port,
                               eth_type=ETH_TYPE_ARP,
                               eth_src=eth_obj.src,
                               eth_dst=eth_obj.dst)

    """
        Learn Switch port associated with a MAC address here
    """

    def port_learn(self, datapath, eth_obj, in_port):
        try:
            self.mac_to_port.setdefault(datapath.id, {
                '90:e2:ba:1c:55:54': 1,
                '90:e2:ba:1c:55:55': 2
            })
            self.mac_to_port[datapath.id][eth_obj.src] = in_port

            if (eth_obj.ethertype == ETH_TYPE_IP) or (eth_obj.ethertype
                                                      == ETH_TYPE_ARP):
                if eth_obj.dst in self.mac_to_port[datapath.id]:
                    out_port = self.mac_to_port[datapath.id][eth_obj.dst]
                else:
                    out_port = datapath.ofproto.OFPP_FLOOD
        except Exception as err:
            self.info(err.message)
            out_port = datapath.ofproto.OFPP_FLOOD
        finally:
            return out_port
Beispiel #6
0
class SecureFirewall(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    inner_policy = {}
    icmp_conn_track = {}
    tcp_conn_track = {}
    udp_conn_track = {}
    sendpkt = SendPacket()
    flow = Construct()
    track = TrackConnection()

    def __init__(self, *args, **kwargs):
        super(SecureFirewall, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
        parser = parse_firewall()
        self.inner_policy = parser.parse()
        self.logger.info("dict is ready")

    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
    def handler_datapath(self, ev):
        SwitchInfo(ev)

    """
        Handles incoming packets. Decode them
        and check for suitable Firewall Rules.
    """

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        try:
            pkt = packet.Packet(msg.data)
            eth = pkt.get_protocols(ethernet.ethernet)[0]
            ethtype = eth.ethertype

            out_port = self.port_learn(datapath, eth, in_port)
            action_fwd_to_out_port = [parser.OFPActionOutput(out_port)]
            action_drop = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
            action_fwd_to_in_port = [parser.OFPActionOutput(in_port)]
            actions_default = action_fwd_to_out_port

            if (out_port != ofproto.OFPP_FLOOD) and (ethtype == ETH_TYPE_IP):
                ipo = pkt.get_protocols(ipv4.ipv4)[0]

                #Check for ICMP
                if (ipo.proto == IPPROTO_ICMP):
                    icmpob = pkt.get_protocol(icmp.icmp)
                    flag1 = 0
                    #Check if this is PING or PONG
                    if ((icmpob.type == ICMP_PING)
                            and self.inner_policy.has_key(ipo.src)):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if temp[i][0] == ipo.dst:
                                xyz = temp[i]
                                if ((xyz[1] == 'ICMP')
                                        and (xyz[5] == 'ALLOW')):
                                    flag1 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.icmp_conn_track = self.track.conn_track_dict(
                                        self.icmp_conn_track, ipo.src, ipo.dst,
                                        "PING", "PONG", xyz[5], 2)
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_ICMP,
                                                       icmpv4_type=ICMP_PING,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst)
                                    self.flow.add_flow(
                                        datapath=datapath,
                                        actions=action_fwd_to_in_port,
                                        priority=1000,
                                        in_port=out_port,
                                        eth_type=ETH_TYPE_IP,
                                        ip_proto=IPPROTO_ICMP,
                                        icmpv4_type=ICMP_PONG,
                                        ipv4_src=ipo.dst,
                                        ipv4_dst=ipo.src)
                                    break
                    if (flag1 == 0):
                        actions_default = action_drop
                        self.flow.add_flow(datapath=datapath,
                                           actions=actions_default,
                                           priority=1001,
                                           in_port=in_port,
                                           eth_type=ETH_TYPE_IP,
                                           ip_proto=IPPROTO_ICMP,
                                           icmpv4_type=icmpob.type,
                                           ipv4_src=ipo.src,
                                           ipv4_dst=ipo.dst)

                #Check for TCP.
                elif (ipo.proto == IPPROTO_TCP):
                    tcpo = pkt.get_protocol(tcp.tcp)
                    flag2 = 0
                    # TCP SYN packet
                    if (((tcpo.bits & TCP_SYN) == TCP_SYN) &
                        ((tcpo.bits & TCP_BOGUS_FLAGS) == 0x00)):
                        if self.inner_policy.has_key(ipo.src):
                            temp = self.inner_policy.get(ipo.src)
                            for i in range(0, len(temp)):
                                if ((temp[i][0] == ipo.dst)
                                        and (temp[i][1] == 'TCP')
                                        and (int(temp[i][2]) == tcpo.src_port)
                                        and (int(temp[i][3]) == tcpo.dst_port)
                                        and (temp[i][5] == 'ALLOW')):
                                    flag2 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.tcp_conn_track = self.track.conn_track_dict(
                                        self.tcp_conn_track, ipo.src, ipo.dst,
                                        tcpo.src_port, tcpo.dst_port, tcpo.seq,
                                        1)
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_TCP,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst,
                                                       tcp_src=tcpo.src_port,
                                                       tcp_dst=tcpo.dst_port)
                                    break

                    # TCP SYN ACK packet
                    elif ((tcpo.bits & TCP_SYN_ACK) == TCP_SYN_ACK):
                        if self.tcp_conn_track.has_key(ipo.dst):
                            temp2 = self.tcp_conn_track.get(ipo.dst)
                            for i in range(0, len(temp2)):
                                if ((temp2[i][0] == ipo.src)
                                        and (int(temp2[i][1]) == tcpo.dst_port)
                                        and
                                    (int(temp2[i][2]) == tcpo.src_port)):
                                    flag2 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.tcp_conn_track = self.track.conn_track_dict(
                                        self.tcp_conn_track, ipo.src, ipo.dst,
                                        tcpo.src_port, tcpo.dst_port, tcpo.seq,
                                        1)
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_TCP,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst,
                                                       tcp_src=tcpo.src_port,
                                                       tcp_dst=tcpo.dst_port)
                                    break

                    # All remaining TCP packets, like, ACK, PUSH, FIN etc.
                    else:
                        if self.tcp_conn_track.has_key(ipo.src):
                            temp3 = self.tcp_conn_track.get(ipo.src)
                            for i in range(0, len(temp3)):
                                if ((temp3[i][0] == ipo.dst)
                                        and (int(temp3[i][1]) == tcpo.src_port)
                                        and
                                    (int(temp3[i][2]) == tcpo.dst_port)):
                                    flag2 = 1
                                    actions_default = action_fwd_to_out_port
                                    break
                    if (flag2 == 0):
                        actions_default = action_drop

                #Check for UDP
                elif (ipo.proto == IPPROTO_UDP):
                    udpo = pkt.get_protocol(udp.udp)
                    flag3 = 0
                    if self.inner_policy.has_key(ipo.src):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if temp[i][0] == ipo.dst:
                                xyz = temp[i]
                                if ((xyz[1] == 'UDP')
                                        and (int(xyz[2]) == udpo.src_port)
                                        and (int(xyz[3]) == udpo.dst_port)
                                        and (xyz[5] == 'ALLOW')):
                                    flag3 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.udp_conn_track = self.track.conn_track_dict(
                                        self.udp_conn_track, ipo.src, ipo.dst,
                                        udpo.src_port, udpo.dst_port, xyz[5],
                                        2)
                                    self.flow.add_flow(datapath=datapath,
                                                       actions=actions_default,
                                                       priority=1001,
                                                       in_port=in_port,
                                                       eth_type=ETH_TYPE_IP,
                                                       ip_proto=IPPROTO_UDP,
                                                       ipv4_src=ipo.src,
                                                       ipv4_dst=ipo.dst,
                                                       udp_src=udpo.src_port,
                                                       udp_dst=udpo.dst_port)

                                    self.flow.add_flow(
                                        datapath=datapath,
                                        actions=action_fwd_to_in_port,
                                        priority=1000,
                                        in_port=out_port,
                                        eth_type=ETH_TYPE_IP,
                                        ip_proto=IPPROTO_UDP,
                                        ipv4_src=ipo.dst,
                                        ipv4_dst=ipo.src,
                                        udp_src=udpo.dst_port,
                                        udp_dst=udpo.src_port)
                                    break
                    if (flag3 == 0):
                        actions_default = action_drop

                else:
                    self.logger.info("Wrong IP protocol found")
                    actions_default = action_drop

            # Handling ARP Rules.
            elif (ethtype == ETH_TYPE_ARP):
                self.arp_handling(datapath, out_port, eth, in_port)
                actions_default = action_fwd_to_out_port
            else:
                actions_default = action_drop

        except Exception as err:
            self.logger.info("ERROR: %s", err.message)
            action_drop = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
            actions_default = action_drop

        finally:
            self.sendpkt.send(datapath, msg, in_port, actions_default)

    """
        Add ARP rules on flow tables
    """

    def arp_handling(self, datapath, out_port, eth_obj, in_port):
        if (out_port != datapath.ofproto.OFPP_FLOOD):
            actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
            self.flow.add_flow(datapath=datapath,
                               actions=actions,
                               priority=1000,
                               in_port=in_port,
                               eth_type=ETH_TYPE_ARP,
                               eth_src=eth_obj.src,
                               eth_dst=eth_obj.dst)

    """
        Learn Switch port associated with a MAC address here
    """

    def port_learn(self, datapath, eth_obj, in_port):
        try:
            self.mac_to_port.setdefault(datapath.id, {
                '90:e2:ba:1c:55:54': 1,
                '90:e2:ba:1c:55:55': 2
            })
            self.mac_to_port[datapath.id][eth_obj.src] = in_port

            if (eth_obj.ethertype == ETH_TYPE_IP) or (eth_obj.ethertype
                                                      == ETH_TYPE_ARP):
                if eth_obj.dst in self.mac_to_port[datapath.id]:
                    out_port = self.mac_to_port[datapath.id][eth_obj.dst]
                else:
                    out_port = datapath.ofproto.OFPP_FLOOD
        except Exception as err:
            self.info(err.message)
            out_port = datapath.ofproto.OFPP_FLOOD
        finally:
            return out_port
Beispiel #7
0
class InefficientFirewall(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    inner_policy = {}
    icmp_conn_track = {}
    tcp_conn_track = {}
    udp_conn_track = {}
    sendpkt = SendPacket()
    flow = Construct()
    track = TrackConnection()
    current_time = Incoming_packet_time()

    def __init__(self, *args, **kwargs):
        super(InefficientFirewall, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
        parser = parse_firewall()
        self.inner_policy = parser.parse()

    @set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
    def handler_datapath(self, ev):
        SwitchInfo(ev)

    """
        Handles incoming packets. Decodes them
        and checks for suitable Firewall rules.
    """

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        try:
            pkt = packet.Packet(msg.data)
            eth = pkt.get_protocols(ethernet.ethernet)[0]
            ethtype = eth.ethertype

            out_port = self.port_learn(datapath, eth, in_port)
            action_fwd_to_out_port = [parser.OFPActionOutput(out_port)]
            action_drop = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
            actions_default = action_fwd_to_out_port

            if (out_port != ofproto.OFPP_FLOOD) and (ethtype == ETH_TYPE_IP):
                ipo = pkt.get_protocols(ipv4.ipv4)[0]

                # Check for ICMP
                if (ipo.proto == IPPROTO_ICMP):
                    flag1 = 0
                    icmpob = pkt.get_protocol(icmp.icmp)

                    # Check if this is PING
                    if ((icmpob.type == ICMP_PING)
                            and self.inner_policy.has_key(ipo.src)):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if temp[i][0] == ipo.dst:
                                xyz = temp[i]
                                if ((xyz[1] == 'ICMP')
                                        and (xyz[5] == 'ALLOW')):
                                    flag1 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.icmp_conn_track = self.track.conn_track_dict(
                                        self.icmp_conn_track, ipo.src, ipo.dst,
                                        "PING", "PONG", xyz[5], 2)
                                    self.logger.info(
                                        "%s  ->  %s : ECHO REQUEST ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    break

                    # Otherwise, PONG...!
                    elif ((icmpob.type == ICMP_PONG)
                          and (self.icmp_conn_track.has_key(ipo.src))):
                        temp2 = self.icmp_conn_track.get(ipo.src)
                        for i in range(0, len(temp2)):
                            if temp2[i][0] == ipo.dst:
                                xyz = temp2[i]
                                if ((xyz[1] == 'PONG')
                                        and (xyz[3] == 'ALLOW')):
                                    flag1 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.logger.info(
                                        "%s  ->  %s : ECHO REPLY ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    self.logger.info(
                                        "\n%s  ->  %s  action= %s  state= ESTABLISHED \n"
                                        % (xyz[0], ipo.src, xyz[2]))
                                    self.current_time.time()
                                    self.logger.info("\n")
                                    break

                    # What about no match ??
                    if (flag1 == 0):
                        actions_default = action_drop
                        self.logger.info("%s  ->  %s : BLOCKED" %
                                         (ipo.src, ipo.dst))

                # Check for TCP
                elif (ipo.proto == IPPROTO_TCP):
                    tcpo = pkt.get_protocol(tcp.tcp)
                    flag2 = 0

                    # TCP SYN packet
                    if (((tcpo.bits & TCP_SYN) == TCP_SYN) &
                        ((tcpo.bits & TCP_BOGUS_FLAGS) == 0x00)):
                        if self.inner_policy.has_key(ipo.src):
                            temp = self.inner_policy.get(ipo.src)
                            for i in range(0, len(temp)):
                                if ((temp[i][0] == ipo.dst)
                                        and (temp[i][1] == 'TCP')
                                        and (int(temp[i][2]) == tcpo.src_port)
                                        and (int(temp[i][3]) == tcpo.dst_port)
                                        and (temp[i][5] == 'ALLOW')):
                                    flag2 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.tcp_conn_track = self.track.conn_track_dict(
                                        self.tcp_conn_track, ipo.src, ipo.dst,
                                        tcpo.src_port, tcpo.dst_port, tcpo.seq,
                                        1)
                                    self.logger.info(
                                        "%s  ->  %s : SYN ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    break

                    # TCP SYN ACK packet
                    elif ((tcpo.bits & TCP_SYN_ACK) == TCP_SYN_ACK):
                        if self.tcp_conn_track.has_key(ipo.dst):
                            temp2 = self.tcp_conn_track.get(ipo.dst)
                            for i in range(0, len(temp2)):
                                if ((temp2[i][0] == ipo.src)
                                        and (int(temp2[i][1]) == tcpo.dst_port)
                                        and
                                    (int(temp2[i][2]) == tcpo.src_port)):
                                    flag2 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.tcp_conn_track = self.track.conn_track_dict(
                                        self.tcp_conn_track, ipo.src, ipo.dst,
                                        tcpo.src_port, tcpo.dst_port, tcpo.seq,
                                        1)
                                    self.logger.info(
                                        "%s  ->  %s : SYN ACK ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    self.logger.info(
                                        "\n%s  ->  %s  src_port= %s  dst_port= %s  state= ESTABLISHED \n"
                                        % (ipo.dst, ipo.src, temp2[i][1],
                                           temp2[i][2]))
                                    self.current_time.time()
                                    self.logger.info("\n")
                                    break

                    # All remaining TCP packets, like, ACK, PUSH, FIN etc.
                    else:
                        if self.tcp_conn_track.has_key(ipo.src):
                            temp3 = self.tcp_conn_track.get(ipo.src)
                            for i in range(0, len(temp3)):
                                if ((temp3[i][0] == ipo.dst)
                                        and (int(temp3[i][1]) == tcpo.src_port)
                                        and
                                    (int(temp3[i][2]) == tcpo.dst_port)):
                                    flag2 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.logger.info(
                                        "%s  ->  %s : TRANSMISSION ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    break

                    # What if no match found ?
                    if (flag2 == 0):
                        actions_default = action_drop
                        self.logger.info("%s  ->  %s : SYN BLOCKED" %
                                         (ipo.src, ipo.dst))

                # Check for UDP
                elif (ipo.proto == IPPROTO_UDP):
                    flag3 = 0
                    udpo = pkt.get_protocol(udp.udp)

                    # Check for tracked UDP
                    if self.udp_conn_track.has_key(ipo.dst):
                        tmp_tpl = self.udp_conn_track.get(ipo.dst)
                        tmp = list(tmp_tpl)
                        for i in range(0, len(tmp)):
                            if (tmp[i][0] == ipo.src):
                                xyz = tmp[i]
                                if ((int(xyz[1]) == udpo.dst_port)
                                        and (int(xyz[2]) == udpo.src_port)
                                        and (xyz[3] == 'UNREPLIED')):
                                    flag3 = 1
                                    self.logger.info(
                                        "%s  ->  %s  : UDP PACKET ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    actions_default = action_fwd_to_out_port
                                    del tmp[
                                        i]  ###  We need to remove this state entry to keep this packet 'REPLIED'
                                    self.logger.info(
                                        "\n%s  ->  %s  src_port= %s  dst_port= %s  state= ASSURED\n"
                                        % (ipo.src, ipo.dst, udpo.src_port,
                                           udpo.dst_port))
                                    break
                        tmp_tpl = tuple(tmp)
                        if len(tmp_tpl) != 0:
                            self.udp_conn_track[ipo.dst] = tmp_tpl
                        else:
                            self.udp_conn_track.pop(ipo.dst, None)

                    # Check for first UDP packet
                    elif self.inner_policy.has_key(ipo.src):
                        temp = self.inner_policy.get(ipo.src)
                        for i in range(0, len(temp)):
                            if temp[i][0] == ipo.dst:
                                xyz = temp[i]
                                if ((xyz[1] == 'UDP')
                                        and (int(xyz[2]) == udpo.src_port)
                                        and (int(xyz[3]) == udpo.dst_port)
                                        and (xyz[5] == 'ALLOW')):
                                    flag3 = 1
                                    actions_default = action_fwd_to_out_port
                                    self.udp_conn_track = self.track.conn_track_dict(
                                        self.udp_conn_track, ipo.src, ipo.dst,
                                        udpo.src_port, udpo.dst_port,
                                        "UNREPLIED", 1)
                                    self.logger.info(
                                        "%s  ->  %s  : UDP PACKET ALLOWED" %
                                        (ipo.src, ipo.dst))
                                    self.logger.info(
                                        "\n%s  ->  %s  src_port= %s  dst_port= %s  state= UNREPLIED\n"
                                        % (ipo.src, ipo.dst, udpo.src_port,
                                           udpo.dst_port))
                                    self.current_time.time()
                                    self.logger.info("\n")
                                    break

                    # what if no match found ?
                    if (flag3 == 0):
                        actions_default = action_drop
                        self.logger.info("%s  ->  %s : UDP BLOCKED" %
                                         (ipo.src, ipo.dst))

                # If not ICMP, TCP or UDP then drop..!
                else:
                    self.logger.info("Wrong IP protocol found")
                    actions_default = action_drop

            # Handling ARP Rules.
            elif (ethtype == ETH_TYPE_ARP):
                self.arp_handling(datapath, out_port, eth, in_port)
                actions_default = action_fwd_to_out_port

            # If packet is not IP or ARP then drop..!
            else:
                actions_default = action_drop

        except Exception as err:
            self.logger.info("MYERROR: %s", err.message)
            action_drop = [parser.OFPActionOutput(ofproto.OFPPC_NO_FWD)]
            actions_default = action_drop

        finally:
            self.sendpkt.send(datapath, msg, in_port, actions_default)

    """
        Add ARP rules on Flow Tables
    """

    def arp_handling(self, datapath, out_port, eth_obj, in_port):
        if (out_port != datapath.ofproto.OFPP_FLOOD):
            actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
            self.flow.add_flow(datapath=datapath,
                               actions=actions,
                               priority=1000,
                               in_port=in_port,
                               eth_type=ETH_TYPE_ARP,
                               eth_src=eth_obj.src,
                               eth_dst=eth_obj.dst)

    """
        Learn Switch port associated with a MAC address here
    """

    def port_learn(self, datapath, eth_obj, in_port):
        try:
            self.mac_to_port.setdefault(datapath.id, {})
            self.mac_to_port[datapath.id][eth_obj.src] = in_port

            if (eth_obj.ethertype == ETH_TYPE_IP) or (eth_obj.ethertype
                                                      == ETH_TYPE_ARP):
                if eth_obj.dst in self.mac_to_port[datapath.id]:
                    out_port = self.mac_to_port[datapath.id][eth_obj.dst]
                else:
                    out_port = datapath.ofproto.OFPP_FLOOD
        except Exception as err:
            self.info(err.message)
            out_port = datapath.ofproto.OFPP_FLOOD
        finally:
            return out_port