云网络探索

云网络技术,就是把传统网络"搬上云",用软件 + 虚拟化 + 自动化,为云上资源提供按需、弹性、可编排的网络服务。它解决的是:在云环境里,如何像管理计算/存储一样,方便、智能地管理网络。

下面分几块说清楚。


一、云网络是什么

  • 本质

    在公有云 / 私有云 / 混合云中,通过网络虚拟化、软件定义、智能控制等手段,为云服务器、容器、存储、数据库等提供:

    • 互联互通

    • 安全隔离

    • 流量优化

    • 全球访问加速

  • 目标 :让网络从"硬件+人工配置"变成"软件+代码+自动策略",实现随业务伸缩、按使用付费、可快速变更


二、核心技术体系

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

  1. VLAN 的局限

    • 标准 802.1Q 只给 12bit 的 VLAN ID,最多 4094 个​ 网络标识。

    • 在云环境、多租户环境,这点数量远远不够,而且配置、管理都比较"重"。

  2. 云网络的需求

    • 要支持大量租户、大量虚拟网络

    • 要能在不同物理机房/可用区之间,把同一个"虚拟二层域"拉通;

    • 要能在普通 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 内的两台虚拟机跨三层通信"为例:

  1. 源端处理(发送方)

    • 虚拟机 A 发出普通以太网帧,目标 MAC 是虚拟机 B。

    • 所在主机的 VTEP​ 查表:

      • 发现 B 的 MAC 对应远端 VTEP 的 IP;
    • 给该帧加上 VXLAN 头(填入 VNI)、UDP 头、IP 头、外层 MAC 头,形成 VXLAN 包,发往对端 VTEP。

  2. 网络传输

    • 中间三层网络只认识"源/目 IP = 两个 VTEP",对里面的 VXLAN 内容"视而不见",按普通 IP 包转发。
  3. 目的端处理(接收方)

    • 对端 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"为例,用文字画一下数据流动:

  1. VM1 发普通以太网帧

    • 源 MAC = VM1,目的 MAC = VM2,VLAN/VNI 暂时没体现在帧上。
  2. OVS 在 Host1 的处理

    • 入端口:tap 口(接 VM1);

    • 流表匹配:

      • 根据 VM1 的 MAC 学习/查表,发现目标 MAC 在 Host2 的 VTEP IP
    • 动作:

      • 给该帧加 VXLAN 头(VNI=xxx)、UDP 头、外层 IP(源=Host1_VTEP_IP,目=Host2_VTEP_IP)、外层 MAC;
    • 出端口:连接到物理网卡的 uplink 口,发到物理网络。

  3. 物理网络只做普通 IP 转发

    • 看到的是两个 VTEP IP 之间的普通 IP 包,不解析 VXLAN 内容。
  4. OVS 在 Host2 的处理

    • 入端口:uplink 口收到 VXLAN 包;

    • 流表匹配:识别是 VXLAN 包,VNI=xxx,解封装,得到原始以太网帧;

    • 查表找到目标 MAC 对应本机 tap 口(接 VM2),从对应端口送出。

  5. VM2 正常收包

    • 完全感觉不到中间经过了一层 VXLAN 隧道。

三、OVS 中 VXLAN 的关键配置点

在 OVS 上配 VXLAN,一般要设置这些对象:

  1. **网桥(Bridge)**​

    • br-intbr-vxlan,作为本机虚拟交换机的核心。

    • 上挂:

      • 虚拟机/容器的 tap/veth 端口;

      • VXLAN 隧道端口。

  2. 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,用于区分不同虚拟网络。

  3. **流表(OpenFlow)**​

    • 告诉 OVS:

      • 什么样的流量要进 VXLAN 隧道(查 MAC 表,命中则 set_tunnel:VNI+ output:vxlan0);

      • 收到的 VXLAN 包如何解封装并送到正确端口(pop_vxlan+ 查表 + output 到 tap)。

    • 在云/SDN 场景里,流表通常由控制器(如 ODL、ONOS、Neutron 插件等)统一下发。

  4. FDB / MAC 学习

    • OVS 会学习:

      • 本机端口 ↔ MAC 的映射;

      • 远端 MAC ↔ 远端 VTEP IP 的映射(通过 VXLAN 控制平面或自学习)。

    • 这些表项决定"包要进哪个 VXLAN 隧道、从哪个本地端口发出去"。


四、典型使用场景

  1. KVM/QEMU 虚拟化 + OVS 的云主机网络

    • 每台物理机装 OVS,虚机接在 br-int上;

    • 跨物理机的同 VNI 虚机,通过 OVS 的 VXLAN 隧道通信;

    • 不同租户用不同 VNI,实现逻辑隔离。

  2. **容器网络(如 OVS + VXLAN 实现 Overlay)**​

    • 容器通过 veth pair 连到 OVS 网桥;

    • 多台宿主机 OVS 用 VXLAN 互联,让容器"像在一个 L2 网"里,支持跨主机 Pod 直连。

  3. 与 OpenStack Neutron 集成

    • Neutron 的 ML2+OVS+VXLAN 驱动:

      • 每个租户网络分配一个 VNI;

      • 在每个计算节点上,Neutron 通过 OVS agent 自动创建 VXLAN 隧道端口、配置流表;

      • 管理员只需要定义网络/子网/端口,底层 OVS+ VXLAN 自动完成。

  4. 实验/教学环境

    • 在几台虚拟机/云主机上装 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 / 控制器,纯命令行即可跑通。

    目标是:

  • 两台物理机/虚拟机:host1host2

  • 每台上一台 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/200dl_vlan=10/20等匹配条件。


