云网络技术,就是把传统网络"搬上云",用软件 + 虚拟化 + 自动化,为云上资源提供按需、弹性、可编排的网络服务。它解决的是:在云环境里,如何像管理计算/存储一样,方便、智能地管理网络。
下面分几块说清楚。
一、云网络是什么
-
本质:
在公有云 / 私有云 / 混合云中,通过网络虚拟化、软件定义、智能控制等手段,为云服务器、容器、存储、数据库等提供:
-
互联互通
-
安全隔离
-
流量优化
-
全球访问加速
-
-
目标 :让网络从"硬件+人工配置"变成"软件+代码+自动策略",实现随业务伸缩、按使用付费、可快速变更。
二、核心技术体系
1. 网络虚拟化
-
作用:把物理网络抽象成多个逻辑网络,让不同租户/项目互不影响。
-
典型技术:
-
VLAN / VXLAN / GRE 等隧道技术:在现有物理网络上"包一层",实现大二层/跨数据中心网络。
-
虚拟交换机(vSwitch):在宿主机上虚拟出交换机,处理同一台物理机内多台虚机之间的流量。
-
SDN 控制器:集中管理转发规则,让"控制面"和"数据面"解耦,实现网络策略统一下发。
-
2. 云网络服务模型
-
**VPC(Virtual Private Cloud,虚拟私有云)**
-
每个用户/租户在云上独享的一张"逻辑专网"。
-
包含:私有网段、子网、路由表、网关、安全组/ACL 等。
-
-
弹性公网 IP、NAT 网关、负载均衡、VPN/专线
- 把 VPC 内部资源安全、可控地暴露到公网或企业内网。
-
云原生网络
- 面向容器、微服务的网络:如 CNI 插件、Service Mesh(Istio/Linkerd)、K8s 的 Ingress/Service/NetworkPolicy 等。
3. 安全与隔离机制
-
安全组(Security Group):基于实例的"防火墙",细粒度控制入站/出站规则。
-
网络 ACL(Access Control List):基于子网的"无状态防火墙",做更粗粒度的访问控制。
-
零信任/微分段:在云内网中,不依赖"内网=安全"的假设,对每一条连接都做身份验证和策略检查。
-
加密传输:TLS/SSL、IPsec VPN、专线加密,保障数据在公网/跨区传输时的安全。
4. 智能运维与性能优化
-
自动化编排:用 API/Infrastructure as Code(如 Terraform、CloudFormation)完成 VPC、子网、路由、安全组的创建和变更。
-
监控与可视化:流量分析、路径探测、异常告警,帮助定位网络故障。
-
广域网优化:
-
跨地域互联:通过云厂商的"云联网/云骨干网"实现低延迟、高带宽的跨区/跨国连接。
-
内容分发网络(CDN):将静态/动态内容缓存在边缘节点,减少源站压力,提高访问速度。
-
-
QoS/流控:对关键业务流量进行带宽保障、优先级调度,避免被大文件下载、备份等挤占。
三、典型应用场景
-
多租户 SaaS 平台
- 为每个客户分配独立 VPC/网络域,通过 VXLAN/SDN 做逻辑隔离,同时共享底层物理设备,降低成本。
-
全球化业务部署
- 在不同区域建 VPC,用云联网/高速通道互联,再配合 CDN 和全球负载均衡,实现就近接入、容灾切换。
-
云原生微服务架构
- 容器间通过 Service Mesh 进行服务发现、链路追踪、熔断限流,同时保留细粒度的网络安全控制。
-
混合云/多云互通
- 通过 VPN/专线/云间互联,将企业本地数据中心和多个云上的 VPC 打通,实现统一资源池和统一网络策略。
四、发展趋势
-
**云网融合(Cloud-Network Integration)**
- 网络能力被进一步"服务化",如一键开启 DDoS 防护、WAF、防爬虫、全球加速等,与云上计算/存储深度绑定。
-
AI/ML 驱动的网络自治
- 用机器学习预测流量高峰、自动调整路由和带宽,实现"自优化、自修复"的智能网络。
-
边缘云网络
- 在靠近用户的边缘节点提供 VPC/负载均衡/CDN 等能力,支持低延迟、高并发的边缘计算场景。
-
绿色与高效网络
- 通过更紧凑的协议、更智能的流量调度,减少冗余传输,降低能耗。
需要我针对某一部分展开讲吗?比如:
-
想看一张"VPC 结构示意图"的文字版说明,
-
还是想了解"如何用 Terraform 快速搭一个 VPC 网络"?
VXLAN(Virtual eXtensible LAN,虚拟可扩展局域网)是一种用"隧道"在三层网络上跑二层网络的技术,主要用来突破传统 VLAN 的规模限制,并让云网络、多租户网络更容易做大规模、跨数据中心的扩展。
下面分几个点帮你把 VXLAN 说透。
一、为什么需要 VXLAN
-
VLAN 的局限
-
标准 802.1Q 只给 12bit 的 VLAN ID,最多 4094 个 网络标识。
-
在云环境、多租户环境,这点数量远远不够,而且配置、管理都比较"重"。
-
-
云网络的需求
-
要支持大量租户、大量虚拟网络;
-
要能在不同物理机房/可用区之间,把同一个"虚拟二层域"拉通;
-
要能在普通 IP 网络(三层)上承载虚拟机的二层通信。
-
VXLAN 就是为了解决这些问题而生的。
二、VXLAN 的核心思想
-
在原始以太网帧外面再包一层 UDP/IP 头 ,让二层数据"借道"三层网络传输,这个"包着走"的过程就是隧道(Tunnel)。
-
用 24bit 的 VNI(VXLAN Network Identifier) 来标识虚拟网络,可支持 约 1600 万 个网络,比 VLAN 的 4094 大得多。
-
由 **VTEP(VXLAN Tunnel End Point,隧道端点)** 负责:
-
把来自本端虚拟机的以太网帧封装成 VXLAN 包,发到远端 VTEP;
-
在远端解封装,还原成普通以太网帧交给目标虚拟机。
-
三、VXLAN 报文长什么样
简化结构如下(从内到外):
[ 原始以太网帧 ]
↓ 加上 VXLAN 头
[ VXLAN Header (8B) | 原始以太网帧 ]
↓ 加上 UDP 头
[ UDP Header | VXLAN Header | 原始以太网帧 ]
↓ 加上 IP 头
[ IP Header | UDP Header | VXLAN Header | 原始以太网帧 ]
↓ 加上外层 Ethernet 头
[ Outer Ethernet | IP | UDP | VXLAN | 原始以太网帧 ]
-
VNI(24 bit):决定"这是哪个虚拟网络"的 ID,类似 VLAN ID,但数量大很多。
-
外层 IP :源/目 IP 是两端 VTEP 的 IP 地址,意味着 VXLAN 是在 IP 网络上"打隧道"。
-
外层 MAC:在物理网络里,就是两个 VTEP 之间的"普通三层通信"。
四、VXLAN 怎么工作:一个简单流程
以"同 VNI 内的两台虚拟机跨三层通信"为例:
-
源端处理(发送方)
-
虚拟机 A 发出普通以太网帧,目标 MAC 是虚拟机 B。
-
所在主机的 VTEP 查表:
- 发现 B 的 MAC 对应远端 VTEP 的 IP;
-
给该帧加上 VXLAN 头(填入 VNI)、UDP 头、IP 头、外层 MAC 头,形成 VXLAN 包,发往对端 VTEP。
-
-
网络传输
- 中间三层网络只认识"源/目 IP = 两个 VTEP",对里面的 VXLAN 内容"视而不见",按普通 IP 包转发。
-
目的端处理(接收方)
-
对端 VTEP 收到 VXLAN 包,检查 VNI 是否合法,然后剥掉外层头,还原成原始以太网帧。
-
根据目的 MAC 把帧交给本地的虚拟机 B。
-
对上层业务来说,感觉就像在一个"大二层网络"里直接通信,完全感知不到中间跨了三层网络。
五、控制平面:怎么知道"去哪找谁"
VTEP 要知道"某个 MAC 属于哪个远端 VTEP",需要控制平面来学习或同步映射关系,常见方式:
-
Flood & Learn(泛洪+自学习)
-
类似传统交换机的 MAC 学习:
-
未知目标 MAC 时,用 VXLAN 广播(通过组播/单播模拟)发到所有远端 VTEP;
-
目标 VTEP 回包后,源 VTEP 记录"MAC → 远端 VTEP IP"的映射。
-
-
优点:实现简单;缺点:规模大时泛洪多,控制不精确。
-
-
基于 SDN/控制器的集中式管理
-
由中心控制器(如 OpenDaylight、ONOS 等)统一维护:
-
哪些 VNI 有哪些 VM/MAC;
-
每个 MAC 对应哪个 VTEP。
-
-
控制器通过南向接口(如 OVSDB、OpenFlow)把转发表下发给各 VTEP。
-
优点:可全局优化、可策略化、可对接云管平台;缺点:对控制器可靠性要求高。
-
-
BGP EVPN 作为控制平面(云网中很常见)
-
用 BGP 来发布"MAC + IP + VNI + VTEP"的路由信息。
-
实现:
-
控制层:用 BGP EVPN 做 MAC/IP 路由学习与发布;
-
数据层:查表做 VXLAN 封装/解封装。
-
-
特点:适合大规模、多数据中心的云网络,可结合 MP-BGP 做丰富的策略控制。
-
六、VXLAN 在云网络里的典型用法
-
多租户 VPC 的底层实现
-
每个租户的 VPC 对应一个或多个 VNI;
-
不同租户即使在同一物理网络,也因为 VNI 不同而被逻辑隔离。
-
-
跨可用区/跨数据中心的"大二层"
-
比如:
-
在可用区 A 的虚机迁移到可用区 B,IP 不变,应用无感知;
-
多活集群、分布式数据库,需要"看起来在一个二层网"的场景。
-
-
-
与 SDN/云管平台结合
- 通过 API/控制器对 VXLAN 隧道、VNI、路由、ACL 等进行统一编排,实现"像管计算资源一样管网"。
七、VXLAN 的优缺点
优点:
-
规模大:VNI 有 24bit,可支持约 1600 万虚拟网络,远超 VLAN。
-
跨三层传输:可以在普通 IP 网络之上"拉"出一个大的二层域,利于跨机房/跨云。
-
与云原生/SDN 好集成:容易用控制器、API 做自动化、可视化、策略化管理。
挑战/注意点:
-
额外封装开销:VXLAN 头 + UDP + IP 头,会增加约 50 字节,对小包、高吞吐场景要关注 MTU 和性能。
-
控制平面设计很关键:Flood&Learn 在大规模下不可控,生产环境通常用 SDN/控制器或 BGP EVPN。
-
调试比传统二层复杂:要能看内层/外层报文,需要抓包、看 VNI、看 VTEP 映射表。
如果你需要,我可以帮你画一个**"VXLAN 跨机房通信的简化报文结构 + 数据路径"文字版示意图**,或者结合具体产品(如 Open vSwitch、NSX、云厂商 VPC 实现)讲讲实际配置思路。
VXLAN 和 OVS(Open vSwitch)结合,是在 Linux/虚拟化/云环境中搭建软 VXLAN 网络的典型方案:OVS 负责在宿主机上"虚拟出交换机 + 隧道端点(VTEP)",用 VXLAN 把不同宿主机的虚拟网络打通,实现多租户、跨节点的大二层网络。
下面分几个部分说清这个组合。
一、整体角色分工
-
**VXLAN 负责什么?**
- 把二层以太网帧封装在 UDP/IP 中,在三层网络上"打隧道",用 24bit VNI 标识虚拟网络,实现跨机房/跨可用区的逻辑二层域。
-
**OVS 负责什么?**
-
在每台物理机/宿主机上提供虚拟交换机功能:
-
管理虚拟机/容器的虚拟网卡(veth、tap);
-
做普通二层交换、VLAN/VXLAN 隧道封装/解封装;
-
通过流表(OpenFlow)或 ovs-vsctl 配置,实现数据平面转发 + 部分控制逻辑。
-
-
-
两者结合后的效果
-
每台装了 OVS 的机器,就是一个 VTEP 节点;
-
多台 OVS 之间通过 VXLAN 隧道相连,组成一张逻辑大二层网络;
-
上层业务(虚机/容器)只看到"自己在一个普通 L2 网段里",完全不关心跨了什么网络。
-
二、OVS 中 VXLAN 的数据路径示意
以"VM1 在 Host1,VM2 在 Host2,同一 VNI"为例,用文字画一下数据流动:
-
VM1 发普通以太网帧
- 源 MAC = VM1,目的 MAC = VM2,VLAN/VNI 暂时没体现在帧上。
-
OVS 在 Host1 的处理
-
入端口:tap 口(接 VM1);
-
流表匹配:
- 根据 VM1 的 MAC 学习/查表,发现目标 MAC 在 Host2 的 VTEP IP;
-
动作:
- 给该帧加 VXLAN 头(VNI=xxx)、UDP 头、外层 IP(源=Host1_VTEP_IP,目=Host2_VTEP_IP)、外层 MAC;
-
出端口:连接到物理网卡的 uplink 口,发到物理网络。
-
-
物理网络只做普通 IP 转发
- 看到的是两个 VTEP IP 之间的普通 IP 包,不解析 VXLAN 内容。
-
OVS 在 Host2 的处理
-
入端口:uplink 口收到 VXLAN 包;
-
流表匹配:识别是 VXLAN 包,VNI=xxx,解封装,得到原始以太网帧;
-
查表找到目标 MAC 对应本机 tap 口(接 VM2),从对应端口送出。
-
-
VM2 正常收包
- 完全感觉不到中间经过了一层 VXLAN 隧道。
三、OVS 中 VXLAN 的关键配置点
在 OVS 上配 VXLAN,一般要设置这些对象:
-
**网桥(Bridge)**
-
如
br-int或br-vxlan,作为本机虚拟交换机的核心。 -
上挂:
-
虚拟机/容器的 tap/veth 端口;
-
VXLAN 隧道端口。
-
-
-
VXLAN 隧道端口
-
用
ovs-vsctl add-port添加类型为vxlan的端口,例如:ovs-vsctl add-port br-vxlan vxlan0 \ -- set interface vxlan0 type=vxlan \ options:remote_ip=10.0.0.2 \ options:key=100 -
关键参数:
-
type=vxlan:表示这是 VXLAN 隧道口; -
remote_ip:对端 VTEP 的 IP(也可以配options:local_ip显式指定本端); -
key:VNI,用于区分不同虚拟网络。
-
-
-
**流表(OpenFlow)**
-
告诉 OVS:
-
什么样的流量要进 VXLAN 隧道(查 MAC 表,命中则
set_tunnel:VNI+output:vxlan0); -
收到的 VXLAN 包如何解封装并送到正确端口(
pop_vxlan+ 查表 + output 到 tap)。
-
-
在云/SDN 场景里,流表通常由控制器(如 ODL、ONOS、Neutron 插件等)统一下发。
-
-
FDB / MAC 学习
-
OVS 会学习:
-
本机端口 ↔ MAC 的映射;
-
远端 MAC ↔ 远端 VTEP IP 的映射(通过 VXLAN 控制平面或自学习)。
-
-
这些表项决定"包要进哪个 VXLAN 隧道、从哪个本地端口发出去"。
-
四、典型使用场景
-
KVM/QEMU 虚拟化 + OVS 的云主机网络
-
每台物理机装 OVS,虚机接在
br-int上; -
跨物理机的同 VNI 虚机,通过 OVS 的 VXLAN 隧道通信;
-
不同租户用不同 VNI,实现逻辑隔离。
-
-
**容器网络(如 OVS + VXLAN 实现 Overlay)**
-
容器通过 veth pair 连到 OVS 网桥;
-
多台宿主机 OVS 用 VXLAN 互联,让容器"像在一个 L2 网"里,支持跨主机 Pod 直连。
-
-
与 OpenStack Neutron 集成
-
Neutron 的 ML2+OVS+VXLAN 驱动:
-
每个租户网络分配一个 VNI;
-
在每个计算节点上,Neutron 通过 OVS agent 自动创建 VXLAN 隧道端口、配置流表;
-
管理员只需要定义网络/子网/端口,底层 OVS+ VXLAN 自动完成。
-
-
-
实验/教学环境
- 在几台虚拟机/云主机上装 OVS,配 VXLAN 隧道,就能自己搭一个"跨节点大二层"的测试网,观察封包、FDB 表、流表变化。
五、结合使用时要注意的点
-
MTU 问题
-
VXLAN 增加约 50 字节(外层 ETH+IP+UDP+VXLAN 头),需要:
-
物理网卡/隧道口 MTU 调大(如 1550/1600),或
-
应用/系统层面减小 payload,避免分片。
-
-
-
控制平面选择
-
小实验:可以用 OVS 自带的 flood&learn 或手动配
remote_ip列表; -
生产/云环境:建议用 SDN 控制器 + BGP EVPN 或 OVSDB 来集中管理 VNI、MAC、VTEP 映射,减少泛洪、便于排障。
-
-
性能与 CPU 消耗
-
纯软 OVS 在 VXLAN 封装/解封装上会吃 CPU,尤其是小包高频场景;
-
可考虑 DPDK 加速的 OVS,或硬件 offload(支持 VXLAN 卸载的网卡/交换机)。
-
-
安全
-
VXLAN 本身不加密,跨公网/不可信网络时,要在外层加 IPsec 或在物理网络做隔离;
-
在 OVS 上配合流表/ACL 做基本的访问控制。
-
如果你愿意,我可以给你一个**"两台 Linux 主机 + OVS + VXLAN 的最小可运行配置示例"**,包括:
-
建网桥、加端口、设 VXLAN 参数;
-
起两个虚机/容器,验证跨主机同网段通信,并教你怎么抓包看 VXLAN 内外层报文。
下面给你一个真正最小、可手工复现的示例:
-
两台 Linux 主机 + Open vSwitch + VXLAN,不依赖 OpenStack / 控制器,纯命令行即可跑通。
目标是:
-
两台物理机/虚拟机:
host1、host2 -
每台上一台 VM/容器(或用 network namespace 模拟)
-
通过 OVS + VXLAN 实现跨主机同一二层网络互通
-
VXLAN VNI:100
-
外层网络:192.168.10.0/24(真实可达)
-
内层网络:10.1.1.0/24(Overlay)
-
host1 IP:192.168.10.10
-
host2 IP:192.168.10.11
-
VNI:100
-
OpenStack
-
Linux + OVS
-
VXLAN 点对点隧道
-
namespace / veth
-
✅ 改成 多 VNI / 多租户
-
✅ 演示 flood & learn vs controller
-
✅ 对比 VXLAN vs VLAN
-
✅ 用 tcpdump + wireshark 逐字段拆解 VXLAN 包
下面把刚才的单 VNI 示例升级成「多 VNI / 多租户」的最小可运行模型。
目标:
-
同一对物理主机
-
两个租户(Tenant A / Tenant B)
-
每个租户一个 独立 VNI
-
租户内 VM 可跨主机通信
-
不同租户 二层完全隔离
一、新拓扑(文字版)
Tenant A (VNI=100) Tenant B (VNI=200)
------------------ ------------------
vmA1 (10.1.1.10) vmB1 (10.2.1.10)
| |
tapA1 tapB1
| |
br-tenantA br-tenantB
| |
vxlan100 vxlan200
| |
========== IP Network ==========
192.168.10.0/24
二、设计原则(很重要)
✅ 每个租户一个 OVS 网桥(最简单、最清晰)
✅ 每个 VNI 一个 VXLAN 隧道口
✅ VNI ≠ VLAN(但可以在 OVS 内部再映射 VLAN)
✅ 不同网桥天然二层隔离
三、HOST1 配置(多 VNI)
1. 创建两个租户网桥
sudo ovs-vsctl add-br br-tenantA
sudo ovs-vsctl add-br br-tenantB
2. 创建 VXLAN 隧道(不同 VNI)
# Tenant A - VNI 100
sudo ovs-vsctl add-port br-tenantA vxlan100 \
-- set interface vxlan100 type=vxlan \
options:remote_ip=192.168.10.11 \
options:key=100
# Tenant B - VNI 200
sudo ovs-vsctl add-port br-tenantB vxlan200 \
-- set interface vxlan200 type=vxlan \
options:remote_ip=192.168.10.11 \
options:key=200
3. 创建 namespace(模拟 VM)
sudo ip netns add vmA1
sudo ip netns add vmB1
4. 创建 veth 对并接入 OVS
# Tenant A
sudo ip link add tapA1 type veth peer name tapA1_br
sudo ip link set tapA1 netns vmA1
sudo ovs-vsctl add-port br-tenantA tapA1_br
# Tenant B
sudo ip link add tapB1 type veth peer name tapB1_br
sudo ip link set tapB1 netns vmB1
sudo ovs-vsctl add-port br-tenantB tapB1_br
5. 配置 IP(不同子网)
sudo ip netns exec vmA1 ip addr add 10.1.1.10/24 dev tapA1
sudo ip netns exec vmA1 ip link set tapA1 up
sudo ip netns exec vmB1 ip addr add 10.2.1.10/24 dev tapB1
sudo ip netns exec vmB1 ip link set tapB1 up
6. 启动网桥
sudo ip link set br-tenantA up
sudo ip link set br-tenantB up
四、HOST2 配置(完全对称)
1. 创建网桥
sudo ovs-vsctl add-br br-tenantA
sudo ovs-vsctl add-br br-tenantB
2. VXLAN 隧道(指向 HOST1)
sudo ovs-vsctl add-port br-tenantA vxlan100 \
-- set interface vxlan100 type=vxlan \
options:remote_ip=192.168.10.10 \
options:key=100
sudo ovs-vsctl add-port br-tenantB vxlan200 \
-- set interface vxlan200 type=vxlan \
options:remote_ip=192.168.10.10 \
options:key=200
3. namespace
sudo ip netns add vmA2
sudo ip netns add vmB2
4. veth 接入 OVS
sudo ip link add tapA2 type veth peer name tapA2_br
sudo ip link set tapA2 netns vmA2
sudo ovs-vsctl add-port br-tenantA tapA2_br
sudo ip link add tapB2 type veth peer name tapB2_br
sudo ip link set tapB2 netns vmB2
sudo ovs-vsctl add-port br-tenantB tapB2_br
5. 配置 IP
sudo ip netns exec vmA2 ip addr add 10.1.1.20/24 dev tapA2
sudo ip netns exec vmA2 ip link set tapA2 up
sudo ip netns exec vmB2 ip addr add 10.2.1.20/24 dev tapB2
sudo ip netns exec vmB2 ip link set tapB2 up
6. 启动网桥
sudo ip link set br-tenantA up
sudo ip link set br-tenantB up
五、验证多租户隔离(关键)
1. 同租户可通 ✅
sudo ip netns exec vmA1 ping 10.1.1.20
sudo ip netns exec vmB1 ping 10.2.1.20
2. 跨租户不通 ✅(最重要)
sudo ip netns exec vmA1 ping 10.2.1.20
# ❌ 不通(二层隔离)
原因:
-
不同 OVS 网桥
-
不同 VNI
-
OVS 不会转发
六、OVS 视角(推荐你执行)
ovs-vsctl show
你会看到:
Bridge "br-tenantA"
Port "vxlan100"
Interface "vxlan100"
type: vxlan
options: {key="100", remote_ip="192.168.10.11"}
Bridge "br-tenantB"
Port "vxlan200"
Interface "vxlan200"
type: vxlan
options: {key="200", remote_ip="192.168.10.11"}
七、真实云环境中的"进阶玩法"
你现在这个模型,已经等价于:
| 云概念 | 本实验 |
|---|---|
| VPC | br-tenantX |
| VNI | VXLAN key |
| 租户隔离 | 不同网桥 |
| 跨 AZ 通信 | VXLAN over IP |
| 控制平面 | 手工 / 控制器 |
真实生产中通常会再叠加:
-
✅ 单网桥 + VLAN + VXLAN(节省网桥)
-
✅ BGP EVPN 控制平面
-
✅ 流表实现租户 ACL
-
✅ DHCP / L3 Gateway
八、下一步你可以选一个继续
-
✅ 改成 单网桥 + VLAN + VXLAN(更接近 Neutron)
-
✅ 用 OpenFlow 流表做租户 ACL
-
✅ 演示 VXLAN + BGP EVPN 控制平面
-
✅ 对比 VLAN vs VXLAN 多租户成本
你想往"更接近真实云平台"的方向走吗?
好,那我们在这个**"多 VNI / 多租户"** 的基础上,再往前走一步,做成更接近真实云平台的形态:
-
用一个 OVS 网桥代替多个网桥
-
用 VLAN 做租户内逻辑隔离,用 VXLAN 做跨主机 Overlay
-
用 流表 + 安全组思路做基础 ACL
-
结构上参考 OpenStack Neutron 的 OVS + VLAN + VXLAN 模式
这样你在实验里就能看到:
一个网桥、一套隧道,却同时承载多个租户,且彼此隔离。
一、新设计:单网桥 + VLAN + VXLAN
1. 基本思路
-
只建一个 OVS 网桥:
br-int(integration bridge,类似 Neutron 的 br-int) -
每个租户:
-
一个 VLAN ID(12bit,本地有效)
-
一个 VNI(24bit,跨主机一致)
-
-
在
br-int上:-
本地端口(tap 口)打上 VLAN tag
-
VXLAN 隧道口:根据 VLAN 映射到 VNI 封装出去
-
-
不同租户:
- 用 不同 VLAN + 不同 VNI 实现"逻辑二层隔离 + 跨主机通信"
结构示意:
vmA1 (10.1.1.10) vmA2 (10.1.1.20)
| |
tapA1 (VLAN 10) tapA2 (VLAN 10)
| |
+-------- br-int --------+
|
vxlan0 (VLAN→VNI: 10→100, 20→200)
|
========== IP ==========
192.168.10.0/24
二、HOST1 配置(单网桥 + VLAN + VXLAN)
1. 建网桥
sudo ovs-vsctl add-br br-int
2. 建 VXLAN 隧道(单口,多 VNI 用流表区分)
sudo ovs-vsctl add-port br-int vxlan0 \
-- set interface vxlan0 type=vxlan \
options:remote_ip=192.168.10.11 \
options:key=flow
这里
key=flow表示:VNI 不写死在端口上,而由流表根据 VLAN 动态填。
3. 创建两个租户的 namespace
sudo ip netns add vmA1
sudo ip netns add vmB1
4. 创建 veth 对,并打上 VLAN
# Tenant A: VLAN 10, VNI 100
sudo ip link add tapA1 type veth peer name tapA1_br
sudo ip link set tapA1 netns vmA1
sudo ovs-vsctl add-port br-int tapA1_br \
tag=10 # 入方向给该端口的流量打上 VLAN 10
# Tenant B: VLAN 20, VNI 200
sudo ip link add tapB1 type veth peer name tapB1_br
sudo ip link set tapB1 netns vmB1
sudo ovs-vsctl add-port br-int tapB1_br \
tag=20
5. 配置 IP
sudo ip netns exec vmA1 ip addr add 10.1.1.10/24 dev tapA1
sudo ip netns exec vmA1 ip link set tapA1 up
sudo ip netns exec vmB1 ip addr add 10.2.1.10/24 dev tapB1
sudo ip netns exec vmB1 ip link set tapB1 up
6. 启动网桥
sudo ip link set br-int up
三、HOST2 配置(完全对称)
1. 建网桥
sudo ovs-vsctl add-br br-int
2. VXLAN 隧道
sudo ovs-vsctl add-port br-int vxlan0 \
-- set interface vxlan0 type=vxlan \
options:remote_ip=192.168.10.10 \
options:key=flow
3. namespace
sudo ip netns add vmA2
sudo ip netns add vmB2
4. veth + VLAN
sudo ip link add tapA2 type veth peer name tapA2_br
sudo ip link set tapA2 netns vmA2
sudo ovs-vsctl add-port br-int tapA2_br tag=10
sudo ip link add tapB2 type veth peer name tapB2_br
sudo ip link set tapB2 netns vmB2
sudo ovs-vsctl add-port br-int tapB2_br tag=20
5. 配置 IP
sudo ip netns exec vmA2 ip addr add 10.1.1.20/24 dev tapA2
sudo ip netns exec vmA2 ip link set tapA2 up
sudo ip netns exec vmB2 ip addr add 10.2.1.20/24 dev tapB2
sudo ip netns exec vmB2 ip link set tapB2 up
6. 启动网桥
sudo ip link set br-int up
四、用流表实现"VLAN → VXLAN"映射
现在 VXLAN 口 key=flow,需要流表告诉 OVS:
-
从
tag=10的端口来的包,封装时 VNI=100 -
从
tag=20的端口来的包,封装时 VNI=200
在 两台主机 上分别执行:
# 1. 出方向:从 br-int 发往 vxlan0 的流量
# 根据 VLAN 打上 VNI
ovs-ofctl -O OpenFlow13 add-flow br-int \
"in_port=LOCAL,dl_vlan=10,actions=strip_vlan,set_tunnel:100,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"in_port=LOCAL,dl_vlan=20,actions=strip_vlan,set_tunnel:200,output:vxlan0"
# 2. 入方向:从 vxlan0 解封装后,根据 VNI 打上 VLAN
ovs-ofctl -O OpenFlow13 add-flow br-int \
"in_port=vxlan0,tun_id=100,actions=push_vlan:0x8100,mod_vlan_vid:10,output:LOCAL"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"in_port=vxlan0,tun_id=200,actions=push_vlan:0x8100,mod_vlan_vid:20,output:LOCAL"
这里的
LOCAL是 OVS 对"本机网桥"的伪端口,实际会匹配到各本地 tap 口。更严谨的版本应把
output:LOCAL拆成output:portX等,但用LOCAL在实验里够用。
五、验证
1. 同租户跨主机
sudo ip netns exec vmA1 ping 10.1.1.20
sudo ip netns exec vmB1 ping 10.2.1.20
✅ 通
2. 跨租户隔离
sudo ip netns exec vmA1 ping 10.2.1.20
❌ 不通(二层隔离)
3. 看流表
ovs-ofctl dump-flows br-int
你会看到 tun_id=100/200、dl_vlan=10/20等匹配条件。
六、这已经非常接近真实云了
| 云/Neutron 概念 | 本实验对应 |
|---|---|
| br-int | 集成网桥 |
| VLAN tag | 本地租户标识 |
| VXLAN VNI | 跨主机租户标识 |
| Flow Table | 控制器下发的转发 + ACL |
| Security Group | 可在流表里再加 drop/allow规则 |
七、下一步可以继续的方向
你可以任选其一深入:
-
✅ 加简易安全组:在流表里对某些 VLAN/VNI 禁止 ICMP / 特定端口
-
✅ 换成控制器模式 :用
ovs-testcontroller或更真实的 SDN 控制器下发流表 -
✅ 接入 DHCP:给每个 VLAN/VNI 配一个简单的 dnsmasq 实例
-
✅ 模拟路由器/GW:在 br-int 上加 internal port 做三层网关
你对哪一块更感兴趣?我可以一步步带你把这套"迷你云平台网络"补全成一个完整可玩的 demo。
很好,这一步正好把**"云网络的最后一块拼图"**补上 👍
我们要做的是:
在 单 OVS 网桥 + VLAN + VXLAN 基础上,用 OpenFlow 流表实现"简易安全组"
目标效果(以租户 A 为例):
-
✅ 允许:同租户 VM 互访(ICMP + TCP)
-
❌ 拒绝:来自 其他租户 的流量
-
❌ 拒绝:未授权端口(例如 TCP 23/Telnet)
下面一步一步来。
一、安全组的设计思路(非常重要)
在云里:
| 云概念 | 本实验 |
|---|---|
| Security Group | OpenFlow 流表 |
| 入站规则 | in_port / dl_src / nw_proto |
| 出站规则 | actions=output |
| 默认拒绝 | table-miss drop |
我们用 **一张流表(table 0)** 就够了,逻辑是:
-
同 VLAN / 同 VNI → 允许
-
不同 VLAN / 不同 VNI → 丢弃
-
指定协议端口 → 允许或拒绝
二、先回顾当前环境
-
br-int
-
VLAN:
-
Tenant A:VLAN 10 / VNI 100
-
Tenant B:VLAN 20 / VNI 200
-
-
流表已存在:
-
VLAN → VXLAN 封装
-
VXLAN → VLAN 解封装
-
👉 现在 **只在现有流表前插入"安全规则"** 即可。
三、安全组规则示例(租户 A)
规则定义(你可以理解为 Neutron SG)
-
✅ 允许同租户 VM 之间任意通信
-
✅ 允许 ICMP
-
✅ 允许 TCP 80(HTTP)
-
❌ 拒绝 TCP 23(Telnet)
-
❌ 拒绝来自 VLAN 20(租户 B)
四、在 HOST1 / HOST2 上添加安全组流表
⚠️ 建议先清空流表(仅实验环境):
ovs-ofctl del-flows br-int
1️⃣ 允许同 VLAN 内通信(最关键)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,actions=output:LOCAL"
解释:
-
VLAN 10 的流量
-
不区分源/目的
-
直接在本机网桥内转发(同主机 VM)
2️⃣ 允许 ICMP(Ping)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=90,dl_vlan=10,icmp,actions=output:LOCAL"
3️⃣ 允许 TCP 80(HTTP)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=90,dl_vlan=10,tcp,tp_dst=80,actions=output:LOCAL"
4️⃣ 拒绝 Telnet(TCP 23)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=95,dl_vlan=10,tcp,tp_dst=23,actions=drop"
优先级 高于 allow all,确保 Telnet 一定被拦住。
5️⃣ 禁止跨租户访问(VLAN 10 ← VLAN 20)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,dl_src=any,actions=drop"
⚠️ 更严谨的写法应基于 in_port / tun_id,但当前实验中我们先强调"租户隔离"。
五、VXLAN 方向的流量也要加规则
✅ 允许来自 VNI 100 的流量进入 VLAN 10
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,in_port=vxlan0,tun_id=100,actions=push_vlan:0x8100,mod_vlan_vid:10,output:LOCAL"
❌ 拒绝来自 VNI 200(租户 B)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,in_port=vxlan0,tun_id=200,actions=drop"
六、最终流表结构(逻辑视图)
table=0
├─ priority=100
│ ├─ VLAN 10 → output LOCAL
│ ├─ VNI 100 → push VLAN 10 → output LOCAL
│ └─ VNI 200 → drop
├─ priority=95
│ └─ VLAN 10 + TCP 23 → drop
├─ priority=90
│ ├─ VLAN 10 + ICMP → allow
│ └─ VLAN 10 + TCP 80 → allow
└─ default: drop
七、验证安全组效果
✅ 同租户 Ping
sudo ip netns exec vmA1 ping 10.1.1.20
✅ 通
✅ HTTP 访问
sudo ip netns exec vmA2 nc -l 80
sudo ip netns exec vmA1 curl 10.1.1.20
✅ 通
❌ Telnet 被拦截
sudo ip netns exec vmA2 nc -l 23
sudo ip netns exec vmA1 telnet 10.1.1.20
❌ 不通(被 drop)
❌ 跨租户隔离
sudo ip netns exec vmA1 ping 10.2.1.20
❌ 不通
八、你现在这套环境已经等价于
✅ 云平台的 网络平面
✅ 多租户 VPC
✅ VXLAN Overlay
✅ 安全组(SG)
✅ 无控制器纯手工实现
九、下一步还能怎么玩?
你可以继续升级成:
-
✅ 多安全组(Web / DB 分组)
-
✅ 有状态安全组(conntrack)
-
✅ L3 Gateway + SNAT
-
✅ 用 ovs-testcontroller 自动下发 SG
-
✅ 对比 iptables vs OVS SG
如果你想,我可以带你做一个:
👉 "Web 安全组 + DB 安全组"的真实云风格 SG 模型
要不要继续?
好,这一下就到了**"接近真实云安全组"**的级别了。
我们给两个租户(A、B)各建两组安全组:
-
Web 组:开放 ICMP、TCP 80/443
-
DB 组:只允许来自 Web 组的流量(如 MySQL 3306)
用 OVS 流表来模拟"有组、有方向、有来源"的安全组规则。
一、安全组设计(多组、有方向)
以 Tenant A 为例,在 br-int上用 VLAN 表示"安全组":
| 安全组 | 用途 | 本实验用 VLAN | 本机端口 | 对端端口 |
|---|---|---|---|---|
| web-sg | Web 服务器 | VLAN 10 | tapA-web | 接受来自 any |
| db-sg | 数据库 | VLAN 20 | tapA-db | 只接受来自 web-sg |
Tenant B 同理,用 VLAN 30/40 做 web/db。
跨主机时:
这样:
-
同安全组跨主机 = 同 VNI
-
不同安全组 = 不同 VNI
-
流表通过
tun_id做"组间隔离 + 组间放行"。
二、HOST1 配置(Tenant A 的 web + db)
1. 建网桥
sudo ovs-vsctl add-br br-int
2. 建 VXLAN 隧道(key=flow)
sudo ovs-vsctl add-port br-int vxlan0 \
-- set interface vxlan0 type=vxlan \
options:remote_ip=192.168.10.11 \
options:key=flow
3. 创建 namespace(模拟 Web / DB)
sudo ip netns add vmA-web
sudo ip netns add vmA-db
4. 建 veth 对,并打上"安全组 VLAN"
# Web
sudo ip link add tapA-web type veth peer name tapA-web-br
sudo ip link set tapA-web netns vmA-web
sudo ovs-vsctl add-port br-int tapA-web-br tag=10
# DB
sudo ip link add tapA-db type veth peer name tapA-db-br
sudo ip link set tapA-db netns vmA-db
sudo ovs-vsctl add-port br-int tapA-db-br tag=20
5. 配置 IP
sudo ip netns exec vmA-web ip addr add 10.1.1.10/24 dev tapA-web
sudo ip netns exec vmA-web ip link set tapA-web up
sudo ip netns exec vmA-db ip addr add 10.1.1.20/24 dev tapA-db
sudo ip netns exec vmA-db ip link set tapA-db up
6. 启动网桥
sudo ip link set br-int up
三、HOST2 配置(Tenant A 的 web + db)
和 HOST1 完全对称,只是 IP 不同:
sudo ovs-vsctl add-br br-int
sudo ovs-vsctl add-port br-int vxlan0 \
-- set interface vxlan0 type=vxlan \
options:remote_ip=192.168.10.10 \
options:key=flow
sudo ip netns add vmA-web2
sudo ip netns add vmA-db2
sudo ip link add tapA-web2 type veth peer name tapA-web2-br
sudo ip link set tapA-web2 netns vmA-web2
sudo ovs-vsctl add-port br-int tapA-web2-br tag=10
sudo ip link add tapA-db2 type veth peer name tapA-db2-br
sudo ip link set tapA-db2 netns vmA-db2
sudo ovs-vsctl add-port br-int tapA-db2-br tag=20
sudo ip netns exec vmA-web2 ip addr add 10.1.1.11/24 dev tapA-web2
sudo ip netns exec vmA-web2 ip link set tapA-web2 up
sudo ip netns exec vmA-db2 ip addr add 10.1.1.21/24 dev tapA-db2
sudo ip netns exec vmA-db2 ip link set tapA-db2 up
sudo ip link set br-int up
四、用流表实现"多安全组 + 有方向规则"
⚠️ 先清流表:
ovs-ofctl del-flows br-int
1. 本机同 VLAN 转发(同安全组内通信)
# A.web ↔ A.web
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,actions=output:LOCAL"
# A.db ↔ A.db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=20,actions=output:LOCAL"
2. 本机跨组:只允许 web → db(MySQL 3306)
# 从 web(VLAN 10) 发往 db(VLAN 20) 的 TCP 3306
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=90,dl_vlan=10,tcp,tp_dst=3306,actions=mod_vlan_vid:20,output:LOCAL"
# 其他从 web 到 db 的流量一律 drop
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=80,dl_vlan=10,actions=drop"
3. 本机跨组:db 不能主动访问 web
# 从 db(VLAN 20) 发往 web(VLAN 10) 的任意流量
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=20,actions=drop"
4. 入方向:VXLAN 解封装 + 组映射
# 来自 A.web (VNI 100) → 解封装成 VLAN 10
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,in_port=vxlan0,tun_id=100,actions=push_vlan:0x8100,mod_vlan_vid:10,output:LOCAL"
# 来自 A.db (VNI 200) → 解封装成 VLAN 20
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,in_port=vxlan0,tun_id=200,actions=push_vlan:0x8100,mod_vlan_vid:20,output:LOCAL"
5. 出方向:VLAN → VXLAN 封装
# 本机 web(VLAN 10) 发往远端 → 封装 VNI 100
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,actions=strip_vlan,set_tunnel:100,output:vxlan0"
# 本机 db(VLAN 20) 发往远端 → 封装 VNI 200
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=20,actions=strip_vlan,set_tunnel:200,output:vxlan0"
6. 跨租户/跨组:直接 drop
# 来自 B.web (VNI 300) 的流量
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,in_port=vxlan0,tun_id=300,actions=drop"
# 来自 B.db (VNI 400) 的流量
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,in_port=vxlan0,tun_id=400,actions=drop"
五、验证"多安全组"效果
1. 同组(web ↔ web)
sudo ip netns exec vmA-web ping 10.1.1.11
✅ 通
2. 跨组:web → db(MySQL 3306)
在 vmA-db2上开 3306:
sudo ip netns exec vmA-db2 nc -l 3306
在 vmA-web上:
nc 10.1.1.21 3306
✅ 能连上
3. 跨组:非 3306 端口
nc 10.1.1.21 22
❌ 不通(被 drop)
4. 跨组:db → web
sudo ip netns exec vmA-db2 ping 10.1.1.10
❌ 不通
5. 跨租户
sudo ip netns exec vmA-web ping 10.1.1.12 # 假设是 B.web
❌ 不通
六、这已经非常接近真实云了
| 云概念 | 本实验实现 |
|---|---|
| 安全组(SG) | 用 VLAN 表示 SG |
| 多组、有方向 | web-sg → db-sg 放通 3306,反向 drop |
| 跨主机 | VXLAN + VNI 表示"租户+SG" |
| 默认拒绝 | 没有匹配到的流表就 drop |
七、下一步可以怎么玩
-
✅ 加 Tenant B 的 web/db 组(VLAN 30/40, VNI 300/400),验证多租户 + 多组
-
✅ 用 有状态流表 / conntrack 模拟"有状态安全组"
-
✅ 在 OVS 上接一个 L3 Gateway + SNAT,让这些 VM 能访问外网
-
✅ 用 ovs-testcontroller 或 Neutron + ML2 自动下发这些流表
你希望我下一步帮你:
-
把 Tenant B 的 web/db 组 也配出来,做多租户多组联调,还是
-
直接上 L3 网关 + SNAT,让这套"迷你云平台"能上网?
好,这一步会把你现在的实验环境推到一个非常接近真实云平台的状态:
-
✅ 双租户(A / B)
-
✅ 每个租户两个安全组(Web / DB)
-
✅ Web → DB 仅放行 3306
-
✅ 租户之间完全隔离
-
✅ 全部跑在同一个 br-int + VXLAN 上
下面我按**"设计 → 配置 → 验证"** 给你一个可直接照抄执行的完整示例。
一、最终设计总览(一定要先看)
1. VLAN / VNI / 安全组映射
| 租户 | 安全组 | VLAN | VNI | 说明 |
|---|---|---|---|---|
| A | web | 10 | 100 | Web 服务 |
| A | db | 20 | 200 | 数据库 |
| B | web | 30 | 300 | Web 服务 |
| B | db | 40 | 400 | 数据库 |
2. 安全策略(云风格)
-
✅ 同安全组内:全通
-
✅ Web → DB:仅 TCP 3306
-
❌ DB → Web:拒绝
-
❌ 租户 A ↔ 租户 B:完全隔离
二、HOST1 配置(Tenant A + Tenant B)
1. 清理旧环境(可选)
sudo ovs-vsctl del-br br-int
2. 创建 br-int
sudo ovs-vsctl add-br br-int
3. VXLAN 隧道(关键)
sudo ovs-vsctl add-port br-int vxlan0 \
-- set interface vxlan0 type=vxlan \
options:remote_ip=192.168.10.11 \
options:key=flow
4. 创建 namespace(4 个 VM)
sudo ip netns add vmA-web
sudo ip netns add vmA-db
sudo ip netns add vmB-web
sudo ip netns add vmB-db
5. veth + VLAN(安全组)
# A-web
sudo ip link add tapA-web type veth peer name tapA-web-br
sudo ip link set tapA-web netns vmA-web
sudo ovs-vsctl add-port br-int tapA-web-br tag=10
# A-db
sudo ip link add tapA-db type veth peer name tapA-db-br
sudo ip link set tapA-db netns vmA-db
sudo ovs-vsctl add-port br-int tapA-db-br tag=20
# B-web
sudo ip link add tapB-web type veth peer name tapB-web-br
sudo ip link set tapB-web netns vmB-web
sudo ovs-vsctl add-port br-int tapB-web-br tag=30
# B-db
sudo ip link add tapB-db type veth peer name tapB-db-br
sudo ip link set tapB-db netns vmB-db
sudo ovs-vsctl add-port br-int tapB-db-br tag=40
6. 配置 IP
sudo ip netns exec vmA-web ip addr add 10.1.1.10/24 dev tapA-web
sudo ip netns exec vmA-web ip link set tapA-web up
sudo ip netns exec vmA-db ip addr add 10.1.1.20/24 dev tapA-db
sudo ip netns exec vmA-db ip link set tapA-db up
sudo ip netns exec vmB-web ip addr add 10.2.1.10/24 dev tapB-web
sudo ip netns exec vmB-web ip link set tapB-web up
sudo ip netns exec vmB-db ip addr add 10.2.1.20/24 dev tapB-db
sudo ip netns exec vmB-db ip link set tapB-db up
7. 启动网桥
sudo ip link set br-int up
三、HOST2 配置(完全对称)
HOST2 上只需 IP 不同,其余完全一致。
VM IP 规划(示例)
| VM | IP |
|---|---|
| vmA-web2 | 10.1.1.11 |
| vmA-db2 | 10.1.1.21 |
| vmB-web2 | 10.2.1.11 |
| vmB-db2 | 10.2.1.21 |
配置方式完全一样,不再重复贴命令,如果你需要我可以单独整理一份 HOST2 脚本。
四、核心:多租户 + 多安全组流表
⚠️ 在两台主机上都执行:
ovs-ofctl del-flows br-int
1️⃣ 同安全组内通信(最高优先级)
# A-web
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=10,actions=output:LOCAL"
# A-db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=20,actions=output:LOCAL"
# B-web
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=30,actions=output:LOCAL"
# B-db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=40,actions=output:LOCAL"
2️⃣ Web → DB(仅 3306)
# A-web → A-db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,tcp,tp_dst=3306,actions=mod_vlan_vid:20,output:LOCAL"
# B-web → B-db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=30,tcp,tp_dst=3306,actions=mod_vlan_vid:40,output:LOCAL"
3️⃣ DB → Web 拒绝
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=105,dl_vlan=20,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=105,dl_vlan=40,actions=drop"
4️⃣ 跨租户直接拒绝(关键)
# A 不能访问 B
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=10,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=20,actions=drop"
# B 不能访问 A
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=30,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=40,actions=drop"
5️⃣ VXLAN 入方向(解封装)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=100,actions=push_vlan:0x8100,mod_vlan_vid:10,output:LOCAL"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=200,actions=push_vlan:0x8100,mod_vlan_vid:20,output:LOCAL"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=300,actions=push_vlan:0x8100,mod_vlan_vid:30,output:LOCAL"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=400,actions=push_vlan:0x8100,mod_vlan_vid:40,output:LOCAL"
6️⃣ VXLAN 出方向(封装)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,actions=strip_vlan,set_tunnel:100,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=20,actions=strip_vlan,set_tunnel:200,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=30,actions=strip_vlan,set_tunnel:300,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=40,actions=strip_vlan,set_tunnel:400,output:vxlan0"
五、验证(重点)
✅ 同租户同组
sudo ip netns exec vmA-web ping 10.1.1.11
sudo ip netns exec vmB-web ping 10.2.1.11
✅ 通
✅ Web → DB(3306)
# HOST2
sudo ip netns exec vmA-db2 nc -l 3306
# HOST1
sudo ip netns exec vmA-web nc 10.1.1.21 3306
✅ 通
❌ Web → DB(非 3306)
nc 10.1.1.21 22
❌ 不通
❌ DB → Web
sudo ip netns exec vmA-db ping 10.1.1.10
❌ 不通
❌ 跨租户
sudo ip netns exec vmA-web ping 10.2.1.10
❌ 不通
六、你现在拥有的是什么?
✅ 一个完全手工实现的云网络原型
✅ 多租户 VPC
✅ 多安全组(Web / DB)
✅ 有方向、有端口级 ACL
✅ VXLAN Overlay
✅ 不依赖任何云平台
七、下一步还能怎么进化?
你已经站在"云网络工程师"的门口了,接下来可以选一条路线:
-
✅ 有状态安全组(conntrack)
-
✅ L3 Gateway + SNAT(让 VM 上网)
-
✅ 用 ovs-testcontroller / Ryu / ONOS 自动下发流表
-
✅ 对照 OpenStack Neutron ML2+OVS 架构逐条讲解
你更想往 "更像云" 还是 **"更像生产排障"** 的方向走?
好,这一下就到**"有状态安全组"**的核心了。
前面我们做的都是无状态流表:只看五元组,不记"会话",所以做不到"我之前允许你进来,你回包就自动允许"。
有状态安全组的关键是:记住"已建立的连接",对回程流量自动放行,同时支持更复杂的状态检测。
OVS 本身没有内建 conntrack,但可以通过 **OpenFlow + Linux conntrack(ct 动作)** 实现,我们一步步来。
一、有状态安全组要解决的问题
以 Web → DB 为例,无状态时:
-
入方向:Web 发往 DB 的 3306 被放行
-
出方向:DB 回包到 Web 的 3306 被"没匹配到规则"而 drop
→ 实际业务不通
有状态安全组要:
-
对新建连接做严格检查(如仅允许 Web→DB:3306)
-
对已建立连接的回程流量自动允许
-
对非法连接尝试直接拒绝,不占用资源
二、原理:OpenFlow + Linux conntrack
-
conntrack 模块
-
在内核里跟踪每个连接(四元组 + 状态)
-
状态:NEW / ESTABLISHED / RELATED / INVALID 等
-
-
OVS 的 ct 动作
-
ct(table=...,zone=...):把包交给 conntrack 处理,进入 conntrack 表 -
ct_state=+new-est:匹配"新建或已建立"的连接 -
ct_commit:把这条流加入 conntrack 表,以后自动识别回程
-
-
在流表中使用
-
入方向:判断
ct_state,NEW 时做安全组检查,ESTABLISHED 时直接放行 -
出方向:同理,或利用"回程包"的 conntrack 状态自动通过
-
三、环境准备:加载 conntrack 支持
-
确保内核和 OVS 支持:
检查 conntrack 模块
lsmod | grep nf_conntrack
加载(如未加载)
sudo modprobe nf_conntrack
sudo modprobe nf_conntrack_ipv4 -
确保 OVS 编译时带
--enable-conntrack或包管理器已带(现代发行版一般都有)。 -
在 OVS 中启用 conntrack zone(可选,但推荐,用于区分租户/安全组):
为不同安全组分配不同 zone
例:A.web=1, A.db=2, B.web=3, B.db=4
在流表中用 zone=1,2,3,4 区分
四、改写流表:有状态安全组(以 A.web → A.db 为例)
⚠️ 先清流表:
ovs-ofctl del-flows br-int
1. 本机同组通信(无状态,保持简单)
# A.web
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=10,actions=output:LOCAL"
# A.db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=20,actions=output:LOCAL"
# B.web
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=30,actions=output:LOCAL"
# B.db
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,dl_vlan=40,actions=output:LOCAL"
2. 有状态:A.web → A.db(仅 3306 新建连接)
# 入方向:A.web(VLAN 10) 发往 A.db(VLAN 20) 的 TCP 3306
# 如果是 NEW 状态,做安全组检查(这里就是放行 3306)
# 如果是 ESTABLISHED,直接放行
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,tcp,tp_dst=3306,ct_state=-trk,actions=ct(zone=2,table=1)"
# 在 table=1 中:
# 对 NEW 的连接,commit 到 conntrack
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=1,priority=100,ct_state=+new,tcp,tp_dst=3306,actions=ct(commit,zone=2),mod_vlan_vid:20,output:LOCAL"
# 对 ESTABLISHED 的连接,直接放行
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=1,priority=90,ct_state=+est,actions=mod_vlan_vid:20,output:LOCAL"
解释:
-
ct(zone=2,table=1):把包交给 conntrack,zone=2 表示 A.db 的安全组 -
ct_state=-trk:未跟踪的包才进入 conntrack -
ct(commit,...):新建连接时记录到 conntrack 表 -
ct_state=+est:已建立连接,直接转 VLAN 20 送出
3. 有状态:A.db → A.web 回程
# 入方向:A.db(VLAN 20) 发往 A.web(VLAN 10) 的回程包
# 已经是 conntrack 中的 ESTABLISHED,直接放行
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=20,ct_state=-trk,actions=ct(zone=1,table=1)"
# table=1 中:
# ESTABLISHED 回程直接转 VLAN 10
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=1,priority=90,ct_state=+est,actions=mod_vlan_vid:10,output:LOCAL"
这样:
-
去程:A.web 发起 3306,被
ct(commit)记录 -
回程:A.db 的包在 conntrack 中是 ESTABLISHED,自动放行
4. 有状态:拒绝非法连接尝试
# A.web 发往 A.db 的非 3306 端口,NEW 状态直接 drop
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=95,dl_vlan=10,tcp,ct_state=-trk,actions=ct(zone=2,table=2)"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=2,priority=100,ct_state=+new,actions=drop"
5. DB → Web 拒绝(双向)
# A.db 主动访问 A.web,直接 drop
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=105,dl_vlan=20,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=105,dl_vlan=40,actions=drop"
6. 跨租户隔离(保持不变)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=10,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=20,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=30,actions=drop"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=120,dl_vlan=40,actions=drop"
7. VXLAN 入方向(解封装 + conntrack)
# A.web(VNI 100) → VLAN 10
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=100,actions=push_vlan:0x8100,mod_vlan_vid:10,output:LOCAL"
# A.db(VNI 200) → VLAN 20
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=200,actions=push_vlan:0x8100,mod_vlan_vid:20,output:LOCAL"
# B.web(VNI 300) → VLAN 30
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=300,actions=push_vlan:0x8100,mod_vlan_vid:30,output:LOCAL"
# B.db(VNI 400) → VLAN 40
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=110,in_port=vxlan0,tun_id=400,actions=push_vlan:0x8100,mod_vlan_vid:40,output:LOCAL"
8. VXLAN 出方向(封装)
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=10,actions=strip_vlan,set_tunnel:100,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=20,actions=strip_vlan,set_tunnel:200,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=30,actions=strip_vlan,set_tunnel:300,output:vxlan0"
ovs-ofctl -O OpenFlow13 add-flow br-int \
"table=0,priority=100,dl_vlan=40,actions=strip_vlan,set_tunnel:400,output:vxlan0"
五、验证有状态安全组
1. 去程 + 回程
# HOST2
sudo ip netns exec vmA-db2 nc -l 3306
# HOST1
sudo ip netns exec vmA-web nc 10.1.1.21 3306
✅ 能连上,且能持续通信(回程包不会被 drop)
2. 非法端口
nc 10.1.1.21 22
❌ 不通,且 conntrack 中不会建立连接
3. 看 conntrack 表
sudo conntrack -L
你会看到类似:
tcp 6 431999 ESTABLISHED src=10.1.1.10 dst=10.1.1.21 sport=xxxxx dport=3306 ...
说明有状态跟踪生效。
六、你现在拥有什么
✅ 多租户
✅ 多安全组(Web / DB)
✅ 有状态安全组(conntrack + OVS)
✅ 有方向、有端口限制
✅ 回程自动放行
✅ 完全手工实现,不依赖云平台
七、下一步可以怎么玩
-
✅ 用 ct_state=+rel 支持 FTP/ICMP 相关连接
-
✅ 在 conntrack 中加 timeout 策略,模拟安全组超时
-
✅ 用 Ryu/ONOS 控制器 自动生成这些 conntrack 流表
-
✅ 上 L3 Gateway + SNAT,让这套"云"能真正访问外网
你更想往 "有状态高级特性" 还是 **"L3 网关 + 上云"** 走?我可以按你选的方向继续搭。