“网络周边安全”是任何一个企业运维团队所必须关注的重点。当我们谈到网络界面控制时,我们往往潜意识地先会想到入站安全(入口)。然而,基于流量的运作,例如,何时可以离开网络(出口)以及流向哪里同样至关重要。在这篇文章中,我们将不深入讨论为什么控制出口流量如此重要的理论细节,毕竟,前人已经说的口都干了。因此,本文仅从技术演进层面来探讨关于在云原生生态中“出口”的选型及实现场景。
在实际的业务场景中,我们往往会遇到如下场景:无论是基于不同业务之间的相互调度所需、或者是基于非法流量及边界业务管控,我们都需要建立我们自己的出口防火墙,以保障我们的业务能够正常运转。具体如下图所示:
撇开运行时环境状态以及技术壁垒,其实,对于我们而言,往往有多种实现方式,只不过所实现的代价有所不同。在基于云原生生态体系,我们可能需要在 Kubernetes 内部创建一个应用程序,以方便路由所有出站流量以及 DNS 流量。从可用性角度而言,为了满足应用程序的可靠性,往往需要部署多个实例予以支撑,使得其在多实例间均衡输出流量。但此种方案往往会产生状态一致性问题,当一个实例发现一个需要允许的新 IP 时,理想情况下,在 DNS 查询完成之前,它需要非常快速地将其与其他实例建立通信,这是有可能的,但是,会给系统增加很多复杂性,其性价比不高。
对于流量出口方面的规划,时至今日,无论基于何种业务场景,目前,主要有以下3种模型可供选择,因此,需要基于自身的需求进行方案的选型,具体如下所示:
1、限制出口流量
2、NAT 映射
3、出口网关
限制出口流量
限制群集的传出连接是一项常见的安全要求和最佳做法。通常,这是通过使用网络策略为每个微服务定义出口规则来实现的,通常将其与确保默认情况下拒绝出站连接的默认拒绝策略结合使用,直到定义了明确允许特定流量的策略。
使用 Kubernetes 网络策略限制对特定外部资源的访问时的一个限制是,需要在策略规则内将外部资源指定为 IP 地址(或IP地址范围)。如果与外部资源关联的 IP 地址发生了变化,则引用这些 IP 地址的每个策略都需要使用新的IP地址进行更新。可以使用 Calico 网络集或 Calico Enterprise 在策略规则中对域名的支持来规避此限制。
除了使用网络策略外,服务网格通常还允许我们自定义配置每个 Pod 可以访问哪些外部服务。对于 Istio,可以集成 Calico 在服务网格层上实施网络策略,包括 L5-7 规则,作为在规则中使用 IP 地址的另一种选择。
请注意,除了到目前为止提到的所有内容之外,外围防火墙还可以用于限制传出连接,例如,仅允许连接到特定的外部 IP 地址范围或外部服务。但是,由于外围防火墙通常无法区分各个 Pod,因此这些规则同样适用于群集中的所有 Pod 。这提供了一定程度的防御,但不能替代对网络策略的要求。
NAT 映射
通常,NAT(网络地址转换)是在数据包通过执行 NAT 的设备时将数据包中的 IP 地址映射到其他 IP 地址的过程。依据不同场景的使用情况,NAT 可以应用于源 IP 地址或目标 IP 地址,也可以应用于两个地址。
在 Kubernetes 出口的上下文中,如果 Pod 具有无法在集群外部路由的 IP 地址(例如,如果 Pod 网络是覆盖网络),则使用 NAT 允许 Pod 连接到集群外部的服务。例如,如果覆盖网络中的 Pod 尝试连接到群集外部的 IP 地址,则托管 Pod 的节点将使用SNAT(源网络地址转换)将数据包的不可路由源 IP 地址映射到 IP 地址。在数据包上转发之前,该节点的 IP 地址。然后,该节点将相反方向的响应数据包映射回原始的 Pod IP 地址,因此数据包在两个方向上都端对端流动,而 Pod 或外部服务均不知道正在发生映射。
在大多数群集中,此 NAT 行为是在整个群集中静态配置的。使用 Calico 时,可以使用 IP 池在特定地址范围内以更精细的级别配置 NAT 行为。这有效地使“不可路由”的范围比“仅在集群内部而不是在集群外部”更严格地定义,这在某些企业部署方案中很有用。
出口网关
Kubernetes 出口的另一种方法是通过一个或多个出口网关路由所有出站连接。网关SNAT(源网络地址转换)连接,因此连接到的外部服务会将连接视为来自出口网关。主要用例是通过出口网关在其允许的连接方面执行直接的安全角色或与外围防火墙(或其他外部实体)结合来提高安全性。例如,以便外围防火墙可以看到来自知名 IP 地址(出口网关)的连接,而不是来自其动态 Pod IP 地址的连接。
接下来,我们以 Istio 为例,简要阐述一下 Egress Gateway 实现场景,具体场景如下:在我们的 Case 中的应用程序命名空间中有两个应用程序:APP-A 和 APP-B,我们希望可以实现以下目标:
1、默认情况下,拒绝从场景中的应用程序命名空间访问所有外部服务。
2、显式允许以下应用程序→外部服务连接:应用程序 A→http://github.com网站;应用程序 A→http://httpbin.org网站;应用程序 B→http://谷歌网站。
3、确保所有对外部服务的调用都通过专用出口网关。
4、能够有效支持 HTTPS 和普通 HTTP 调用。
简要结构示意图如下所示:
(此图源自网络)
基于上述结构示意图,在实际的业务场景中,只需正确配置一些 Istio 资源,如出口网关部署和服务、边车、网关、虚拟服务和服务入口,以便能够借助 Istio 实现对我们的出口流量的管控与追踪。
因此,我们可以简单试想下,若存在一个应用程序列表和一个希望从应用程序访问的外部服务列表,然后简单地选择允许哪些连接。我们可以借助自动的出口控制机制,例如, UI 或 CLI,或者其他声明性方法,并确定它们之间允许哪些连接,所有必要的资源都将在后台自动创建和维护,基于此种场景,何尝不是一种先进的理念呢?
在安全层面,可以借助 Sidecar 代理,限制某些连接的访问以实现服务流量能够运行在专用的网关通道。同时,基于授权策略,使得我们能够对 Mesh 中的工作负载进行访问控制。
综上所述,在后续的微服务发展历程中,我们可以毫无压力地将“服务网格”视为云原生生态领域堆栈体系中的具有划时代意义的关键组件。毕竟,若能够基于云操作化和自动化服务 Mesh,势必将会使得基于不同业务场景所构建和运行基于 Istio 的 Mesh 变得轻而易举,从而解放劳动力。站在另外角度,从某种意义上而言,无论是基于安全而言还是生态的成熟性,着实解决了某些业务领域的痛点。
综上所述,基于容器 K8S 生态中 “Egress“ 机制的相关思考,本文到此为止,大家有任何问题或建议,可以随时留言、沟通。