2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

OpenFlow(OVS) 下的“路由技术”

  • 2019-11-11
  • 本文字数:3074 字

    阅读完需:约 10 分钟

OpenFlow(OVS)下的“路由技术”

熟悉这款设备的同学,应该也快到不惑之年了吧!这应该是 Cisco 最古老的路由器了。上个世纪 80 年代至今,路由交换技术不断发展,但是在这波澜壮阔的变化之中,总有一些东西在嘈杂的机房内闪闪发光,像极了工程师的头顶,充满了智慧!



Cisco“古董”路由器


本文主要描述了一种将三层路由变成二层交换转发(以及二层转发变成三层路由)的实现方式,以应对 OVS(OpenFlow)跨网段路由复杂的问题;当然技术本身是客观的,具体应用还要看场景。


随着 SDN 技术不断“发展”,玩路由器交换机的变成了“传统网工”,搞控制器、转发器的才算是正常工作,当然任何新技术的掌握都离开对“历史”了解或者反刍;也许几年以后当有人听到一条一条的配置 ACL、配置路由表是一件很不可思议的事情,因为那时所有的配置都是控制器做好模型生成配置自动下发的,点点鼠标或者写个 py 脚本就可以了。

传统的路由交换机

OK,言归正传,我们先来了解一下传统路由、交换的区别:



交换: 一般指的是同网段内分组包的转发,转发依据:MAC 地址。


  • PC 视角:当两台主机在同一个网段,PC1 需要访问 PC2 时,PC1 首先会发送 arp 请求报文,请求 PC2 的的 MAC 地址;收到响应后,PC1 会把 PC2 的 MAC 地址封装在分组包的目的 MAC 的位置,然后将分组报文扔给交换机;PC2 也会做类似的动作。

  • 交换机视角:交换机会接收网段上的所有数据帧;利用接收数据帧中的源 MAC 地址来建立 MAC 地址表(源地址自学习),使用地址老化机制进行地址表维护。MAC 地址表中查找数据帧中的目的 MAC 地址,如果找到就将该数据帧发送到相应的端口,如果找不到,就向除入端口以外的所有的端口发送;向所有端口转发广播帧和多播帧。


路由:一般指不同网段的数据包的转发,转发依据:IP 路由。


  • PC 视角:当两台主机在不同的网段,PC1 需要访问 PC2 时,PC1 首先会在自己的路由表内查询 PC2 的 IP 地址对应的下一跳(一般默认是网关)地址,然后再去发送 ARP 报文,请求该下一跳对应的 MAC 地址;收到响应后,PC1 会把该 MAC 地址封装在数据包的目的 MAC 的位置(注意此时的目的 IP 仍是 PC2 的 IP 地址,而不是下一跳 IP),然后将数据报文扔给路由器;PC2 也会做类似的动作。

  • 路由器视角:当路由器收到一个 IP 数据包,路由器就会找出数据包的三层包头中的目的 IP 地址,然后拿着目的 IP 地址到自己的路由表中进行查询,找到“最匹配”的路由条目后,将数据包根据路由条目所指示的出接口或者下一跳 IP 转发出去,这就是 IP 路由(当然路由器还会做一些额外的工作:将数据包的三层包头的 TTL 减一,修改数据包的二层源 MAC 地址为自己出接口的 MAC,修改数据包的二层目的 MAC 地址为下一跳的 MAC);而每一台路由器都会在本地维护一个路由表(Routing Table),路由表中装在着路由器获知的路由条目,路由条目由路由前缀(路由所关联的目的地址)、路由信息的来源、出接口或者下一跳 IP 等元素构成;路由器通过静态配置或者动态的方式获取路由条目并维护自己的路由表。

OpenFlow 的出现

当 OpenFlow 出现以后,路由器、交换机统一变成了转发器,转发依据:流表。


OK,我们先看一下流表长啥样:


