实验5实验6_102101616_许之烨

102101616许之烨

实验5︰开源控制器实践——POX

⼀、阅读Hub模块代码,使⽤tcpdump 验证Hub模块

h1 ping h2的tcpdump的抓包截图(Hub模块)

在这里插入图片描述

h1 ping h3

在这里插入图片描述

根据上⽅截图可以发现,不管h1 ping h2还是h3,h2和h3都能接收到数据包,符合Hub模块的作⽤:在每个交换机上安装泛洪通配符规则,将数据包⼴播转发,此时交换机等效于集线器。

⼆、阅读L2_learning模块代码,使⽤tcpdump 验证Switch模块。

h1 ping h2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

h1 ping h3

在这里插入图片描述
根据上方截图可以发现,当h1 ping相应主机时,只有相应主机可以接收到数据包,原因是Switch模块的作用:让OpenFlow交换机实现L2自学习

实验6:开源控制器实践——RYU

⼀、搭建下图所⽰SDN拓扑,协议使⽤Open Flow 1.0,并连接Ryu控制器,通过Ryu的图形界⾯查看⽹络拓扑。

在这里插入图片描述

⼆、阅读Ryu⽂档的The First Application⼀节,运⾏当中的L2Switch,h1ping h2或h3,在⽬标主机使⽤ tcpdump 验证L2Switch,分析L2Switch和POX的Hub模块有何不同。

L2Switch.py代码

from ryu.base import app_manager
 from ryu.controller import ofp_event
 from ryu.controller.handler import MAIN_DISPATCHER
 from ryu.controller.handler import set_ev_cls
 from ryu.ofproto import ofproto_v1_0
 class L2Switch(app_manager.RyuApp):
 OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
 def __init__(self, *args, **kwargs):
 super(L2Switch, self).__init__(*args, **kwargs)
 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
 def packet_in_handler(self, ev):
 msg = ev.msg
 dp = msg.datapath
 ofp = dp.ofproto
 ofp_parser = dp.ofproto_parser
 actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
 data = None
 if msg.buffer_id == ofp.OFP_NO_BUFFER:
 data = msg.data
 out = ofp_parser.OFPPacketOut(
 datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
 actions=actions, data = data)
 dp.send_msg(out)

重新构建拓扑,并对h2、h3节点进抓包

h1 ping h2

在这里插入图片描述

h1 ping h3

在这里插入图片描述

结论:RYU的L2Switch模块和POX的Hub模块都采洪泛转发,但不同之处在于可以在pox的Hub模块运时查看流表,在ryu的L2Switch模块运时查看到流表。

三、编程修改L2Switch.py,另存为L2xxxxxxxxx.py,使之和POX的Hub模块的变得⼀致

102101616.py

from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
class hub(app_manager.RyuApp):
 OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
 def __init__(self, *args, **kwargs):
 super(hub, self).__init__(*args, **kwargs)
 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
 def switch_feathers_handler(self, ev):
 datapath = ev.msg.datapath
 ofproto = datapath.ofproto
 ofp_parser = datapath.ofproto_parser
 # install flow table-miss flow entry
 match = ofp_parser.OFPMatch()
 actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
ofproto.OFPCML_NO_BUFFER)]
 # 1\OUTPUT PORT, 2\BUFF IN SWITCH?
 self.add_flow(datapath, 0, match, actions)
 def add_flow(self, datapath, priority, match, actions):
 # 1\ datapath for the switch, 2\priority for flow entry, 3\match field,
4\action for packet
 ofproto = datapath.ofproto
 ofp_parser = datapath.ofproto_parser
 # install flow
 inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
actions)]
 mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=priority,
