云原生网格里的智能门卫:用 Istio EnvoyFilter 打造自定义 WAF 安全规则

服务网格(Service Mesh)正在重塑微服务的安全边界。本文从头拆解 Istio 与 EnvoyFilter 的原理,手把手教你编写运行在数据面上的自定义 WAF 规则,无需额外硬件或反向代理,即可实现 SQL 注入、XSS 等攻击的边车级拦截。适合想深入了解服务网格安全实践的小白。

云原生网格里的智能门卫:用 Istio EnvoyFilter 打造自定义 WAF 安全规则
封面图:ZuCDN · ZuCDN 原创

从“网格”说起:服务网格到底是什么

我的处理经验

说到Mesh Istio,很多问题都出在细节上。在传统的单体架构里,安全防护往往集中在网关或应用自身。但微服务化之后,服务之间动辄成百上千条网络调用,每个服务都自己实现安全逻辑既不现实,也容易产生漏洞。这时候,服务网格(Service Mesh) 出现了——它把网络通信、负载均衡、服务发现、安全策略等基础设施能力从业务代码中剥离出来,下沉到一个独立的基础设施层。这个层通常以“边车代理”(Sidecar Proxy)的形式伴随每个服务实例运行。

你只需要部署一个代理容器(比如 Envoy),它自动劫持服务进出流量,所有集群内的通信都经过它。于是,整个网格变成了一个可编程的数据平面,安全规则、流量路由、可观测性全部可以在这个平面上统一配置。这就是云原生 Mesh 架构的核心思想。

Istio 和 Envoy:谁在网格里干活?

容易忽略的细节

目前最流行的服务网格实现是 Istio。它并不是自己实现了代理,而是基于 Envoy(一个高性能 C++ 代理)来作为数据平面。Istio 的控制平面负责下发配置(比如路由、策略、安全规则),而 Envoy 代理负责执行。换句话说,Istio 是大脑,Envoy 是手脚。

Envoy 强大的可扩展性使其支持动态配置。除了内置的 HTTP 连接管理、健康检查、TLS 终止等功能,Envoy 还提供了一种机制允许用户在不修改 Envoy 核心代码的前提下,注入自定义逻辑——这就是 EnvoyFilter

EnvoyFilter 是什么?为什么它适合做 WAF?——Mesh Istio

实际操作要点

EnvoyFilter 是 Istio 中的一种自定义资源(CRD),允许你直接操作 Envoy 的配置。你可以通过它插入新的过滤器、修改现有过滤器参数、甚至完全替换 Envoy 监听器或集群配置。对于安全场景来说,我们最常用的是在 HTTP 连接管理器(HttpConnectionManager)上插入一个 Lua 过滤器本地速率限制过滤器,实现自定义的请求检查逻辑。

传统的 WAF(Web 应用防火墙) 通常部署在入口网关(如 Nginx、硬件设备)或者作为反向代理集群。但在服务网格中,每个服务实例都有一个 Envoy 边车,这意味着你可以在距离攻击目标最近的地方——也就是每个服务的入口——执行安全检测。这样有几个明显优势:

  • 精细化:可以为特定的服务、特定的路由、特定的请求头设定不同的规则。
  • 无侵入:业务代码完全不需要修改,安全能力由基础设施层提供。
  • 统一管控:所有安全策略通过 Istio 控制平面集中下发,审计和变更都非常方便。

用 EnvoyFilter 实现 WAF 的两种常见方式

1. 使用 Envoy 内置的 rate_limit 过滤器做简单的请求限频

虽然限频不属于严格意义上的 WAF,但它是防止暴力破解和 CC 攻击的有效手段。Envoy 的本地速率限制过滤器可以直接在 EnvoyFilter 中配置阈值,比如每个客户端 IP 每秒最多 10 次请求。

2. 使用 Lua 过滤器编写自定义检测逻辑

Envoy 支持内嵌 Lua 虚拟机,你可以编写 Lua 脚本拦截 HTTP 请求/响应,检查 URL、请求体、请求头中的可疑模式。例如检测 SQL 注入关键词(’ OR 1=1 — 等)、XSS 标签()等。检测到攻击后,可以返回 403、记录日志或直接丢弃连接。

动手:一个拦截 SQL 注入的 EnvoyFilter 实例

先看关键判断

假设我们有一个微服务 orders,它在集群内部接收来自前端网关的请求。我们想对 /api/orders 路径下的所有 POST 请求体进行简单的关键词检查,发现 SQL 注入特征则拒绝。下面是一个典型的 EnvoyFilter 配置(YAML):

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: orders-sql-injection-filter
  namespace: default
spec:
  workloadSelector:
    labels:
      app: orders
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        portNumber: 8080
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.filters.http.lua
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
          inlineCode: |
            function envoy_on_request(request_handle)
              local body = request_handle:body()
              if body then
                if string.find(body, "' OR ") or string.find(body, "1=1") or string.find(body, "DROP TABLE") then
                  request_handle:respond({[":status"] = "403"}, "Blocked by WAF: SQL injection detected")
                end
              end
            end
  

这个配置做了几件事:

  • 通过 workloadSelector 只作用于 app=orders 的 Pod。
  • 在入站 HTTP 连接管理器的 router 过滤器之前插入一个 Lua 过滤器。
  • Lua 脚本读取请求体,检查是否包含常见的 SQL 注入模式,命中则返回 403。

注意:实际生产环境不要用简单关键词匹配,应当使用专业的正则表达式库或集成 ModSecurity 的规则集。Lua 过滤器更适合快速自定义轻量逻辑。

Mesh Istio:如何验证和调试你的 WAF 规则?

验证与回滚

EnvoyFilter 一旦 apply,会立即生效。建议先在 staging 环境测试:

  • 观察 Envoy 的访问日志(通过 Istio 的 accessLog 配置)确认请求被拦截。
  • 使用 istioctl proxy-config listener [pod] 查看指定 Pod 的 Envoy 监听器配置,确认 Lua 过滤器已注入。
  • 如果规则误拦截了正常请求,可以快速删除 EnvoyFilter 或修改 inlineCode 后重新 apply。

风险与回滚

容易忽略的细节

EnvoyFilter 非常强大,但也容易出错。常见的风险包括:

  • 语法错误:Lua 脚本或 YAML 格式错误可能导致 Envoy 拒绝配置,甚至造成 Sidecar 重启。
  • 性能影响:复杂的 Lua 逻辑或高并发下请求体检查会增加延迟。
  • 误封正常流量:过于激进的规则会阻断合法请求。

回滚方法非常简单:直接 kubectl delete envoyfilter orders-sql-injection-filter,Istio 会自动恢复之前的配置。建议在修改时使用 --dry-run 检查语法,并且逐步灰度(先对少量实例应用)。

总结:Mesh 原生 WAF 是未来趋势

我的处理经验

通过 Istio 的 EnvoyFilter 实现自定义 WAF 并不复杂,它充分利用了服务网格已有的基础设施,避免了在微服务架构中引入额外的反向代理或专用 WAF 设备。对于中小团队来说,这是一种低成本、高灵活性的安全方案。当然,对于复杂的攻击模式(如规则绕过、多阶段攻击),还需要结合专业的 WAF 引擎(如 ModSecurity)或者云厂商的 Web 应用防火墙。但无论如何,掌握 EnvoyFilter 的能力,能让你在服务网格中真正实现“安全即代码”。后续只要定期检查关键指标,Mesh Istio就不会变成维护负担。

延伸阅读