root@ubuntu:~# ovs-ofctl dump-flows br2NXST_FLOW reply (xid=0x4):cookie=0x0, duration=16080.313s, table=0, n_packets=1, n_bytes=42, idle_age=15691, priority=200,arp,arp_tpa=2.2.2.0/24 actions=output:100cookie=0x0, duration=15964.186s, table=0, n_packets=1, n_bytes=42, idle_age=15691, priority=100,arp,arp_tpa=1.1.1.0/24 actions=output:1cookie=0x0, duration=15985.113s, table=0, n_packets=5, n_bytes=490, idle_age=15692, priority=200,icmp,nw_dst=2.2.2.0/24 actions=output:100cookie=0x0, duration=15802.910s, table=0, n_packets=5, n_bytes=490, idle_age=15692, priority=100,icmp,nw_dst=1.1.1.0/24 actions=output:1
复制代码


当然有人称流表为 ACL,这也可以理解,都有着强大的匹配域以及 Action,流表的 Pipeline 可以算是其特色(性能暂时先不 care);到此为止,MAC 表、路由表在转发器上面已经统统看不到了,你能看到只有上面的流表。


就 OVS 来说,如果把 Bridge 配置成 Secure 模式,默认是没有什么流表的;如果现在我们把 OVS 配置成一台普通的传统二层交换机,只需要增加几条关于 ARP、ICMP 的流表,就可以 Ping 通了(可以参考以上示例),这还是比较简单的。


当然可能有些人说还有更简单的:只需把 Bridge 配置 Standalone 模式或者增加一条默认 action=NORMAL 的流表就可以了。但是如果这样的话,所有的流量又回到传统的二层三层转发去了,作为新时代的 OVS,这符合我的个性啊,如果这样的话,这活还是交给 Linux Bridge 来干吧。


但是问题来了,如果把 OVS 配置成一台有路由器功能的转发器,这就比较困难了;因为通过上文分析路由转发过程相对来说还是比较复杂的,需要做的工作如下:


  • 需要一个类似网关的设备(Device),来响应 ARP 请求:当然可以在新增 OVS 时自动生成的设备上配置网关地址,也可以增加单独的设备专门作为网关。

  • 需要修改数据包的二层源目 MAC 地址以及三层包头的 TTL:因为路由是逐跳转发的,每一跳都需要做这些工作,即使是现在通过流表转发,中间的转发器直接转发报文,到达倒数第一跳的时候还是需要把数据包的目的 MAC 地址修改为接受端的 MAC 地址。

一切皆交换的世界

在 OpenFlow 的世界所有的网络设备都是转发器或者称为交换机,执行简单的转发转发动作; OK,那我们能不能将跨网段访问的路由转发变换成普通的二层转发呢?答案是 YES!


下面我们通过一个示例来实现这个想法:首先我们要解决的第一个问题就是网关的问题:如何取消对网关的 ARP 请求?这个在 Linux 平台下并不是一件难事,只需一条命令:


root@ubuntu:~# ip route add 0.0.0.0/0 dev eth0 scope link
复制代码


(同时注意 arp_ignore 需要是 0 或 1)


Link 路由是可以直接 arp 目标地址的,而不是 arp 下一跳地址。意思就是说,目标地址是属于跟本地直连的二层链路上,不跨三层。既然是不跨三层的链路,arp 就可以畅行无阻,而标准中又没有规定 arp 协议包的请求源和请求目标必须是同一个网段的地址(甚至都没有掩码约束),所以说,一个以下的 arp 请求是有效的:



验证得到了响应:



细心的童鞋可以发现上面的命令实际上解决了我们的两个问题,网关的问题解决了,另外由于源主机直接请求目的主机的 MAC 地址,所以封装的时候也直接封装了目的主机的 MAC,省去了我们在倒数第一跳修改数据包的目的 MAC 为目的主机的工作。


最后剩下一个问题就是防环的 TTL 的问题,这个处理起来也比较简单一些,我们可以在流表中加入 actions=dec_ttl(1), output:100,在每一跳中自动减小 TTL。


然后在接收端的 PC 上面做类似的操作,中间的 OVS 添加相关 ARP 以及业务流的流表,就实现了跨网段的“交换”。

Little Tips

通过以上描述,已经实现了跨网段的路由向交换的转换,另外也可以实现所谓二层交换向路由的转换,比如 10.0.0.100/24 访问 10.0.0.200/24,按照我们的想当然是应该走二层转发的,也就是直接请求目的主机的 MAC 地址,然后封装、发送。