match=match, instructions=inst)
 datapath.send_msg(mod)
 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
 def packet_in_handler(self, ev):
 msg = ev.msg
 datapath = msg.datapath
 ofproto = datapath.ofproto
 ofp_parser = datapath.ofproto_parser
 in_port = msg.match['in_port'] # get in port of the packet
 # add a flow entry for the packet
 match = ofp_parser.OFPMatch()
 actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]
 self.add_flow(datapath, 1, match, actions)
 # to output the current packet. for install rules only output later
packets
 out = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
in_port=in_port, actions=actions)
 # buffer id: locate the buffered packet
 datapath.send_msg(out)

结果

在这里插入图片描述
在这里插入图片描述

四、编程实现和OpenDaylight实验的样的硬超时功能

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
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
 # 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. The bug has been fixed in OVS v2.1.0.
 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,
hard_timeout=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,
 priority=priority, match=match,
 instructions=inst, hard_timeout=hard_timeout)
 else:
 mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
 match=match, instructions=inst,
hard_timeout=hard_timeout)
 datapath.send_msg(mod)
 @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
 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:
 # ignore lldp packet
 return
 dst = eth.dst
 src = eth.src
 dpid = format(datapath.id, "d").zfill(16)
 self.mac_to_port.setdefault(dpid, {})
 self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
 # 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)]\
 actions_timeout=[]
 # install a flow to avoid packet_in next time
 if out_port != ofproto.OFPP_FLOOD:
 match = parser.OFPMatch(in_port=in_port, eth_dst=dst, eth_src=src)
 # verify if we have a valid buffer_id, if yes avoid to send both
 # flow_mod & packet_out
 hard_timeout=10
 if msg.buffer_id != ofproto.OFP_NO_BUFFER:
 self.add_flow(datapath, 2, match,actions_timeout,
msg.buffer_id,hard_timeout=10)
 self.add_flow(datapath, 1, match, actions, msg.buffer_id)
 return
 else:
 self.add_flow(datapath, 2, match, actions_timeout,
hard_timeout=10)
 self.add_flow(datapath, 1, match, actions)
 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)

实验六进阶要求

代码

import json
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller import 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 icmp
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib import hub
from random import randint,seed
from time import time
#Custom Event for time out
class EventMessage(event.EventBase):
 '''Create a custom event with a provided message'''
 def __init__(self, message):
 print("Creating Event")
 super(EventMessage, self).__init__()
 self.msg=message
#Main Application
class MovingTargetDefense(app_manager.RyuApp):
 OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
 _EVENTS = [EventMessage] 
 R2V_Mappings=
{"10.0.0.1":"","10.0.0.2":"","10.0.0.3":"","10.0.0.4":"","10.0.0.5":"","10.0.0.6":
"","10.0.0.7":"","10.0.0.8":""}
 V2R_Mappings={} 
 AuthorizedEntities=['10.0.0.1']
 Resources=["10.0.0.9","10.0.0.10","10.0.0.11","10.0.0.12",
 "10.0.0.13","10.0.0.14","10.0.0.15","10.0.0.16",
 "10.0.0.17","10.0.0.18","10.0.0.19","10.0.0.20",
 "10.0.0.21","10.0.0.22","10.0.0.23","10.0.0.24",
 "10.0.0.25","10.0.0.26","10.0.0.27","10.0.0.28",
 "10.0.0.29","10.0.0.30","10.0.0.31","10.0.0.32",
 "10.0.0.33","10.0.0.34","10.0.0.35","10.0.0.36"]
 def start(self):
 '''
 Append a new thread which calls the TimerEventGen function which
generates timeout events
 every 30 seconds & sends these events to its listeners
 Reference: https://sourceforge.net/p/ryu/mailman/ryu-devel/?
viewmonth=201601&viewday=12
 '''
 super(MovingTargetDefense,self).start()
 self.threads.append(hub.spawn(self.TimerEventGen))
 
 def TimerEventGen(self):
 
 '''
 A function which generates timeout events every 30 seconds
 & sends these events to its listeners
 Reference: https://sourceforge.net/p/ryu/mailman/ryu-devel/?
viewmonth=201601&viewday=12
 '''
 while 1:
 self.send_event_to_observers(EventMessage("TIMEOUT"))
 hub.sleep(30)
 
 def __init__(self, *args, **kwargs):
 '''Constructor, used to initialize the member variables'''
 super(MovingTargetDefense, self).__init__(*args, **kwargs)
 self.mac_to_port = {}
 self.datapaths=set()
 self.HostAttachments={}
 self.offset_of_mappings=0
 
 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
 def handleSwitchFeatures(self, ev):
 '''
 Handles switch feature events sent by the switches to the controller
 the first time switch sends negotiation messages.
 We store the switch info to the datapaths member variable
 & add table miss flow entry to the switches.
 
 #Reference: Simple_Switch
 #http://ryu.readthedocs.io/en/latest/writing_ryu_app.html
 '''
 datapath = ev.msg.datapath
 ofproto = datapath.ofproto
 parser = datapath.ofproto_parser
 self.datapaths.add(datapath);
 # install table-miss flow entry
 match = parser.OFPMatch()
 actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
 ofproto.OFPCML_NO_BUFFER)]
 self.add_flow(datapath, 0, match, actions)
 
 def EmptyTable(self,datapath):
 '''
 Empties flow table of a switch!
 Remove Flow rules from switches
 Reference: https://sourceforge.net/p/ryu/mailman/message/32333352/
 '''
 ofProto=datapath.ofproto
 parser = datapath.ofproto_parser
 match=parser.OFPMatch()
 
