了解Ryu OpenFlow控制器,mininet,WireShark和tcpdump

我是OpenFlow和SDN的新手。 我需要在Ubuntu或Debian机器上设置Ryu OpenFlow控制器的帮助,并了解一个基本的Ryu应用程序。

注意 :这个问题已经有了答案。

这可能是我在Stack Overflow上写的最长的帖子之一。 我一直在学习OpenFlow,SDN和Ryu,并想在这里记录我的初学者的知识。 如果需要,请纠正/编辑我的帖子。

这个简短的指南假设你已经有计算机网络和主要网络协议的知识。 本指南将帮助您从系统设置开始使用OpenFlow。

1.什么是OpenFlow和SDN?

请阅读OpenFlow – Open Networking Foundation 。

进一步阅读: 网络的未来,以及Scott Shenker和软件定义网络协议的过去,IEEE INFOCOM 2009 。

在你开始之前:

基础设施层包括网络核心内的路由器和交换机。

控制层包括运行OpenFlow控制器的PC以及控制器本身。

应用程序层包含在该控制器上运行的应用程序。 在Ryu中,这些应用程序是用Python编写的。

OpenFlow是基础设施和控制层交互使用的协议。 OpenFlow不提供自己的API。 这是一个开源协议,供开发OpenFlow交换机的供应商和编写控制器的开发人员使用,如Ryu。 该API由控制器提供。

2.在Debian 8上设置Ryu OpenFlow控制器

先决条件

你需要互联网接入。 如果您在虚拟机中运行Debian,请发出以下命令,通过NAT自动配置您的以太网接口:

su dhclient eth0 

启用sudo

Debian默认不会使用sudo。 稍后您将使用的某些Ryu应用程序需要sudo。 您可以安装sudo并将自己添加到sudo'ers列表中,如下所示:

 su apt-get install sudo # you might need to do apt-get update first! nano /etc/sudoers 

找到说%sudo ALL =(ALL:ALL)ALL的行,并在其下面添加一个条目:

 yourusername ALL=(ALL:ALL) ALL 

按CTRL + X,然后按Y将更改保存到sudoers文件。 现在你可以以root身份注销,返回到你自己的shell

 exit 

启用最佳屏幕分辨率(仅限VM)

如果您在Virtual Box中运行Debian,则默认安装不会启用Virtual Box的全屏分辨率支持。 您将在第3节稍后介绍更大的屏幕。现在启用它是一个好主意。

在虚拟机窗口中,单击设备>插入客人添加CD图像…

然后cd到包含文件的目录

 cd /media/cdrom 

由于权限问题,Debian不会让您运行脚本。 将文件复制到您的主目录,更改权限,然后运行它:

 mkdir ~/VBOXGUEST cp * ~/VBOXGUEST cd ~/VBOXGUEST chmod 755 * sudo ./VBoxLinuxAdditions.run 

重启

 sudo shutdown -r now 

安装Git

 sudo apt-get install git 

安装Mininet

Mininet允许您虚拟模拟笔记本电脑/ PC上的各种网络接口。 使用Git安装它:

 cd ~ # if you are in some other directory git clone git://github.com/mininet/mininet cd mininet git tag # this will list available versions git checkout -b 2.2.1 2.2.1 # replace 2.2.1 with the version you wish to install cd .. mininet/util/install.sh -a # default installation, includes all components, recommended 

我建议你安装OpenFlow Wireshark解剖器。 您以后可以安装Wireshark来分析数据包。 OpenFlow Wireshark Dissector帮助Wireshark从OpenFlow数据包中获取尽可能多的信息。

 mininet/util/install.sh -h 

运行以下命令来检查你的mininet安装:

 sudo mn --test pingall 

安装Ryu OpenFlow控制器

OpenFlow控制器使用OpenFlow协议在控制层和基础设施层之间进行通信。 此外,它是提供API来开发在应用层(在控制层之上)运行的SDN应用程序的控制器。 有许多OpenFlow控制器。 Ryu OpenFlow控制器是一个使用Python脚本作为应用程序的控制器。 再次,使用Git安装它:

 cd ~ git clone git://github.com/osrg/ryu.git 

安装Wireshark

 sudo apt-get install wireshark 

安装支持的Python模块

Debian 8.3默认安装了Python 2.7和3.4。 但是,您需要安装Ryu应用程序(Python脚本)使用的一些Python模块。 您可以使用pip安装Python模块:

 cd ~/ryu sudo apt-get install python-dev python-pip python-setuptools sudo pip install . 

