Untitled

 avatar
unknown
plain_text
5 months ago
13 kB
6
Indexable
# Lab5 Skeleton

from pox.core import core
import pox.openflow.libopenflow_01 as of
import pox.lib.packet as pkt
from time import time
import ipaddress

log = core.getLogger()


class Routing(object):
    # ROUTING RULES:
    # RULE 1: ICMP traffic forwarded only between Student Housing LAN, Faculty LAN, and IT Department subnets (or between devices on the same subnet)
    # RULE 2: TCP traffic forwarded only between the University Data Center, IT Department, Faculty LAN, Student Housing LAN, trustedPC, or between devices on the same subnet, however only the Faculty LAN can access the exam server
    # RULE 3: UDP traffic is forwarded only between the University Data Center, IT Department, Faculty LAN, Student Housing LAN, or between devices on the same subnet
    # RULE 4: All other traffic should be dropped

    def __init__(self, connection):
        # Keep track of the connection to the switch so that we can
        # send it messages!
        self.connection = connection

        # This binds our PacketIn event listener
        connection.addListeners(self)

        # define subnets
        self.subnets = {
            'faculty': ipaddress.ip_network('10.0.1.0/24'),
            'student': ipaddress.ip_network('10.0.2.0/24'),
            'it_dept': ipaddress.ip_network('10.40.3.0/24'),
            'exam_server': ipaddress.ip_network('10.100.100.2/32'),
            'data_center': ipaddress.ip_network('10.100.100.0/24'),
            'trusted_pc': ipaddress.ip_network('10.0.203.6/32'),
            'guest1': ipaddress.ip_network('10.0.198.6/32'),
            'guest2': ipaddress.ip_network('10.0.198.10/32')

            # ,
            # add guest1 and guest2
        }

        # subnet to switch map
        self.subnet_switch = {
            'core': 1,
            'faculty': 2,
            'student': 3,
            'it_dept': 4,
            'data_center': 5
        }


        # return what subnet an IP is in

    def get_subnet(self, ip):
        ip = ipaddress.ip_address(ip)
        print("GET_SUBNET IP:", ip)
        # iterate across subnets and submit name if there's an IP match'
        for name, subnet in self.subnets.items():
            if ip in subnet:
                print("SUBNET FOUND:", name)
                return name
        return None

        # check if two IP in the same subnet

    def same_subnet(self, ip1, ip2):
        ip1 = ipaddress.ip_address(ip1)
        ip2 = ipaddress.ip_address(ip2)
        print("SAME_SUBNET:", ip1, " ", ip2)

        for subnet in self.subnets.values():
            if ip1 in subnet and ip2 in subnet:
                return True
        return False

    def do_routing(self, packet, packet_in, port_on_switch, switch_id):
        # port_on_switch - the port on which this packet was received
        # switch_id - the switch which received this packet]

        def accept(out_port, idle_timeout=30):
            msg = of.ofp_flow_mod()
            msg.match = of.ofp_match.from_packet(packet)
            msg.idle_timeout = idle_timeout
            msg.hard_timeout = 300
            msg.priority = 1

            if packet_in.buffer_id != of.NO_BUFFER and packet_in.buffer_id is not None:
                msg.buffer_id = packet_in.buffer_id
            else:
                msg.data = packet_in

            # check if there is a list of ports, if there is, we assign multiple actions
            if isinstance(out_port, list):
                for port in out_port:
                    msg_copy = msg
                    msg_copy.match = of.ofp_match.from_packet(packet)
                    msg_copy.idle_timeout = idle_timeout
                    msg_copy.hard_timeout = 300
                    msg_copy.priority = 1
                    if packet_in.buffer_id != of.NO_BUFFER and packet_in.buffer_id is not None:
                        msg_copy.buffer_id = packet_in.buffer_id
                    else:
                        msg_copy.data = packet_in
                    msg_copy.actions.append(of.ofp_action_output(port=port))
                    self.connection.send(msg_copy)
            else:
                msg.actions.append(of.ofp_action_output(port=out_port))
                self.connection.send(msg)

            print("Packet Accepted")

        def drop():
            msg = of.ofp_flow_mod()
            msg.match = of.ofp_match.from_packet(packet_in)
            msg.idle_timeout = 45
            msg.hard_timeout = 600
            self.connection.send(msg)
            print("Packet Dropped - Flow Table Installed on Switches")

        # PACKET HANDLING BEGINS
        if packet.find('arp') is not None:
            msg = of.ofp_flow_mod()
            msg.match = of.ofp_match.from_packet(packet)
            msg.idle_timeout = 30
            msg.hard_timeout = 300
            msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            self.connection.send(msg)
            return

        # print("PACKET BEGINS")

        # RULE 1: determine if ICMP
        print("NOT ARP PACKET")
        print(packet)
        ip_packet = packet.find('ipv4')
        if not ip_packet:
            return

        src_ip = ip_packet.srcip
        dst_ip = ip_packet.dstip

        src_subnet = self.get_subnet(src_ip)
        dst_subnet = self.get_subnet(dst_ip)

        print(ip_packet)

        # switch_ID to check what switch I'm on
        # if destination is this IP
        # return this port, or return that port, or return that port

        # do_routing contains accept and drop and 4 rules
        # 2 helper functions: 1 of them is same_subnet, and a

        # rule 1: ICMP
        # GOAL: if/else tree individually handling ICMP, TCP, UDP
        # this tree will determine source and destination ports
        # it will do this based on a source and destination IP to determine a given subnet

        # #define subnets
        # self.subnets = {
        #   'faculty': ipaddress.ip_network('10.0.1.0/24'),
        #   'student': ipaddress.ip_network('10.0.2.0/24'),
        #   'it_dept': ipaddress.ip_network('10.40.3.0/24'),
        #   'exam_server': ipaddress.ip_network('10.100.100.2/32'),
        #   'data_center': ipaddress.ip_network('10.100.100.0/24'),
        #   'trusted_pc': ipaddress.ip_network('10.0.203.6/32')
        #   }

        # switch_id
        # port_on_switch
        if ip_packet.protocol == 1:  # 1 is ICMP
            #if an ICMP packet is going to switch 1, it means it must be trying to go to an external (non-source subnet)
            #therefor, i only need to check the case for external subnets - in this case faculty, student, it_dept
            #only ICMP packets from the faculty, student, and IT would get here anyway
            if (switch_id == 's1'): #core switch
                if (dst_subnet == 'faculty' and (port_on_switch == 3 or port_on_switch == 2 or port_on_switch == 4)):
                    dest_port = 2
                    accept(dest_port)
                    return
                if (dst_subnet == 'student' and (port_on_switch == 3 or port_on_switch == 2 or port_on_switch == 4)):
                    dest_port = 3
                    accept(dest_port)
                    return
                if (dst_subnet == 'it_dept' and (port_on_switch == 3 or port_on_switch == 2 or port_on_switch == 4)):
                    dest_port = 4
                    accept(dest_port)
                    return
                drop()
                return

            if (switch_id == 's2'): #faculty switch
                if (port_on_switch == 1):
                    #means it is coming from subnet
                    #if going to same subnet, route there
                    if (dst_subnet == 'faculty'):
                        if (dst_ip == '10.0.1.2'):
                            dest_port = 3
                        elif (dst_ip == '10.0.1.3'):
                            dest_port = 4
                        elif (dst_ip == '10.0.1.4'):
                            dest_port = 5
                        else:
                            drop()
                            return
                        accept(dest_port)
                        return
                    #otherwise, must either go to student or it_dept to be externally routed to s1
                    if (dst_subnet == 'student' or dst_subnet == 'it_dept'):
                        dest_port = 1
                        accept(dest_port)
                        return
                    drop()
                    return
                #means it is coming from s1
                elif (port_on_switch == 2):
                    #route internally or drop
                    if (dst_subnet == 'faculty'):
                        if (dst_ip == '10.0.1.2'):
                            dest_port = 3
                        elif (dst_ip == '10.0.1.3'):
                            dest_port = 4
                        elif (dst_ip == '10.0.1.4'):
                            dest_port = 5
                        else:
                            drop()
                            return
                        accept(dest_port)
                        return
                    drop()
                    return
            if (switch_id == 's3'): #student switch
                #means it is coming from subnet
                if (port_on_switch == 1):
                    if (dst_subnet == 'student'):
                        if (dst_ip == '10.0.2.2'):
                            dest_port = 4
                        if (dst_ip == '10.0.2.3'):
                            dest_port = 6
                        if (dst_ip == '10.0.2.40'):
                            dest_port = 5
                        accept(dest_port)
                        return
                    #only externally route if it_dept or faculty
                    elif (dst_subnet == 'it_dept' or dst_subnet == 'faculty'):
                        dest_port = 1
                        accept(dest_port)
                        return
                #3 means its coming from s1
                if (port_on_switch == 3):
                    if (dst_subnet == 'student'):
                        if (dst_ip == '10.0.2.2'):
                            dest_port = 4
                        if (dst_ip == '10.0.2.3'):
                            dest_port = 6
                        if (dst_ip == '10.0.2.40'):
                            dest_port = 5
                        accept(dest_port)
                        return
                drop()
                return

            if (switch_id == 's4'): #it switch
                if (port_on_switch == 1):
                    if (dst_subnet == 'it_dept'):
                        if (dst_ip == '10.40.3.30'):
                            dest_port = 5
                        if (dst_ip == '10.40.3.254'):
                            dest_port = 6
                        accept(dest_port)
                        return
                    elif (dst_subnet == 'faculty' or dst_subnet == 'student')
                #coming from s1
                if (port_on_switch == 4):
                    if(dst_subnet == 'it_dept'):
                        if(dst_ip == '10.40.3.30'):
                            dest_port = 5
                        if (dst_ip == '10.40.3.254'):
                            dest_port = 6
                        accept(dest_port)
                        return
                drop()
                return
            if (switch_id == 's5'):
                #datacenter switch
                if (port_on_switch == 5): #coming from s1
                    #should not have any input from s1 ever
                    drop()
                    return
                if (port_on_switch == 1): #coming from subnet
                    if(dst_subnet == 'data_center' or dst_subnet == 'exam_server')
                        if(dst_ip == '10.100.100.2'):
                            dest_port = 6
                        if(dst_ip == '10.100.100.20'):
                            dest_port = 7
                        if(dst_ip == '10.100.100.56'):
                            dest=port = 8
                        accept(dest_port)
                        return

        #later implement rules 2 and 3
        print("PACKET TYPE INVALID")

        # rule 4
        drop()

    def _handle_PacketIn(self, event):
        """
        Handles packet in messages from the switch.
        """
        packet = event.parsed  # This is the parsed packet data.
        if not packet.parsed:
            log.warning("Ignoring incomplete packet")
            return

        packet_in = event.ofp  # The actual ofp_packet_in message.
        self.do_routing(packet, packet_in, event.port, event.dpid)


def launch():
    """
    Starts the component
    """

    def start_switch(event):
        log.debug("Controlling %s" % (event.connection,))
        Routing(event.connection)

    core.openflow.addListenerByName("ConnectionUp", start_switch)
Editor is loading...
Leave a Comment