flow_mod=datapath.ofproto_parser.OFPFlowMod(datapath,0,0,0,ofProto.OFPFC_DELETE,0,
0,1,ofProto.OFPCML_NO_BUFFER,ofProto.OFPP_ANY,ofProto.OFPG_ANY,0,match=match,instr
uctions=[])
 datapath.send_msg(flow_mod)
 
 #Listen to timeout & update the mappings
 @set_ev_cls(EventMessage)
 def update_resources(self,ev):
 '''
 Listen to the Time-out event & update the real-virtual IP address
mappings from the resources
 Also remove the flow rules from all the switches.
 & Add a default, table-miss entry to all the switches.
 
 '''
 '''seed function is used initialize random number generator. The current
system time is seeded to
 obtain different set of random numbers every time the function runs.''' 
 seed(time())
 pseudo_ranum = randint(0,len(self.Resources)-1) #randint returns a random
integer in the range of 0 and len(Resources)-1
 print ("Random Number:",pseudo_ranum)
 for keys in self.R2V_Mappings.keys():
 #Virtual IP address are assigned to each host from the pool of
Resources starting from (pseudo_ranum)th index
 self.R2V_Mappings[keys]=self.Resources[pseudo_ranum]
 #pseudo_ranum is updated to point to next index. If the index is