上面的代码会自动运行位于这个目录下的setup.py,并从Python包索引中获取缺少的Python模块。 该脚本将自动安装所有相关模块。 但是,请执行以下操作以确保您稍后不会丢失任何模块:

 sudo pip install webob sudo pip install eventlet sudo pip install paramiko sudo pip install routes 

启动

启动mininet使用以下命令模拟3台主机和一台交换机:

 sudo mn --topo single,3 --mac --switch ovsk --controller remote 

你会看到一个mininet提示符。 这个提示可以用来ping主机,在它们之间发送数据包等。

打开另一个终端窗口来运行Ryu。 在这个例子中,我们将运行一个应用程序(simple_switch_13.py),它将模拟一个简单的第2层交换机,将所有接收到的数据包转发到除接收到的数据包之外的所有端口。

 cd ~/ryu PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py 

确保您在运行时位于主目录中。

你们都定了 要ping主机并分析数据包传输,请转到下一节。

3.试用Wireshark和tcpdump

在本节中,我们将使用mininet将数据包从一台主机发送到另一台主机,并使用tcpdump和Wireshark分析结果传输。

数据包传输的方式正是我们可以在软件定义的网络中控制的。 我们通过编写运行在控制器之上的不同应用程序来完成这项工作。 这些应用构成了SDN控制平面的应用层。

设置拓扑并运行控制应用程序

注意:在前面的章节中,您使用mininet创建了一个拓扑,并启动了一个Ryu应用程序来控制传输。 如果您重新启动或退出其中任何一个,我会重复这些命令来创建拓扑并在此启动Ryu应用程序:

 cd ~ sudo mn --topo single,3 --mac --switch ovsk --controller remote 

并在一个单独的终端窗口中:

 cd ~/ryu PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py 

玩包

在mininet提示符下,发出以下命令,为您创建的拓扑中的三台主机中的每台主机打开一个控制台窗口:

 mininet> xterm h1 h2 h3 

堆叠这些控制台,以便您可以同时看到它们! 然后在h2和h3的xterms中运行tcpdump,一个实用程序打印主机看到的数据包:

 tcpdump -XX -n -i h2-eth0 tcpdump -XX -n -i h3-eth0 

注意:如果您之前使用过Wireshark,就好像分别在这两台主机的eth0接口上捕获报文。

在创建拓扑时,mininet将以下IP地址分配给三台主机:

 h1: 10.0.0.1 h2: 10.0.0.2 h3: 10.0.0.3 

从主机1的外壳上ping主机2和主机3,并在每个命令后观察对其他两个控制台的影响:

 ping 10.0.0.2 ping 10.0.0.3 

尝试ping一个无法访问(不存在的主机),并看到在控制台上的影响:

 ping 10.0.0.7 

你应该已经观察到ICMP(ping)和ARP(拥有这个IP地址的)协议存在于本节中! 您也可以使用Wireshark而不是tcpdump来完成上述操作。 这是tcpdump的图形化选择。

注意:数据包被转发的方式取决于在Ryu上运行的应用程序。 你可以写一个应用程序来删除所有的数据包。 在这种情况下,你的ping不会对其他两个控制台产生影响。

4.了解基本的第2层交换机应用程序

在本节中,我们将分析在第3节中控制数据包传输的第2层交换机应用程序的简化版本的工作。

工作学习桥(或第2层交换机)

我之前提到,如果你正在阅读本指南,我假设你已经有了基本的网络协议知识(包括第二层交换机,学习桥或以太网交换机的工作),我将会总结不管下面几行。

一个“学习”网桥存储一个与其连接的主机的数据库。 主机由网卡的MAC地址标识,如下所示: ab:cd:ef:12:34:56 (十六进制)。 港口只是由他们的号码标识。 例如,具有4个端口的交换机具有端口1,2,3和4。

如果交换机在端口2上收到一个数据包,它将查看该数据包的目标MAC地址(指向哪个主机)。 然后,它会查看它的数据库,看看它是否知道该主机连接到哪个端口。 如果发现它,它只将该数据包转发到该特定的端口。 但是,如果数据库中没有条目,它会将该数据包扩散到所有端口,如果数据包是发往其的数据包,则主机可以检查它们自己。

同时,交换机查看该数据包的 MAC地址,并立即知道主机X位于端口2,它将该条目存储在该数据库中。 所以现在你知道了,如果目标主机回复源主机,交换机将不必洪泛回复数据包!

Ryu API Python代码简介

不要直接去simple_switch_13.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 class L2Switch(app_manager.RyuApp): 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)] out = ofp_parser.OFPPacketOut( datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port, actions=actions) dp.send_msg(out) 

进口

我不会深入研究进口报表。 我们将在分析使用它们的代码时分别讨论这些导入。

基本的应用程序框架