六、这已经非常接近真实云了

云/Neutron 概念 本实验对应
br-int 集成网桥
VLAN tag 本地租户标识
VXLAN VNI 跨主机租户标识
Flow Table 控制器下发的转发 + ACL
Security Group 可在流表里再加 drop/allow规则

七、下一步可以继续的方向

你可以任选其一深入:

  1. 加简易安全组:在流表里对某些 VLAN/VNI 禁止 ICMP / 特定端口

  2. 换成控制器模式 :用 ovs-testcontroller或更真实的 SDN 控制器下发流表

  3. 接入 DHCP:给每个 VLAN/VNI 配一个简单的 dnsmasq 实例

  4. 模拟路由器/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)**​ 就够了,逻辑是:

  1. 同 VLAN / 同 VNI → 允许

  2. 不同 VLAN / 不同 VNI → 丢弃

  3. 指定协议端口 → 允许或拒绝


二、先回顾当前环境

  • br-int

  • VLAN:

    • Tenant A:VLAN 10 / VNI 100

    • Tenant B:VLAN 20 / VNI 200

  • 流表已存在:

    • VLAN → VXLAN 封装

    • VXLAN → VLAN 解封装

👉 现在 **只在现有流表前插入"安全规则"**​ 即可。


三、安全组规则示例(租户 A)

规则定义(你可以理解为 Neutron SG)

  1. ✅ 允许同租户 VM 之间任意通信

  2. ✅ 允许 ICMP

  3. ✅ 允许 TCP 80(HTTP)

  4. ❌ 拒绝 TCP 23(Telnet)

  5. ❌ 拒绝来自 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)

✅ 无控制器纯手工实现


九、下一步还能怎么玩?

你可以继续升级成:

  1. 多安全组(Web / DB 分组)

  2. 有状态安全组(conntrack)

  3. L3 Gateway + SNAT

  4. 用 ovs-testcontroller 自动下发 SG

  5. 对比 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。

跨主机时:

  • 用 VXLAN 的 tun_id表示"安全组 + 租户":

这样:

  • 同安全组跨主机 = 同 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​ 自动下发这些流表

你希望我下一步帮你:

  1. Tenant B 的 web/db 组​ 也配出来,做多租户多组联调,还是

  2. 直接上 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

✅ 不依赖任何云平台


七、下一步还能怎么进化?

你已经站在"云网络工程师"的门口了,接下来可以选一条路线:

  1. 有状态安全组(conntrack)

  2. L3 Gateway + SNAT(让 VM 上网)

  3. 用 ovs-testcontroller / Ryu / ONOS 自动下发流表

  4. 对照 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

  1. conntrack 模块

    • 在内核里跟踪每个连接(四元组 + 状态)

    • 状态:NEW / ESTABLISHED / RELATED / INVALID 等

  2. OVS 的 ct 动作

    • ct(table=...,zone=...):把包交给 conntrack 处理,进入 conntrack 表

    • ct_state=+new-est:匹配"新建或已建立"的连接

    • ct_commit:把这条流加入 conntrack 表,以后自动识别回程

  3. 在流表中使用

    • 入方向:判断 ct_state,NEW 时做安全组检查,ESTABLISHED 时直接放行

    • 出方向:同理,或利用"回程包"的 conntrack 状态自动通过


三、环境准备:加载 conntrack 支持

  1. 确保内核和 OVS 支持:

    检查 conntrack 模块

    lsmod | grep nf_conntrack

    加载(如未加载)

    sudo modprobe nf_conntrack
    sudo modprobe nf_conntrack_ipv4

  2. 确保 OVS 编译时带 --enable-conntrack或包管理器已带(现代发行版一般都有)。

  3. 在 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 网关 + 上云"**​ 走?我可以按你选的方向继续搭。

相关推荐
M158227690552 小时前
SG-ECAT-HUB_4 4 口 EtherCAT 分支器|一进三出・多拓扑・DC 同步工业扩展神器
网络·tcp/ip
鸢尾掠地平2 小时前
什么是VLAN中的Hybrid(混杂口)?如何使用Hybrid(混杂口)?
网络
芯智工坊3 小时前
第4章 Mosquitto命令行工具快速上手
网络·人工智能·mqtt·开源
taxunjishu3 小时前
Profinet转Modbus TCP正极材料匀浆智能网关实施方案
网络·网络协议
萤火阳光3 小时前
43|Python 异步生态深度:aiohttp/aiomysql/aioredis 全链路异步实战
开发语言·网络·python
robin59113 小时前
【技术】更改docker网络MTU办法
网络·docker·容器
二月夜3 小时前
深入理解网络分区架构:外网、DMZ与内网详解
网络
不早睡不改名@4 小时前
Netty源码解析---FastThreadLocal-addToVariablesToRemove方法详解
java·网络·笔记·学习·netty
NaclarbCSDN4 小时前
User ID controlled by request parameter with password disclosure-Burp 复现
网络·安全·web安全