overshooted from the Resources pool, it is looped back to point to 0th index 
 pseudo_ranum=(pseudo_ranum+1)%len(self.Resources) 
 self.V2R_Mappings = {v: k for k, v in self.R2V_Mappings.items()}
 print ("**********", self.R2V_Mappings,"***********")
 print ("**********", self.V2R_Mappings,"***********")
 '''
 Reference: https://sourceforge.net/p/ryu/mailman/message/32333352/
 How to remove flowrules from switches
 '''
 for curSwitch in self.datapaths:
 #Remove all flow entries
 parser = curSwitch.ofproto_parser
 match=parser.OFPMatch()
 flowModMsg=self.EmptyTable(curSwitch)
 #Add default flow rule
 ofProto=curSwitch.ofproto
 actions = [parser.OFPActionOutput(ofProto.OFPP_CONTROLLER,
 ofProto.OFPCML_NO_BUFFER)]
 self.add_flow(curSwitch, 0, match, actions)
 
 def isRealIPAddress(self,ipAddr):
 '''Returns True id IP address is real'''
 if ipAddr in self.R2V_Mappings.keys():
 return True
 
 def isVirtualIPAddress(self,ipAddr):
 ''' Returns True if the IP address is virtual'''
 if ipAddr in self.R2V_Mappings.values():
 return True
 
 '''def isAuthorizedEntity(self,ipAddr):
 if ipAddr in self.AuthorizedEntities:
 return True'''
 
 def isDirectContact(self,datapath,ipAddr):
 '''
 Return true if the IP addr host is directky connected to the switch
given
 Also assumes that the host is directly connected if it has no
information in the hostAttachments Table
 '''
 if ipAddr in self.HostAttachments.keys():
 if self.HostAttachments[ipAddr]==datapath:
 return True
 else:
 return False
 return True
 
 
 def add_flow(self, datapath, priority, match, actions, buffer_id=None,
hard_timeout=None):
 '''
 Adds flow rules to the switch 
 Reference: Simple_Switch
 http://ryu.readthedocs.io/en/latest/writing_ryu_app.html
 '''
 ofproto = datapath.ofproto
 parser = datapath.ofproto_parser
 
 inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
 actions)]
 if buffer_id :
 if hard_timeout==None:
 mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
 priority=priority, match=match,
 instructions=inst)
 else:
 mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
 priority=priority, match=match,
 instructions=inst, hard_timeout=hard_timeout)
 else:
 if hard_timeout==None:
 mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
 match=match, instructions=inst)
 else:
 mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
 match=match, instructions=inst,
hard_timeout=hard_timeout)
 datapath.send_msg(mod)
 #Packet Handler ICMP & ARP
 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
 def handlePacketInEvents(self, ev):
 '''
 Handles Incoming Packets & implements Random Host mutation technique
 by changing src & dst IP addresses of the incoming packets.
 Some part of the code is inspired by Simple_Switch
 http://ryu.readthedocs.io/en/latest/writing_ryu_app.html 
 '''
 actions=[]
 pktDrop=False
 
 
 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
 dpid = datapath.id
 ofproto = datapath.ofproto
 parser = datapath.ofproto_parser
 in_port = msg.match['in_port']
 pkt = packet.Packet(msg.data)
 arp_Obj=pkt.get_protocol(arp.arp)# Extract ARP object from packet
 icmp_Obj=pkt.get_protocol(ipv4.ipv4)# Extract ICMP object packet
 
 if arp_Obj:
 '''Handles ARP packets'''
 src=arp_Obj.src_ip
 dst=arp_Obj.dst_ip
 
 '''
 To Implement a Learning MTD, there is a need to know, to which
switch, the host is directly connected to.
 So the first time an ARP packet comes in who's src address is
real, we store the IP addr-Switch DPID mapping
 into the member variable HostAttachments.
 '''
 if self.isRealIPAddress(src) and src not in
self.HostAttachments.keys():
 self.HostAttachments[src]=datapath.id
 
 '''
 Learning MTD implementation
 if src is real change it to virtual no matter wat.
 if dest doesn't have a mapping in my table change to real and
flood.
 This happens only for the first time when we donot know
 to which switch, the destination host is directly connected
to.
 if dst is virtual check if dest is directly connected then change
it to real
 else let it pass unchanged.
 '''
 
 if self.isRealIPAddress(src):
 
match=parser.OFPMatch(eth_type=0x0806,in_port=in_port,arp_spa=src,arp_tpa=dst)
 spa = self.R2V_Mappings[src] 
 print("Changing SRC REAL IP "+src+"---> Virtual SRC IP "+spa)
 actions.append(parser.OFPActionSetField(arp_spa=spa))
 
 if self.isVirtualIPAddress(dst):
 match= 
parser.OFPMatch(eth_type=0x0806,in_port=in_port,arp_tpa=dst,arp_spa=src)
 if
