自学内容网 自学内容网

3-3 基于RYU的流量风暴事件原理与响应策略

在传统网络中,存在着一定的广播流量,占据了一部分的网络带宽。同时,在有环的拓扑中,如果不运行某些协议,广播数据还会引起网络风暴,使网络瘫痪。
如有以下的一个网络拓扑结构(3_2_topoplus.py)

from mininet.net import Mininet
from mininet.node import OVSSwitch, Host
from mininet.cli import CLI
from mininet.link import Link
from mininet.node import RemoteController
#import networkx as nx
#import matplotlib.pyplot as plt

def create_network():
    net = Mininet()
        # 创建单个OVS交换机
    switch1 = net.addSwitch('s1', cls=OVSSwitch,protocols='OpenFlow13')
    switch2 = net.addSwitch('s2', cls=OVSSwitch,protocols='OpenFlow13')
    
    
    # 创建2个主机
    host1 = net.addHost('h1', cls=Host, ip='192.168.0.1/24', defaultRoute='via 192.168.0.254')
    host2 = net.addHost('h2', cls=Host, ip='192.168.0.2/24', defaultRoute='via 192.168.0.254')
    host3 = net.addHost('h3', cls=Host, ip='192.168.0.3/24', defaultRoute='via 192.168.0.254')
    host4 = net.addHost('h4', cls=Host, ip='192.168.0.4/24', defaultRoute='via 192.168.0.254')

   
    
    # 连接主机到交换机
    net.addLink(host1, switch1)
    net.addLink(host2, switch1)
    net.addLink(host3, switch2)
    net.addLink(host4, switch2)
#交换机连接交换机
    net.addLink(switch1, switch2)
    net.addLink(switch1, switch2)#环路
     
    
    # 指定控制器的IP地址和端口
    #可以先使用ss -tlnp | grep ryu-manager查看ryu运行后的监听端口
    controller_ip = '127.0.0.1'
    controller_port = 6633

# 创建Mininet网络,并指定控制器和OpenFlow协议版本
  
    net.addController('controller', controller=RemoteController, ip=controller_ip, port=controller_port,protocols='OpenFlow13')
  
    # 启动网络
    net.start()
      
    # 打开命令行界面
    CLI(net)
    
    # 关闭网络
    net.stop()

if __name__ == '__main__':
    create_network()

结合上一篇文章中已经实现的控制器应用程序,我们进行测试,并观察产生的数据交互信息,因产生广播风暴(瞬间达到千万级别的包)导致资源崩溃,无法ping通
在这里插入图片描述
在软件定义网络中,要解决以上安全问题,我们可以在控制器应用程序中进行编程实现。下文将实现在控制器RYU应用程序上开发ARP代理功能模块,以解决目前的网络广播风暴安全隐患。

进入/etc/sysctl.conf修改linux内核配置,关闭icmpv6功能
root@zmq-virtual-machine:/etc# vi sysctl.conf
root@zmq-virtual-machine:/etc# nano sysctl.conf
root@zmq-virtual-machine:/etc# nano sysctl.conf
在这里插入图片描述
在文件的末尾添加以下行来禁用 ICMPv6:
复制
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6=1
这将禁用所有接口(all)和默认接口(default)的 IPv6 功能。
然后保存并重新加载配置文件并应用更改:
在这里插入图片描述
以上关闭后最后,重启一下linux系统会重启ipv6
在这里插入图片描述
经过以上操作后,如果生成的host中仍然还有ipv6因为我们在构建网络中比有IP协议的支撑,即使关掉HOST的IPv6 后仍然有ovs生成的虚拟交换机发送相关信息(即使禁用所有设备的ipv6相关你握手包,也还会有IPv4的包,如果都没有握手包,IP协议将因无法正常协商而出现异常)
因此,需要使用编程的办法在ryu控制器APP上进行数据包剔除,把相关的促发信息改为ARP(ping的先行数据包)才进行响应,包括下发流表和mac地址学习等。

解决问题: 前面的packet_in数据包是没有ip地址的?只有ARP才开始有?
1 在packet_in_handler函数中剔除ICMP

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import set_ev_cls
from ryu.controller.handler import  MAIN_DISPATCHER
from ryu.controller.handler import CONFIG_DISPATCHER
from ryu.ofproto import  ofproto_v1_3
from ryu.lib.packet import  packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ipv6
from ryu.lib.packet import icmp
from ryu.lib.packet import icmpv6


class L2Switch(app_manager.RyuApp):
 def __init__(self, *args, **kwargs):
     super(L2Switch, self).__init__(*args, **kwargs)
     self.mac_port_table={}

 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
 def switch_features_handler(self, ev):
     datapath = ev.msg.datapath
     ofproto = datapath.ofproto

     #msg = ev.msg    #features阶段的数据包没有封装承载其他的协议,因此没有data字段 
     parser=datapath.ofproto_parser
     #pkt = packet.Packet(msg.data)#features阶段的数据包没有封装承载其他的协议,因此没有data字段 
     #icmp_pkt = pkt.get_protocol(icmp.icmp)#features阶段的数据包没有封装承载其他的协议,因此没有data字段 
     #icmp6_pkt = pkt.get_protocol(icmpv6.icmpv6)#features阶段的数据包没有封装承载其他的协议,因此没有data字段 
     #if not icmp_pkt and not icmp6_pkt:  #无需判断
     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):

     ofproto = datapath.ofproto
     parser = datapath.ofproto_parser

     inst=[parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,actions)]
     mod=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_hander(self,ev):
     msg = ev.msg
     dp = msg.datapath
     ofp = dp.ofproto
     ofp_parser = dp.ofproto_parser
     in_port = msg.match['in_port']

     dpid=dp.id
     pkt = packet.Packet(msg.data)
     icmp_pkt = pkt.get_protocol(icmp.icmp)
     icmp6_pkt = pkt.get_protocol(icmpv6.icmpv6)
     if not icmp_pkt  and not icmp6_pkt:
         self.mac_port_table.setdefault(dpid, {})
         pkt = packet.Packet(msg.data)
         eth_pkt = pkt.get_protocols(ethernet.ethernet)[0]

         dst = eth_pkt.dst
         print(dst)
         src = eth_pkt.src
         self.mac_port_table[dpid][src] = in_port
         if dst in self.mac_port_table[dpid]:
             out_port = self.mac_port_table[dpid][dst]
         else:
             out_port = ofp.OFPP_FLOOD
         actions = [ofp_parser.OFPActionOutput(out_port)]

         if out_port != ofp.OFPP_FLOOD:
             match = ofp_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
             if msg.buffer_id != ofp.OFP_NO_BUFFER:
                 self.add_flow(dp, 1, match, actions, msg.buffer_id)
                 print("1")
                 return
             else:
                 self.add_flow(dp, 1, match, actions)
                 print("2")

         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=in_port, actions=actions, data=data)
         dp.send_msg(out)

在这里插入图片描述

本代码运行后,因为剔除了icmp,因此不会因为因为icmp直接产生风暴风险,但是在mininet中执行ping后将产生ARP风暴,效果如下图所示。

在这里插入图片描述


原文地址:https://blog.csdn.net/qq_28938301/article/details/138846675

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!