下面的代码是一个完美的Ryu应用程序。 其实你也可以执行它! 但它不会做任何事情:

  from ryu.base import app_manager class L2Switch(app_manager.RyuApp): def __init__(self, *args, **kwargs): super(L2Switch, self).__init__(*args, **kwargs) 

作为类的参数,我们传递ryu.base.app_manager.RyuApp导入(在第一行导入)。 从Ryu API手册中, app_manager类是Ryu应用程序的集中管理。 它加载Ryu应用程序,为它们提供上下文并在Ryu应用程序之间路由消息。

EventOFPPacketIn事件

一个新的方法packet_in_handler被添加到L2Switch类。 当Ryu收到一个OpenFlow的packet_in消息时,这个被调用。 当Ryu收到一个packet_in消息时,会引发一个ofp_event.EventOFPPacketIn事件。 set_ev_cls装饰器告诉Ryu何时应该调用关联的函数packet_in_handler

set_ev_cls装饰器的第一个参数指出了一个调用函数的事件。 正如你所期望的那样,每当发生一个ofp_event.EventOFPPacketIn事件时,就会调用这个函数。

第二个参数表示当您想允许Ryu处理一个事件时的切换状态。 在Ryu和交换机之间的握手完成之前,您可能想要忽略OpenFlow packet_in消息。 使用MAIN_DISPATCHER作为第二个参数意味着这个函数只有在协商完成后才被调用。 MAIN_DISPATCHER表示交换机的正常状态。 在初始化阶段,交换机处于HANDSHAKE_DISPATCHER状态!

现在让我们看看函数的主体。 我们将分解成两部分。

  msg = ev.msg dp = msg.datapath ofp = dp.ofproto ofp_parser = dp.ofproto_parser 

ev.msg是一个包含接收到的数据包的数据结构。

msg.dp是表示数据路径(交换机)的数据结构内的对象。

dp.ofprotodp.ofproto_parser是代表Ryu和交换机协商的OpenFlow协议的对象。

  actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)] out = ofp_parser.OFPPacketOut( datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port, actions=actions) dp.send_msg(out) 

OFPActionOutput类与packet_out消息一起使用来指定packet_out中发送数据包的交换机端口。 由于在这个简化的应用程序中没有转发数据库,​​所以我们把数据包OFPP_FLOOD到所有端口,所以使用常量OFPP_FLOOD

OFPPacketOut类用于构建packet_out消息。

通过使用send_msg类的send_msg方法,可以将OpenFlow消息对象发送到actions变量中定义的端口。 我再说一遍,在这种情况下,动作是建立的,目的地包括所有端口。

活动

你在上面的代码中反复看到了术语事件。 在事件驱动的编程中,程序的流程由事件控制,事件由系统接收的消息引发(例如,当(OpenFlow启用的)开关接收 Ryu的packet_in消息时,会packet_in 。 我们之前曾经讨论过,OpenFlow是一个控制器(Ryu,PC)和基础设施(或交换机)通信的协议。 packet_in 这样的 消息 正是使用OpenFlow协议看起来像两个之间的通信!

下一步

你可能想要继续建立你自己的Ryu应用程序。 学习Ryu API(或Python语言,如果你还不熟悉的话)可能是一个好的开始。 祝你好运!

你可能会发现有用的Ryu控制器是Ryuretic。 Ryuretic是一个模块化的,基于SDN的网络应用程序开发框架。 它允许网络运营商直接在OSI模型的不同层次(包括L2,L3,L4和中介层协议)使用分组报头字段。 用户只需选择匹配字段并选择提供的操作来更新OpenFlow交换机。

Ryuretic后端将所有事件作为一个pkt(一个字典对象)呈现给用户,并且通过提供感兴趣的头域(例如,pkt ['srcmac'],pkt ['dstmac'])来检索pkt的内容, pkt ['ethtype'],pkt ['inport'],pkt ['srcip']等)使用来自pkt的信息,用户可以选择匹配哪些字段以及什么动作(fwd,drop,redirect,mirror ,工艺),当发现一场比赛时。

要安装Ryuretic,只需将[files]( https://github.com/Ryuretic/RyureticLabs/tree/master/ryu/ryu/app/Ryuretic )复制到目录/ ryu / ryu / app / Ryuretic。 如果你安装了Ryu,那么你已经有了/ ryu / ryu / app目录。 你只需要创建Ryuretic目录并在那里复制文件。

Ryuretic Labs提供安装说明和一些使用Ryuretic在SDN上实施安全功能的使用案例。 它还提供了一个Mininet测试平台,用于在SDN-Hub提供的虚拟机上测试您的网络应用程序。