self.isDirectContact(datapath=datapath.id,ipAddr=self.V2R_Mappings[dst]):
 keys = self.V2R_Mappings.keys() 
 tpa = self.V2R_Mappings[dst] 
 print("Changing DST Virtual IP "+dst+"---> REAL DST IP "+tpa)
 actions.append(parser.OFPActionSetField(arp_tpa=tpa))
 
 elif self.isRealIPAddress(dst):
 '''Learn MTD From Flood'''
 
match=parser.OFPMatch(eth_type=0x0806,in_port=in_port,arp_spa=src,arp_tpa=dst)
 if not self.isDirectContact(datapath=datapath.id,ipAddr=dst):
 pktDrop=True
 print ("Dropping from",dpid)
 else:
 pktDrop=True
 elif icmp_Obj:
 '''Handles ICMP packets'''
 print("ICMP PACKET FOUND!")
 src=icmp_Obj.src
 dst=icmp_Obj.dst
 
 if self.isRealIPAddress(src) and src not in
self.HostAttachments.keys():
 self.HostAttachments[src]=datapath.id
 
 '''
 Learning MTD implementation
 if src is real change it to virtual no matter wat.
 if dest doesn't have a mapping in my table change to real and
flood.
 This happens only for the first time when we donot know
 to which switch, the destination host is directly connected
to.
 if dst is virtual check if dest is directly connected then change
it to real
 else let it pass unchanged.
 '''
 
 if self.isRealIPAddress(src): 
 match= 
parser.OFPMatch(eth_type=0x0800,in_port=in_port,ipv4_src=src,ipv4_dst=dst)
 ipSrc = self.R2V_Mappings[src]
 print("Changing SRC REAL IP "+src+"---> Virtual SRC IP "+ipSrc)
 actions.append(parser.OFPActionSetField(ipv4_src=ipSrc))
 if self.isVirtualIPAddress(dst):
 #print self.HostAttachments
 match= 
parser.OFPMatch(eth_type=0x0800,in_port=in_port,ipv4_dst=dst,ipv4_src=src)
 if
self.isDirectContact(datapath=datapath.id,ipAddr=self.V2R_Mappings[dst]):
 ipDst = self.V2R_Mappings[dst] 
 print("Changing DST Virtual IP "+dst+"---> Real DST IP
"+ipDst)
 actions.append(parser.OFPActionSetField(ipv4_dst=ipDst))
 
 elif self.isRealIPAddress(dst):
 '''Learn From Flood'''
 
match=parser.OFPMatch(eth_type=0x0806,in_port=in_port,arp_spa=src,arp_tpa=dst)
 if not self.isDirectContact(datapath=datapath.id,ipAddr=dst):
 pktDrop=True
 print ("Dropping from",dpid)
 else:
 pktDrop=True
 
 '''Extract Ethernet Object from packet''' 
 eth = pkt.get_protocols(ethernet.ethernet)[0]
 dst = eth.dst
 src = eth.src
 '''Store the incoming packet source address, switch & the port combination
to be used to learn the packet switching'''
 self.mac_to_port.setdefault(dpid, {})
 self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
 
 '''learn a mac address to avoid FLOOD next time.'''
 
 self.mac_to_port[dpid][src] = in_port
 '''Learning Mac implemention to avoid flood'''
 if dst in self.mac_to_port[dpid]:
 out_port = self.mac_to_port[dpid][dst]
 else:
 out_port = ofproto.OFPP_FLOOD
 if dst in self.mac_to_port[dpid]:
 out_port = self.mac_to_port[dpid][dst]
 else:
 out_port = ofproto.OFPP_FLOOD
 '''Append the outport action to the action set'''
 if not pktDrop:
 actions.append(parser.OFPActionOutput(out_port))
 '''install a flow to avoid packet_in next time'''
 if out_port != ofproto.OFPP_FLOOD:
 '''
 verify if we have a valid buffer_id, if yes avoid to send both
flow_mod & packet_out
 Install Flow rules to avoid the packet in message for similar
packets.
 '''
 if msg.buffer_id != ofproto.OFP_NO_BUFFER:
 self.add_flow(datapath, 1, match, actions,msg.buffer_id)
 return
 else:
 self.add_flow(datapath, 1, match, actions) 
 data = None
 if msg.buffer_id == ofproto.OFP_NO_BUFFER:
 data = msg.data
 '''
 Build a packet out message & send it to the switch with the action
set,
 Action set includes all the IP addres changes & out port actions.
 '''
 out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
 in_port=in_port, actions=actions, data=data)
 '''Send the packet out message to the switch'''
 datapath.send_msg(out)

