容器出口流量控制:OpenShift安全系列第七篇

并不是所有OCP中应用都需要访问外部网络,默认情况下,OpenShift 不限制容器的出口访问流量。为防止来自被***容器集的恶意网络流量,我们可以控制集群出口流量。


OpenShift 提供了多种控制出口流量的方法:

  • OpenShift 出口防火墙

  • OpenShift 出口路由器

  • 出口静态 IP


为了方便理解,我画一个思维导图:

容器出口流量控制:OpenShift安全系列第七篇




红帽 OpenShift  SDN提供的三个插件:

  • ovs-subnet 插件提供一个扁平网络,它分布到所有集群节点并可连接所有容器集。

    ovs-multitenant 插件隔离每个 OpenShift 项目。此插件使用 虚拟可扩展局域网 (VXLAN) ,并为每个项目分配一个 虚拟网络 ID (VNID) 来进行隔离。

    默认情况下,一个项目中的容器集无法访问其他项目中的容器集。您可以使用 oc adm pod-network join-projects 命令来联合项目,使得它们的容器集和服务能够*通信。以下命令允许 projectA 访问 projectB 中的容器集和服务,反之亦然。


  • ovs-networkpolicy 插件允许项目管理员使用 OpenShift 网络策略资源自行定义访问控制。默认情况下,如果未定义任何网络策略资源,项目中的容器集可以访问任何其他容器集。


描述节点和容器集网络

OpenShift 为每个集群节点配置一个名为 br0 的 Open vSwitch 网桥。

容器出口流量控制:OpenShift安全系列第七篇

OpenShift 使用 虚拟以太网设备 (veth) 将容器集连接到 br0 网桥。veth 设备提供一对互连的接口:发送到一端的网络数据包由另一端接收。

OpenShift 为每个容器集创建一个 veth 设备,一端连接到容器集内的 eth0 接口,另一端则连接到 br0 网桥。


节点上的 tun0 接口是 br0 网桥上的 Open vSwitch 端口。OpenShift 使用该接口进行外部集群访问。OpenShift 通过组合使用网络路由、Netfilter NAT 规则和 br0 流表中的条目来配置通过 tun0 进行的外部访问。

OpenShift 使用节点上的 vxlan_sys_4789 接口或者 br0 中的 vxlan0 来构建节点之间的集群覆盖网络。不同节点上容器集之间的通信将经由这个接口。


配置出口防火墙

出口防火墙也是通过配置networkpolicy实现:

cat firewall.yaml
kind: EgressNetworkPolicy
apiVersion: v1
metadata:
 name: myfirewall
spec:
 egress:
 - to:
     cidrSelector: 192.168.12.0/24
   type: Allow
 - to:
     dnsName: db-srv.example.com
   type: Allow
 - to:
     dnsName: analytics.example.com
   type: Allow
 - to:
     cidrSelector: 0.0.0.0/0
   type: Deny

此对象允许出口流量传输到 192.168.12.0/24 网络,再传输到 db-srv.example.com 和 analytics.example.com 系统。最后一条规则拒绝所有其他流量。

由于 OpenShift 在没有规则匹配的情况下允许流量,并按顺序检查规则,因此最后一条规则充当“全部拒绝”默认值。规则仅作用于出口流量,不影响容器集间通信。


使用出口防火墙时有几个限制:

  • 只有集群管理员才能创建 EgressNetworkPolicy 对象。项目成员或项目管理员无法在其项目中定义出口防火墙。

  • OpenShift 必须使用 ovs-multitenant 或 ovs-networkpolicy SDN 插件。

  • 您无法在 OpenShift default 项目中定义出口防火墙。

  • 每个项目只能定义一个 EgressNetworkPolicy 对象。


 Egress 路由器

当容器尝试访问外部网络时,数据包将从容器集流到 br0 网桥,再到发生 NTA 的 tun0 接口,然后流到外部服务。从该服务的角度来看,连接源自OCP节点 IP 地址。

容器出口流量控制:OpenShift安全系列第七篇

如果 OpenShift 将容器集重新放置到另一个节点,或者在多个节点上复制容器集,则外部服务可能会看到多个源 IP 地址。


因此,当防火墙保护服务时,您需要授权所有 OpenShift 节点 IP 地址。如果向集群添加新节点,则还需要更新防火墙规则。这会带来极大的困扰。


通过使用 OpenShift 出口路由器,您可以向防火墙和外部服务提供唯一可识别的源 IP 地址。


出口路由器是在项目中运行的特定容器集。它充当您的容器集和外部服务之间的代理。路由器容器集有两个网络接口:

  • eth0 ,用于和其他集群容器集通信

  • macvlan0 ,用于和外部服务通信


Macvlan 接口是特殊的接口,它直接将节点接口公开给容器。该接口具有底层网络可见的 MAC 地址。

容器出口流量控制:OpenShift安全系列第七篇



出口路由器的运行模式可以是以下三种之一:重定向、HTTP 代理或 DNS 代理。下表介绍并且比较了这些模式。

重定向模式 HTTP 代理模式 DNS 代理模式
容器镜像 openshift3/ose-pod openshift3/ose-egress-http-proxy openshift3/ose-egress-dns-proxy
技术 Netfilter NAT 规则 Squid HAProxy
支持的协议 TCP 和 UDP HTTP 和 HTTPS TCP
通过路由器代理请求所需的应用更新 将外部服务的 IP 地址或名称替换为路由器前面的 OpenShift 服务的名称。 定义 http_proxy 或 https_proxy 环境变量。 将外部服务的 IP 地址或名称替换为路由器前面的 OpenShift 服务的名称。

出口静态 IP 地址

可以在项目级别的 NetNamespace 对象中定义静态 IP 地址。使用这种配置时,发送自项目中容器集的所有出口流量都源自于该 IP 地址。


与出口路由器不同,使用出口 IP 地址不会启动容器集,您也不必修改应用来通过路由器代理流量。

但是,为外部访问启用静态 IP 地址时有几个限制:

  • 只有集群管理员才能在项目的 NetNamespace 对象中定义地址。

  • OpenShift 必须使用 ovs-networkpolicy SDN 插件。

oc patch netnamespace myproject \-p '{"egressIPs": ["172.25.250.19"]}'
netnamespace.network.openshift.io/myproject patched


上一篇:从一张图看Devops全流程


下一篇:OpenShift容量规划方法