ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Cilium 多层网络安全指南:从 L3 身份策略到 L4 端口限制与 L7 应用协议管控

Cilium 多层网络安全指南:从 L3 身份策略到 L4 端口限制与 L7 应用协议管控 Cilium 多层网络安全指南从 L3 身份策略到 L4 端口限制与 L7 应用协议管控【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/ciliumCilium 的安全能力构建在 eBPF 数据路径之上以身份Identity替代 IP 地址作为策略判定的核心依据并在网络协议栈的不同层级提供可独立使用、也可组合叠加的安全策略。本篇基于仓库文档 Documentation/security/network/intro.rst 及其配套的安全概念文档系统讲解 Cilium 的 L3 端点间连接策略、L4 出入站端口限制与 L7 应用协议级访问控制HTTP/RPC/DNS并给出可复制、可运行的 YAML 策略示例。读完本文你将掌握 Cilium 多层安全模型的完整脉络、三种策略执行模式以及如何结合标签、CIDR、服务与实体等不同 selector 编写生产可用的网络策略。Cilium 基于身份的安全模型示意图Cilium 的多层级安全模型如 Documentation/security/network/intro.rst 所述Cilium 在多个层面提供安全能力每一层都可以单独使用也可以组合叠加形成纵深防御L3网络层端点之间的连通性策略Connectivity Policy。例如任何带标签rolefrontend的端点都可以连接任何带标签rolebackend的端点。L4传输层对入站incoming与出站outgoing连接可访问的端口进行限制。例如rolefrontend端点只能发起对 443 端口HTTPS的出站连接rolebackend端点只能接受 443 端口的入站连接。L7应用层在应用协议级别做细粒度访问控制保护 HTTP 与远程过程调用RPC协议。例如rolefrontend端点只能执行 REST API 调用GET /userdata/[0-9]与rolebackend的其他 API 交互一律受限。三个层级分别对应仓库文档 Documentation/security/network/identity.rstL3 身份基础、Documentation/security/policy/layer4.rstL4 策略与 Documentation/security/policy/layer7.rstL7 策略。下文逐一展开。L3 安全把安全从 IP 寻址中彻底解耦传统 IP 过滤模型的可扩展性困境Kubernetes 等容器管理系统为每个 Pod 分配独立的 IP 地址避免不必要的 NAT也让每个容器拥有完整的端口空间。这种模型带来的逻辑后果是随着集群规模与 Pod 数量增长网络层必须管理海量 IP 地址。而传统安全架构恰恰建立在 IP 地址过滤之上。以一个简单例子说明若所有带标签rolefrontend的 Pod 都应被允许向所有rolebackend的 Pod 发起连接那么每个运行了rolebackendPod 的集群节点都必须安装一条过滤器——只允许所有rolefrontendPod 的 IP 地址访问本地rolebackendPod 的 IP 地址其余连接请求一律拒绝。例如目标地址是10.1.1.2时仅当源地址属于[10.1.2.2, 10.1.2.3, 20.4.9.1]才放行。每当一个rolefrontend或rolebackend的 Pod 启动或停止所有相关节点上的规则都必须同步增删对应 IP。在大型分布式应用中这意味着一秒钟内可能要在数千个节点上更新安全规则。更糟的是新rolefrontendPod 的启动必须延迟到所有承载rolebackend的节点更新完规则之后否则新 Pod 发出的连接可能被误丢。这套模型难以高效扩展。身份Identity驱动的安全模型为规避上述限制Cilium 将安全与网络寻址完全分离安全判定基于 Pod 的身份Identity而身份由标签Labels派生。身份可以在多个 Pod 之间共享当第一个rolefrontendPod 启动时Cilium 为其分配一个身份该身份被允许向rolebackend的身份发起连接后续再启动更多rolefrontendPod只需通过键值存储key-value store解析该身份无需在任何承载rolebackend的节点上执行操作新 Pod 的启动只需等待其身份解析完成——这远比在所有其他节点上更新安全规则简单得多。此机制在 Documentation/security/network/identity.rst 中有完整论述锚点arch_id_security。围绕身份Cilium 还派生了安全相关的辅助概念详见 Documentation/security/network/index.rst 中的安全概念导航identity、policyenforcement、proxy、encryption 等章节。跨节点身份传递身份必须随数据包在网络中传递才能在多主机集群中生效。如 Documentation/security/network/policyenforcement.rst 所述发送端点的身份被嵌入到集群节点之间传输的每一个网络数据包中接收节点提取身份后即可校验某个身份是否被允许与本地端点通信。这正是 Cilium 能保持节点本地决策、全局一致策略的关键实现机制。策略执行机制有状态、双向语义与默认策略有状态策略语义所有安全策略都基于有状态stateful策略执行描述会话类协议策略表达的意图是连接建立的允许方向。若策略允许A B则B到A的回复包被自动放行但B并不会因此自动获得向A发起连接的权限——若需要该结果必须显式允许两个方向。策略可以在ingress入站或egress出站执行ingress 表示每个集群节点校验所有入站数据包判断其是否可被传送给目标端点egress 则校验出站数据包判断其是否可被传送到预期目的地。默认安全策略Default Security Policy默认行为遵循先放行、后收紧的白名单模型未加载任何策略时默认允许所有通信除非显式启用了策略执行一旦加载第一条策略规则策略执行自动开启此后所有通信必须被白名单化否则相关数据包将被丢弃同理若端点不受任何 L4 策略约束所有端口的出入通信均被允许一旦为端点关联至少一条 L4 策略所有未显式允许的端口连接将被阻断。三种策略执行模式Documentation/security/policy/intro.rst锚点policy_enforcement_modes定义了 cilium-agent 的三种策略执行模式模式行为default默认行为。端点在被策略选中前拥有不受限的网络访问被策略选中后仅允许被允许的流量。该状态按方向独立判定并可逐策略调整见下文的EnableDefaultDenyalways即使没有任何规则选中特定端点也在所有端点上启用策略执行never即使在规则选中特定端点时也在所有端点上禁用策略执行即所有流量全部放行配置方式通过 Helm 值policyEnforcementMode或对应的 cilium-agent 配置标志enable-policy设置。若在enable-policy: always模式下运行健康检查通常还需要显式放行健康端点health endpoint的通信。端点默认拒绝default-deny语义默认情况下所有端点的出站与入站流量都是放行的。当端点被某条网络策略选中时它会按方向转换到默认拒绝default-deny状态只允许显式放行的流量任何规则选中某端点且含 ingress 段 → 该端点在 ingress 方向进入默认拒绝任何规则选中某端点且含 egress 段 → 该端点在 egress 方向进入默认拒绝。策略可以显式关闭默认拒绝字段EnableDefaultDeny用于配置。EnableDefaultDeny被禁用的规则在判定默认模式时被忽略。这使管理员可以安全地全集群应用仅观测类策略而不会让合法流量被误丢。例如下面的策略拦截所有 DNS 流量用于观测但即使它是作用于端点的第一条策略也不会将端点置入默认拒绝apiVersion: cilium.io/v2 kind: CiliumClusterwideNetworkPolicy metadata: name: intercept-all-dns spec: endpointSelector: matchExpressions: - key: io.kubernetes.pod.namespace operator: NotIn values: - kube-system - key: k8s-app operator: NotIn values: - kube-dns enableDefaultDeny: egress: false ingress: false egress: - toEndpoints: - matchLabels: io.kubernetes.pod.namespace: kube-system k8s-app: kube-dns toPorts: - ports: - port: 53 protocol: TCP - port: 53 protocol: UDP rules: dns: - matchPattern: *注意EnableDefaultDeny不适用于 L7 策略。添加一条不含L7 allow-all的 L7 规则即使显式禁用了 default-deny也会造成丢包。拒绝响应处理Policy Deny Response默认情况下网络策略拒绝 Pod 的 egress 流量时Cilium 会静默丢包应用表现为连接超时而非立即失败。通过--policy-deny-response选项可以改变该行为none默认静默丢弃被拒绝的数据包应用体验到连接超时icmp实验性当 egress 流量被策略拒绝时向源 Pod 回送 ICMP Destination Unreachable给应用即时反馈。注意事项icmp模式仅适用于被网络策略拒绝的 IPv4/IPv6 egress Pod 流量暂不支持 ingress 方向的拒绝且使用该模式时必须确保 ICMP ingress 流量已被策略放行否则应用仍会体验超时。规则基础Rule Basics与白名单模型所有策略规则均基于白名单模型规则只放行匹配的流量。若两条规则中一条覆盖更广则所有匹配更广规则的流量都被放行若多条规则存在交集则匹配这些规则并集的流量被放行不匹配任何规则的流量按策略执行模式被丢弃。策略规则共享一个公共基类型指定规则作用于哪些端点及标识规则的元数据。每条规则分为 ingress 段与 egress 段。其核心 Go 结构定义与 api/v1 中的策略类型一致如下type Rule struct { // EndpointSelector selects all endpoints which should be subject to // this rule. EndpointSelector and NodeSelector cannot be both empty and // are mutually exclusive. EndpointSelector EndpointSelector json:endpointSelector,omitempty // NodeSelector selects all nodes which should be subject to this rule. // Can only be used in CiliumClusterwideNetworkPolicies. NodeSelector EndpointSelector json:nodeSelector,omitempty // Ingress is a list of IngressRule which are enforced at ingress. Ingress []IngressRule json:ingress,omitempty // Egress is a list of EgressRule which are enforced at egress. Egress []EgressRule json:egress,omitempty // Labels is a list of optional strings which can be used to // re-identify the rule or to store metadata. Labels labels.LabelArray json:labels,omitempty // Description is a free form string, it can be used by the creator of // the rule to store human readable explanation of the purpose of this // rule. Rules cannot be identified by comment. Description string json:description,omitempty }字段要点endpointSelector/nodeSelector选择策略作用的对象。endpointSelector基于 Kubernetes LabelSelector只匹配端点Endpoint的标签nodeSelector同样基于 LabelSelector 但匹配集群节点的标签且只能在 CiliumClusterwideNetworkPolicy 中使用详见 HostPolicies。两者互斥且不能同时为空。ingress/egress分别作用于进入/离开端点的网络数据包。两者均可省略若同时省略则该规则不产生效果。labels标识规则的标签用于规则列表查询与按标签删除。通过 Kubernetes 导入的策略会自动获得标签io.cilium.k8s.policy.nameNAMENAME对应 NetworkPolicy 或 CiliumNetworkPolicy 资源的名称。description自由文本仅作人类可读的意图说明不被 Cilium 解释。L4 安全限制出入站端口toPorts 与 PortProtocol 结构L4 策略可以叠加在 L3 策略之上也可以独立使用。它限制端点通过特定协议在特定端口上收发数据包。若端点没有指定任何 L4 策略则允许其在所有 L4 端口与协议含 ICMP上收发一旦指定了任意 L4 策略ICMP 将被阻断除非它属于策略允许的连接的相关流量。L4 策略作用于服务端口映射service port mapping完成之后的端口。L4 策略通过toPorts字段在 ingress 和 egress 两个方向指定其类型为PortProtocol// PortProtocol specifies an L4 port with an optional transport protocol type PortProtocol struct { // Port can be an L4 port number, or a name in the form of http // or http-8080. EndPort is ignored if Port is a named port. Port string json:port // EndPort can only be an L4 port number. It is ignored when // Port is a named port. EndPort int32 json:endPort,omitempty // Protocol is the L4 protocol. If omitted or empty, any protocol // matches. Accepted values: TCP, UDP, /ANY // Matching on ICMP is not supported. Protocol string json:protocol,omitempty }要点Port可以是端口号也可以是命名端口如http、http-8080EndPort用于表达端口范围此时Port是起始端口Protocol接受TCP、UDP、/ANY任意协议不支持匹配 ICMP。基础示例限定 TCP 80以下规则将带标签appmyService的所有端点限制为只能向任意 L3 目的地使用 TCP 发送 80 端口的数据包对应仓库示例 examples/policies/l4/l4.yamlapiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: l4-rule spec: endpointSelector: matchLabels: app: myService egress: - toPorts: - ports: - port: 80 protocol: TCP端口范围示例限制appmyService端点只能向任意 L3 目的地使用 TCP 发送 80–444 端口的数据包示例见 examples/policies/l4/l4_port_range.yamlapiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: l4-rule spec: endpointSelector: matchLabels: app: myService egress: - toPorts: - ports: - port: 80 endPort: 444 protocol: TCP说明L7 规则支持端口范围但 DNS 规则除外。L3L4 组合示例examples/policies/l4/l3_l4_combined.yaml 展示了标签依赖的 L4 规则允许所有rolefrontend端点与所有rolebackend端点通信但必须使用 TCP 80 端口其他标签的端点无法与rolebackend通信rolefrontend也无法在 80 之外的端口与rolebackend通信。CIDR 依赖的 L4 规则见 examples/policies/l4/cidr_l4_combined.yaml则把同样的端口限制叠加到fromCIDR/toCIDR之上。限制 ICMP/ICMPv6 类型通过icmps字段类型ICMPField可以精细限制端点收发特定 ICMP/ICMPv6 类型。Family支持IPv4默认与IPv6Type可以是 8 位数字0–255或对应的 CamelCase 消息名如EchoReply、DestinationUnreachable、TimeExceeded等。一旦指定任何 ICMP 策略L4 与 ICMP 通信将被阻断除非属于策略允许的连接。完整示例见 examples/policies/l4/icmp.yaml。TLS SNI 限制当一个服务器 IP 上托管多个网站时TLS 的 SNIServer Name Indication扩展在握手阶段携带主机名/域名决定返回哪张证书。Cilium 策略可以限制端点只能与指定 SNI 列表建立 TLS 握手。SNI 策略总是在 egress 级别配置通常与端口策略组合使用且要求启用 L7 代理。示例见 examples/policies/l4/l4_sni.yaml限制appmyService端点只能与 SNI 为one.one.one.one的服务器建立 TLS 连接尝试其他 SNI 会被拒绝——使用 curl 访问cilium.io时会直接收到Connection reset by peercurl: (35) Recv failure。L7 安全应用协议级访问控制L7 规则的嵌入方式与组合语义L7 策略规则嵌入在 L4 规则中可用于 ingress 与 egress。基类型L7Rules是一个端口级规则类型的联合体// L7Rules is a union of port level rule types. Mixing of different port // level rule types is disallowed, so exactly one of the following must be set. // If none are specified, then no additional port level rules are applied. type L7Rules struct { // HTTP specific rules. HTTP []PortRuleHTTP json:http,omitempty // DNS-specific rules. DNS []PortRuleDNS json:dns,omitempty }语义要点L7Rules是联合体结构每个端口只能使用其中一个成员字段若多条toPorts规则以相同PortProtocol选中重叠端点集合同类型的 L7 规则会合并类型不同则策略被拒绝每个成员是一组应用协议规则列表L7 请求只要匹配其中至少一条规则即被允许若未指定任何规则则全部流量放行若策略中同时存在一条普通 L4 规则和一条带 L7 规则的相似 L4 规则后者的 L7 部分不生效与 L3/L4 策略不同违反 L7 规则不会丢包Cilium 会尽可能构造并返回应用协议级的拒绝消息例如 HTTP 请求返回HTTP 403 access deniedDNS 请求返回DNS REFUSEDL7 策略会将流量代理到节点本地的 Envoy 实例以 DaemonSet 或内嵌于 agent Pod 方式部署因此被策略覆盖的 L7 流量依赖 Cilium agent Pod 的可用性在 HostPolicy使用nodeSelector中目前仅 DNS 类 L7 规则可用。HTTP 策略HTTP 规则PortRuleHTTP支持以下匹配字段均使用扩展 POSIX 正则字段匹配对象说明path请求路径必须以/开头省略或为空则所有路径放行method请求方法如GET、POST、PUT、PATCH、DELETE省略或为空则全部方法放行hostHost 头如foo.com省略或为空则忽略 Host 头headersHTTP 头请求中必须存在的头部列表还可通过HeaderMatches对头部值做高级匹配并用Mismatch字段定义不匹配时的行为典型示例——允许envprod端点向appservice端点发起GET /public对应 examples/policies/l7/http/simple/l7.yamlapiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: rule1 spec: description: Allow HTTP GET /public from envprod to appservice endpointSelector: matchLabels: app: service ingress: - fromEndpoints: - matchLabels: env: prod toPorts: - ports: - port: 80 protocol: TCP rules: http: - method: GET path: /public该策略下访问其他 URL 或使用其他方法的请求都会被拒绝HTTP 40380 之外端口的请求则被丢弃。另一个示例examples/policies/l7/http/http.yaml展示带头部约束的规则限制appmyService端点只能在 80 端口以 TCP 接收数据且仅允许GET /path1与携带X-My-Header: true的PUT /path2。DNS 策略与 IP 发现L7 DNS 策略对 DNS 查询做允许/拒绝仅按查询名或名称模式判定不考虑查询类型等其他字段由DNS Proxy执行。代理同时收集响应中的 IP用于填充 L3 的toFQDNs规则见 Documentation/security/policy/layer3.rst 的 DNS based 一节。匹配方式与 L3toFQDNs一致matchName精确匹配域名多个matchName条目可并列matchPattern模式匹配支持通配符——*在域名内匹配 0 个或多个合法 DNS 字符但不跨.*.cilium.io匹配sub.cilium.io但不匹配cilium.io或sub.sub.cilium.io单独的*匹配所有名称并把响应中的全部 IP 写入 agent 的 DNS 缓存。实践要点在 Kubernetes 中应用 DNS 策略时必须显式放行service.namespace.svc.cluster.local.形式的查询matchPattern: *.*.svc.cluster.local.依赖 DNS search list 补全 FQDN 的查询必须整体放行强烈建议只拦截发往集群 DNS 服务如kube-dns的 DNS 流量避免扩大 DNS 策略的信任边界部分常见容器镜像如基于 musl 的 Alpine会把 DNS Proxy 的Refused响应当作更严重的失败停止遍历/etc/resolv.conf中的 search list。可用--tofqdns-dns-reject-response-code选项缓解默认refused可改为nameError返回 NXDomain更精细的方案是为 Pod 配置合适的ndots通过dnsConfigDNS 规则不支持端口范围拦截 DNS 数据本身也是一条独立的策略规则需配置--enable-l7-proxytrue并包含rules.dnsYAML 块若要观测而不断言可参考 examples/policies/l7/dns/dns-visibility.yaml。综合示例examples/policies/l7/dns/dns.yaml中L7 DNS 策略只放行cilium.io、其任意子域及api.cilium.io的任意子域L3toFQDNs规则则只允许连接到 DNS 响应中返回的、匹配特定名称集的 IP并叠加 L4 端口限制此处为 TCP 80。DNS 查询被允许但未被toFQDNs选中的域名其 IP 仍不可连接。L3 策略的五种表达方式在 Cilium 中L3 连通性策略可以通过以下方式表达详见 Documentation/security/policy/layer3.rstEndpoints based基于端点双方都是 Cilium 管理的端点用EndpointSelector描述关系。优势在于 IP 地址不写入策略策略与寻址完全解耦——这也是 intro 文档中rolefrontend/rolebackend例子的实现方式。空EndpointSelector匹配所有端点。Ingress 用fromEndpoints选源Egress 用toEndpoints选目标。基础 ingress 示例见 examples/policies/l3/simple/l3.yamlapiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: l3-rule spec: endpointSelector: matchLabels: role: backend ingress: - fromEndpoints: - matchLabels: role: frontendServices based基于服务借助编排系统的服务概念如 Kubernetes Service endpoints即使目标端点不受 Cilium 管理也无需把 IP 硬编码进策略。通过 egress 规则中的toServices按名称或标签选择器引用 Kubernetes Service。无选择器的 Service 会被转换为 CIDR 选择器受限于 CIDR 规则无法选择 Pod 的约束不建议用toServices授权访问default/kuberneteskube-apiserver应使用kube-apiserver实体。Entities based基于实体用语义化实体描述无需知道 IP 的远端对端包括host本地主机及 host-network 容器、remote-node集群内其他节点、kube-apiserver、ingress处理 L7 流量的 Cilium Envoy 实例、cluster本地集群全部端点、cluster-mesh、init身份未解析的启动中端点、health健康检查端点、unmanaged、world集群外全部端点等价于0.0.0.0/0与all。示例见 examples/policies/l3/entities 下的 apiserver.yaml、host.yaml、nodes.yaml、world.yaml。Node based基于节点remote-node实体的扩展。启用--enable-node-selector-labelstrue或 Helm 值nodeSelectorLabels: true后每个 cilium-agent 为其他节点分配独立的远端节点身份可通过fromNodes/toNodes只允许特定节点访问并可用--node-labels过滤参与身份计算的标签。示例见 examples/policies/l3/entities/customnodes.yaml。CIDR based基于 IP/CIDR当远端不受 Cilium 管理、没有标签时使用外部服务、VM、物理机等需要把 IP 或子网硬编码进策略应作为最后手段。Ingress 用fromCIDR/fromCIDRSetEgress 用toCIDR/toCIDRSet*CIDRSet还支持排除子网并可间接引用 CiliumCIDRGroup 以降低大规模 CIDR 选择带来的身份消耗。默认情况下 CIDR 选择器不匹配集群内实体--policy-cidr-match-modepods|nodes可改变该行为但会显著增加安全身份消耗官方建议默认保持关闭。DNS based基于 DNS / FQDN用域名选择集群外远端toFQDNs的matchName/matchPattern由 DNS Proxy 拦截响应并学习 IP行为与 CIDR 规则类似且尊重 DNS TTL。每个 FQDN 每端点默认最多保留 50 个 IP--tofqdns-endpoint-max-ip-per-hostname可调超限后最旧的 IP 自动过期。toFQDNs规则不能再包含其他 L3 规则如toEndpoints、toCIDR但可携带 L4/L7 规则。示例见 examples/policies/l3/fqdn/fqdn.yaml。注意fromRequires/toRequires用于建立基础标签要求自 Cilium 1.19 起已被移除。如需基线约束语义请基于上述 selector 组合实现。结语组合多层策略构建纵深防御把四个层级串起来看Cilium 的安全模型是身份驱动、分层叠加、按方向默认拒绝L3 用身份标签派生而非 IP 建立端点间连通性基线天然免疫 IP 漂移与大规模规则同步问题L4 在传输层收紧端口与协议含 ICMP 类型与 TLS SNIL3 与 L4 可独立或组合使用L7 通过 Envoy 代理对 HTTP/RPC/DNS 做应用级断言违规流量返回协议级拒绝消息而非静默丢包策略执行遵循白名单模型与按方向ingress/egress的 default-deny 语义未加载策略时默认放行首条策略加载后自动收紧。围绕这些概念仓库提供了完整可运行示例examples/policies 下的 l3、l4、l7 子目录与更细的策略话题如 Documentation/security/policy/deny.rst 的显式拒绝、Documentation/security/policy/host.rst 的主机策略、Documentation/security/policy/lifecycle.rst 的策略生命周期可在此基础上按业务场景逐层组合构建从 Pod 到集群出口的完整纵深防御体系。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表