运行结果

在这里插入图片描述

交换机流表

在这里插入图片描述

回答问题

项目实现了什么功能?具体怎么实现?你认为这样的机制形成了一个什么样的防御?
使用SDN的移动目标防御机制 开发了一种移动目标防御机制,以防止来自内部和外部网络的IP扫描。基于随机主机变异技术, 在SDN中控制数据包流动。使用控制器提供的北向API开发了一种新的路由机制,使用多线程、 装饰器、事件创建和事件处理技术。使用Python对OpenFlow协议和RYU控制器进行了广泛的测 试和评估。 在这个项目中,网络资产对外部和内部攻击者是隐藏的。
OpenFlow控制器被智能编程以执行IP 变异技术。这种技术通过为底层主机分配虚拟IP地址以高变异率来改变真实IP地址。虚拟IP地址 是从使用伪随机数生成器生成的未分配IP地址池中提取的,以确保高度的不可预测性。
开发了一个自学习算法以实现自动化。
详细算法:
该项目的主要目标是通过动态地址分配来防止IP扫描。 在这个方案中,网络中的每个主机都有两个地址,一个是真实地
址,另一个是虚拟地址。 真实IP地址之间的通信被阻断,只允许在虚拟IP地址之间进行通信。 因此,即使攻击者获取目标的信息,它在一定的超时时间后也会发生变化。 唯一的假设是网络中主机之间的通信是使用域名进行的。 我使用了一种称为随机主机变异的技术来实现这一点,该技术在IEEE论文中发表过。
周期性超时事件成:通过定时器每30秒成超时事件,于触发IP地址映射的更新。
SDN交换机流表控制:通过向SDN交换机下发流表项,实现对数据包的转发控制。根据不同的情况,动态更新 流表以实现IP地址的转换。 数据包处理︓ 在数据包传输事件处理函数中,根据数据包中的源和标IP地址,以及实现的移动标防御机制,改变数据包的源和标IP地址,实现络拓扑的变化。
综合来看,这个机制通过周期性地改变络实体的IP地址映射,即将真实IP地址与虚拟IP地址进映射,并动态更新流表项,使攻击者难以追踪实际络拓扑和识别真实IP地址。这种动态性和不可预测性增强了络的安全 性,因为攻击者很难确定标的真实位置和属性,从降低了攻击的成功可能性。

个人阶段总结

本次实验和上次实验非常相识,只是上次用的POX控制器,这次实验为Ryu,有了上次实验的,以为这次会非常简单,但是并没有。首先Ryu的图形可视化界面没有完整呈现出网络拓扑,查找方法没有能够解决。后面在ping的时候,一直ping不同,查找了很多方法,有说IP问题,都是过后还是没有用。后面参考同学作业,提示要先运行Ryu在建立topo,后面更换代码,终于可以ping通了。 这次实验让我更深刻理解了RYU控制器实现软件定义的集线器原理和交换机原理,Ryu 是一个基于组件的软件定义网络框架。Ryu 为软件组件提供定义良好的API,使开发人员可以轻松创建新的网络管理和控制应用程序。Ryu 支持各种用于管理网络设备的协议,例如OpenFlow,Netconf,OF-config等。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值