但是由于种种原因,目的主机 10.0.0.200/24 可能跟源主机是跨三层网络的,那现在怎么办呢?OK,可以在源主机上面增加一条明细路由把 10.0.0.200/24 指向默认网关,在目的主机上面增加一条明细路由把 10.0.0.100/24 指向默认网关,然后再 ping 一下,有木有看到自己的嘴角上扬呢!


交换机本就应该做二层转发的事情,其他的分布式出去吧!


本文转载自公众号 UCloud 技术(ID:ucloud_tech)。


原文链接:


https://mp.weixin.qq.com/s/xTmseMTJdBJ3TB93elxsHA


2019-11-11 17:371650

评论

发布
暂无评论
发现更多内容

你使用的SimpleDateFormat类还安全吗?

华为云开发者联盟

Java 安全 线程 高并发 SimpleDateFormat类

FastApi-04-请求体-1

Python研究所

FastApi 8月日更

基于 Apache APISIX,新浪微博API网关的定制化开发之路

API7.ai 技术团队

Apache 网关 APISIX 微博

区块链技术如何有效应对气候变化

CECBC

2021Java春招面试真题详解,Git-如何优雅地回退代码

策划Java工程师

Java 程序员 后端

2021Java面经:Android屏幕适配-重点盘点

策划Java工程师

Java 程序员 后端

分布式拒绝服务 (DDoS) 攻击对企业运维造成的影响分析

九河云安全

下一个颠覆的领域:区块链如何影响审计行业?(下)

CECBC

从河南暴雨、疫情反弹看区块链“灾疫”治理

CECBC

2021年Java开发实战!仿微信的网络聊天室项目开发【完整源码讲解

策划Java工程师

Java 程序员 后端

立体车库数据管理被卡脖子?织信车库管理系统全面掌控车辆新状况

优秀

低代码

gitlab无法通过ssh拉代码

阿呆

#GitLab

编译脚本:编写CMakeFile(一)

正向成长

CMakeFile

FIL分币系统源码|分销商城功能开发模式介绍

Geek_23f0c3

fil Fil算力挖矿分币系统 Filecoin分销商城

TRTC代码示例文档集合完毕!哪里不会点哪里!

腾讯云音视频

腾讯云 音视频 API sdk

android 工作资料!职场中的中年危机

欢喜学安卓

android 程序员 面试 移动开发

关于Spring注解开发教程,打包全送你

华为云开发者联盟

Java spring 容器 注解 组件

面试官:你了解JVM的锁优化吗?

百度开发者中心

Java 最佳实践 方法论 语言 & 开发

防火墙 Keepalived 异常双活恢复后部分外网访问中断问题分析

Qunar技术沙龙

运维 防火墙 网络 故障诊断 keep-alive

Python代码阅读(第2篇):数字转化成列表

Felix

Python 编程 Code Programing 阅读代码

2021Java笔试题总结!Java个人学习之旅(第十天)

策划Java工程师

Java 程序员 后端

DataPipeline荣膺CFS第十届财经峰会“2021数字化转型推动力奖”

DataPipeline数见科技

大数据 数据融合 数据管理

Linux 网络管理技术 OSI 七层模型和 TCP/IP 四层模型

学神来啦

Linux 运维 IP

迅捷录屏大师 Tech Support

凌天一击

啃书一年多的我,推荐Python初学者不要在乱看书了,有这三本就妥妥的

冇先生

2021Java大厂面试集合,java多线程

策划Java工程师

Java 程序员 后端

当企业遭遇分布式拒绝服务 (DDoS) 攻击时,第一时间该如何进行操作?

九河云安全

频繁出现的分布式拒绝服务 (DDoS) 攻击​,有什么办法可以抵御吗?

九河云安全

双非本化学跨专业,投岗阿里/滴滴后端三面,最终拿下offer

编程菌

Java 编程 程序员 面试 计算机

ironSource 在 2021 ChinaJoy 举办多场活动赋能中国开发者

Hologres揭秘:深度解析高效率分布式查询引擎

阿里云大数据AI技术

OpenFlow(OVS)下的“路由技术”_文化 & 方法_UCloud技术_InfoQ精选文章