ARTICLE DETAIL

资讯详情

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

Cilium 网络策略 L4 层指南:限制端口、ICMP/ICMPv6 类型与 TLS SNI

Cilium 网络策略 L4 层指南:限制端口、ICMP/ICMPv6 类型与 TLS SNI Cilium 网络策略 L4 层指南限制端口、ICMP/ICMPv6 类型与 TLS SNI【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium本篇技术指南围绕 Cilium 的 Layer 4传输层网络策略展开系统讲解如何通过CiliumNetworkPolicy精确限制端点的 ingress/egress 端口与协议、按类型限制 ICMP/ICMPv6 报文以及基于 TLS 服务器名称SNI管控出站加密连接。读完本文你将掌握toPorts、icmps、serverNames三个核心策略字段的完整用法能够独立编写从单端口、端口范围到 L3L4 组合的实战策略并理解其在 Cilium 策略引擎中的底层实现原理。概述什么是 Layer 4 策略Cilium 的 Layer 4 策略在 IP 层L3之上、应用层L7之下工作用于限制端点endpoint在特定端口上使用特定传输协议收发数据包的能力。它既可以与 Layer 3 策略叠加使用也可以独立使用例如 l4.yaml 这样的纯 L4 规则。Cilium 的策略默认行为遵循未声明即放行的模型如果某个端点没有指定任何 L4 策略则该端点可以在所有 L4 端口和协议包括 ICMP上收发数据一旦为该端点指定了任何L4 策略ICMP 将被默认阻断除非该 ICMP 报文属于某个被策略放行的连接例如与已允许的 TCP 连接关联的 ICMP 差错报文L4 策略的匹配发生在service 端口映射service port mapping之后即策略中写的端口是转换后的实际端口这一点在编写涉及 Kubernetes Service 的规则时需要特别注意。限制 ingress/egress 端口toPorts字段L4 策略通过toPorts字段同时支持 ingress 与 egress 两个方向。toPorts接收一个PortProtocol结构体其完整定义如下与 pkg/policy/api/l4.go 中的 API 类型保持一致// 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. // // optional 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. // // optional Protocol string json:protocol,omitempty }各字段的语义说明字段类型说明portstringL4 端口号或命名端口named port如http、http-8080。若为命名端口则endPort被忽略endPortint32端口范围的结束端口只能是 L4 端口数字0–65535仅当port为数字时生效protocolstringL4 协议。省略或为空表示匹配任意协议可取值为TCP、UDP或ANY。不支持对 ICMP 的匹配ICMP 需使用下文单独的icmps字段从源码角度看pkg/policy/api/l4.go 中定义了完整的协议常量集除TCP、UDP、SCTP、ICMP、ICMPV6、ANY外还包括VRRP、IGMP以及隧道/封装类协议GRE、IPIP、IPV6、ESP、AH。其中扩展 IP 协议GRE、IPIP、IPV6、ESP、AH和 VRRP、IGMP 需要开启--enable-extended-ip-protocols参数且这些协议不依赖传输层端口。SupportedProtocols()函数表明策略引擎在常规匹配中实际支持 TCP、UDP、SCTP 三种传输协议排除ANY。此外pkg/policy/api/rule_validation.go 中的PortProtocol.Sanitize()会执行两项规范化将符合 IANA 服务名格式的端口名统一转为小写保证大小写不敏感的匹配并将协议字符串解析为规范的L4Proto类型。示例限制到单一 TCP 端口以下规则将带有标签appmyService的所有端点限制为仅能使用 TCP 协议、通过端口 80 发出数据包目标可以是任意 L3 目的地完整文件见 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示例端口范围Port Ranges通过endPort字段可以一次性放行一段连续的端口。以下规则将appmyService的端点限制为仅能使用 TCP 协议、通过 80–444 端口范围发出数据包完整文件见 examples/policies/l4/l4_port_range.yamlapiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: l4-port-range-rule spec: endpointSelector: matchLabels: app: myService egress: - toPorts: - ports: - port: 80 endPort: 444 protocol: TCP需要注意两个与端口范围相关的限制DNS 规则不支持端口范围。在 pkg/policy/api/rule_validation.go 中当策略同时包含 DNS 规则且EndPort大于起始端口时会直接返回错误DNS rules do not support port ranges除 DNS 规则外的其他 Layer 7 规则如 HTTP 规则均支持端口范围。与标签/CIDR 组合的 Layer 4 规则L4 策略最常见的实战形态是与 L3 选择器组合形成谁 到哪 用什么端口/协议的完整约束。示例依赖标签的 L4 规则以下规则完整文件见 examples/policies/l4/l3_l4_combined.yaml允许所有带有rolefrontend标签的端点与所有带有rolebackend标签的端点通信但必须使用 TCP 协议且端口为 80apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: l4-rule spec: endpointSelector: matchLabels: role: backend ingress: - fromEndpoints: - matchLabels: role: frontend toPorts: - ports: - port: 80 protocol: TCP该规则同时带来两层约束效果其他标签的端点无法与rolebackend端点通信rolefrontend端点也不能在 80 端口以外的其他端口与rolebackend通信。示例依赖 CIDR 的 L4 规则以下规则完整文件见 examples/policies/l4/cidr_l4_combined.yaml允许所有带有rolecrawler标签的端点与 CIDR192.0.2.0/24内的所有远端目的地通信但必须使用 TCP 协议且端口为 80apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: cidr-l4-rule spec: endpointSelector: matchLabels: role: crawler egress: - toCIDR: - 192.0.2.0/24 toPorts: - ports: - port: 80 protocol: TCP同样地该规则隐式拒绝了两类流量无rolecrawler标签的端点对192.0.2.0/24的访问以及rolecrawler端点在 80 端口以外对该 CIDR 的访问。限制 ICMP/ICMPv6 类型icmps字段ICMP 策略可以附加在 Layer 3 策略之上也可以独立使用。它通过icmps字段限制端点收发特定 ICMP/ICMPv6 类型的数据包类型既可以写成整数8bit 编码 0–255也可以写成对应的驼峰命名消息名如EchoReply。与 L4 端口策略类似一旦指定了任何 ICMP 策略其他 L4 与 ICMP 通信都会被阻断除非与策略放行的连接相关。icmps字段接收ICMPField结构体其定义位于 pkg/policy/api/icmp.go// ICMPField is a ICMP field. type ICMPField struct { // Family is a IP address version. // Currently, we support IPv4 and IPv6. // IPv4 is set as default. Family string json:family,omitempty // Type is a ICMP-type. // It should be an 8bit code (0-255), or its CamelCase name (for example, EchoReply). Type *intstr.IntOrString json:type }字段说明familyIP 地址版本取值IPv4默认或IPv6typeICMP 类型可为 0–255 的整数或类型的驼峰名称支持的类型与 IP 版本相关由 pkg/policy/api/icmp.go 中的两张映射表定义。IPv4 支持的类型名称与编码对照类型名称编码EchoReply0DestinationUnreachable3Redirect5Echo / EchoRequest8RouterAdvertisement9RouterSelection10TimeExceeded11ParameterProblem12Timestamp13TimestampReply14Photuris40ExtendedEchoRequest42ExtendedEchoReply43IPv6 支持的类型名称与编码对照类型名称编码DestinationUnreachable1PacketTooBig2TimeExceeded3ParameterProblem4EchoRequest128EchoReply129MulticastListenerQuery / Report / Done130 / 131 / 132RouterSolicitation / RouterAdvertisement133 / 134NeighborSolicitation / NeighborAdvertisement135 / 136RedirectMessage137RouterRenumbering138ICMPNodeInformationQuery / Response139 / 140InverseNeighborDiscoverySolicitation / Advertisement141 / 142HomeAgentAddressDiscoveryRequest / Reply144 / 145MobilePrefixSolicitation / Advertisement146 / 147DuplicateAddressRequestCodeSuffix / ConfirmationCodeSuffix157 / 158ExtendedEchoRequest / ExtendedEchoReply160 / 161从源码看ICMPField的自定义UnmarshalJSONpkg/policy/api/icmp.go会在反序列化时校验若Type是命名类型非纯数字则必须存在于对应family的类型名映射表中否则返回错误PortProtocol()方法pkg/policy/api/icmp.go则负责在策略编译时将ICMPField转换为带ICMP/ICMPV6协议的PortProtocol供底层数据路径使用。另外每个ICMPRule的Fields列表最多允许 40 项MaxItems40。示例限制 ICMP/ICMPv6 类型以下规则将appmyService的端点限制为仅能发出 IPv4 ICMP 类型 8Echo Request以及 IPv6 ICMPv6 EchoRequest 消息完整文件见 examples/policies/l4/icmp.yamlapiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: icmp-rule spec: endpointSelector: matchLabels: app: myService egress: - icmps: - fields: - type: 8 family: IPv4 - type: EchoRequest family: IPv6可以看到type: 8整数与type: EchoRequest名称在该规则中可同时混用两种写法对 IPv4 的 Echo Request 指向同一个类型编码8。限制 TLS SNIserverNames字段背景什么是 SNI当多个网站共享同一个 IP 地址托管在同一台服务器上时服务器名称指示Server Name IndicationSNI作为 TLS 协议的扩展确保客户端能拿到自己访问网站的正确 SSL 证书。SNI 允许在 TLS 握手阶段就指定网站的主机名或域名而无需等到握手完成后建立 HTTP 连接时才得知域名。SNI 策略的用法与约束Cilium 网络策略可以限制端点与指定 SNI 列表之间建立 TLS 握手的能力。SNI 策略具有两个显著特点始终配置在 egress 方向且通常与端口策略toPorts搭配使用要求启用 L7 代理TLS SNI 策略的强制实施依赖 L7 proxy。SNI 在策略 API 中由PortRule.ServerNames字段承载定义见 pkg/policy/api/l4.go如果该字段非空则流量必须为 TLS且握手阶段必须包含其中一个允许的 SNI。ServerName类型pkg/policy/api/l4.go还支持两类通配符匹配语义*匹配 0 个或多个 DNS 合法字符可出现在模式的任意位置特殊的*单独出现时匹配所有合法 DNS 名称**.是特殊前缀匹配该前缀下的所有多级子域名。例如*.cilium.io匹配www.cilium.io和blog.cilium.io但不匹配cilium.io本身*cilium.io匹配subcilium.io、sub-cilium.io**.cilium.io匹配app.cilium.io与test.app.cilium.io但不匹配cilium.io。单个ServerName最长 255 字符。示例限制 TLS SNI以下规则完整文件见 examples/policies/l4/l4_sni.yaml将appmyService的端点限制为仅能对one.one.one.one这个 SNI 建立 TLS 连接apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: l4-sni-rule spec: endpointSelector: matchLabels: app: myService egress: - toPorts: - ports: - port: 443 protocol: TCP serverNames: - one.one.one.one该规则将 443 端口 TCP 流量交给 L7 代理检查只有 TLS ClientHello 中携带的 SNI 为one.one.one.one时才放行对任何其他 SNI例如cilium.io的握手尝试都会被拒绝。下面是尝试用 curl 连接cilium.io时被策略拒绝的典型表现$ kubectl exec my-service-pod -- curl -v https://cilium.io * Host cilium.io:443 was resolved. * IPv6: (none) * IPv4: 104.198.14.52 * Trying 104.198.14.52:443... * Connected to cilium.io (104.198.14.52) port 443 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * Recv failure: Connection reset by peer * OpenSSL SSL_connect: Connection reset by peer in connection to cilium.io:443 * Closing connection curl: (35) Recv failure: Connection reset by peer command terminated with exit code 35错误特征很明确TCP 连接已成功建立Connected to cilium.io port 443但在 TLS 握手阶段TLS handshake, Client hello之后连接被对端重置Connection reset by peer最终 curl 以退出码 35SSL connect error结束——这正是 SNI 策略在 L7 代理层拦截非允许域名的表现。策略校验与底层实现要点理解 L4 策略的底层实现有助于排查问题类型与协议规范化策略加载时PortProtocol.Sanitize()pkg/policy/api/rule_validation.go负责端口名小写化与协议解析ICMP 类型名称则通过UnmarshalJSON在反序列化阶段即完成合法性校验。PortProtocol 的覆盖语义pkg/policy/api/l4.go 的Covers()方法定义了端口/协议匹配的相等或超集语义命名端口只能被同名命名端口覆盖协议上ANY可覆盖具体协议。这与策略合并且按最严格规则生效的行为直接相关。deny 策略的差异用于拒绝流量的PortDenyRulepkg/policy/api/l4.go只包含Ports列表不含 L7 规则deny 策略不支持 L7 规则因此 SNI 与 L7 管控只能通过 allow 策略实现。CRD 落地上述字段最终体现在CiliumNetworkPolicy与CiliumClusterwideNetworkPolicy的 CRD 校验规则中见 pkg/k8s/apis/cilium.io/client/crds/v2/ciliumnetworkpolicies.yaml包括port的数字/命名端口正则、endPort的 0–65535 范围、protocol的枚举、ServerNames的通配符模式等确保不合法的 L4 策略在创建时即被 API Server 拒绝。小结Cilium 的 Layer 4 策略通过三个核心字段提供了从传输层到 TLS 层的精细管控能力toPorts限制特定端口与协议TCP/UDP 等的收发支持命名端口与endPort端口范围可独立使用或与fromEndpoints/toCIDR等 L3 选择器组合icmps按类型限制 ICMP/ICMPv6 报文整数编码与驼峰名称两种写法等价serverNames在 egress 方向限制 TLS 握手的 SNI需配合 L7 代理使用支持*与**.通配符。这些字段对应的 API 定义、校验逻辑与转换实现均可在 pkg/policy/api/l4.go、pkg/policy/api/icmp.go 与 pkg/policy/api/rule_validation.go 中追溯完整的可运行示例则收录于 examples/policies/l4 目录。建议读者在编写策略后结合策略校验工具与真实业务流量如文中的 curl 验证方式逐步收紧规则实现最小权限的网络隔离。【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表