作为领先的云原生入口控制器和网关代理,Traefik 凭借其出色的可扩展性、简单性和性能,在现代应用架构中扮演着关键角色。而在最新发布的 Traefik v3.0 版本中,引入了 WebAssembly 和 Coraza Web 应用程序防火墙(WAF) Plugin 的强强联手,为网络代理的功能和安全性带来了前所未有的增强。
— 01 —Traefik 自定义 Plugin 开发的前世恩怨
作为 Traefik 项目早期最受欢迎的功能之一,“自定义 Plugin ”的概念自 2017 年开始由用户提出,并源于以下背景和需求:
https://github.com/traefik/traefik/issues/1336?ref=traefik.io
其实,回顾 Traefik 的发展史,在 2016 年正式对外发布后,Traefik 已经成为了一个备受欢迎的边缘代理解决方案,然而,基于各自业务的实际情况,一些用户希望能够更进一步地定制和扩展其功能。希望能够有一种灵活的方式来添加特定的功能或自定义请求处理逻辑,以满足他们特定应用程序的需求。这种需求的提出促使了 Traefik 团队开始构思如何为用户提供一种可扩展的机制来满足这些需求。
于是,自定义 Plugin 的概念应运而生。它允许开发人员编写自己的 Plugin,并将其与 Traefik 集成,从而实现对代理服务的个性化定制。这种机制为用户提供了灵活性和可扩展性,使他们能够根据自己的需求添加特定的功能或修改请求处理流程。
随着时间的推移,自定义 Plugin 成为了 Traefik 项目中最受欢迎的功能之一,为用户提供了无限的可能性,使他们能够根据自己的应用程序需求进行定制,无论是添加新的协议支持、实现高级的路由逻辑还是集成其他的服务和工具。
因此,如何基于 Golang 自定义实现这些 Plugin ,并使其能够丝滑运行便是当前所要解决的问题。比如,尝试将 Go 代码编译成动态库,以使得这些库可以在运行时加载和执行。然而,基于当时 Go 语言的生态不是特别完善不足以支撑自定义 Plugin 的需求,于是在 Traefik 团队的共同努力下实现了一种优雅的 Go 解释器,也就是当前主流的 Yaegi 项目,随着众多技术人员的参与,基于 Yaegi 所开发的中间件 Plugin 在Traefik 生态中成为现实。Yaegi 使许多人能够为他们的上下文开发中间件或提供商。时至今日,我们可以看到通过目录提供的中间件 Plugin 达到一百多个,以及更多私有的 Plugin。
尽管采用了 Yaegi 解释器,使得用 Go 语言编写 Plugin 成为可能,但这种做法对于非 Go 开发人员来说仍有一定门槛。正因如此,一部分社区开发者在 2023 年开始着手探索构建一种全新的 Plugin 引擎,以突破现有 Plugin 体系的语言束缚,进一步扩展 Traefik 的灵活性和可扩展性。
因此,一种与语言无关、安全可靠、高性能等特性,成为了构建 Traefik 新一代 Plugin 体系的不二之选,那便是——WebAssembly 技术。
— 02 —WebAssembly:Traefik v3.0 边缘计算能力的基石
WebAssembly,即 缩写为 “WASM” 作为一种革命性的低级编程模型,以其紧凑的二进制指令格式和接近原生的运行性能,引起了广泛关注。不同于传统的高级编程语言,WebAssembly 而是类似于硬件指令集的底层抽象,为 Web 带来了全新的执行环境。
除了在 Web 浏览器中运行外,WebAssembly 同样可以借助 WebAssembly 系统接口(WASI)规范在操作系统级别的运行时运行,实现对底层系统资源如文件、网络等的访问,从而使得 WASM 成为一种通用的可移植二进制指令格式,促进了云原生、边缘计算、AI 推理等诸多领域的应用实践。
更多关于 WebAssembly 在构建 Traefik Plugin 的内容,大家可参考如下:为什么说 WebAssembly 让 Traefik Plugin 开发走向神坛 ?
接下来,我们主要了解一下在实际的业务场景中, WebAssembly 如何为 Traefik Plugin 开发助力。
对 Traefik 了解的人应该都知道,作为云原生时代领先的反向代理和负载均衡器, Traefik 采用了模块化架构设计,其请求路由管道由 Entrypoint(入口点)、Router (路由器)以及Service(服务)三大核心组件构成。
入口点作为流量的入口,定义了网络层面上进入 Traefik 的监听端点,可以是基于 HTTP、HTTPS、TCP 等多种协议类型。传入的请求经过入口点后,会被路由器所接管并进行智能分发。路由器是整个路由管道的大脑,负责根据配置的规则和策略,将请求精准地转发至能够处理该请求的服务节点。
在请求的路由转发过程中,Traefik 提供了中间件(Middleware)机制,使得请求在被最终定向至服务节点前,可以经过一系列预处理或后处理操作。这些操作涉及访问控制、请求转换、身份验证、速率限制等多种功能,为路由管道添加了极大的灵活性和可扩展性。
接下来,让我们来看看如何为 Traefik 编写 WASM Plugin,这里,我们基于 WebAssembly 编写一个自定义 Plugin。
为了实现该 Plugin,Traefik 提供了多种开发语言选择,包括 Go、C 以及 Rust 等,只要最终代码能够实现统一的 HTTP-Wasm 接口规范即可。在当前示例中,我们使用 Go 语言进行开发,目标主要实现两个核心功能:handleRequest 和 handleResponse,分别负责请求预处理和响应后处理的自定义逻辑。
具体可参考如下:
package main
import (
"encoding/json"
"fmt"
"os"
"github.com/http-wasm/http-wasm-guest-tinygo/handler"
"github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
)
// Config the plugin configuration.
type Config struct {
Headers map[string]string `json:"headers,omitempty"`
}
func main() {
var config Config
err := json.Unmarshal(handler.Host.GetConfig(), &config)
if err != nil {
handler.Host.Log(api.LogLevelError, fmt.Sprintf("Could not load config %v", err))
os.Exit(1)
}
mw, err := New(config)
if err != nil {
handler.Host.Log(api.LogLevelError, fmt.Sprintf("Could not load config %v", err))
os.Exit(1)
}
handler.HandleRequestFn = mw.handleRequest
}
// Demo a Demo plugin.
type Demo struct{}
// New created a new Demo plugin.
func New(config Config) (*Demo, error) {
return &Demo{}, nil
}
func (d Demo) handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
return true, 0
}
然后,将编译的 Plugin 加载到静态配置中,具体可参考如下:
# Static configuration
experimental:
localPlugins:
example:
moduleName: github.com/traefik/plugindemowasm
```
最后,使用我们所构建的新 Plugin 定制一个路由器,具体如下所示:
# Dynamic configuration
http:
routers:
my-router:
rule: host(`demo.localhost`)
service: service-foo
entryPoints:
- web
middlewares:
- my-plugin
services:
service-foo:
loadBalancer:
servers:
- url: http://127.0.0.1:5000
middlewares:
my-plugin:
plugin:
example:
headers:
Foo: Bar
是不是看起来跟其他的差不多一样简单?
— 03 —Coraza:增强Traefik v3.0 安全性的堡垒
什么是 Coraza ?
在应用程序安全防护领域,Coraza 作为一款全新的开源 Web 应用程序防火墙(WAF)项目,凭借其卓越的性能表现和灵活的防护能力,正崭露头角。
作为 OWASP (开放Web应用程序安全项目) 旗下的一员,Coraza 从底层开始采用 Go 语言精心构建,摒弃了传统 WAF 产品臃肿笨重的代码基因,拥有极致的性能优化和资源占用效率。在多项基准测试中,Coraza 展现出远超同类产品的高吞吐量和低延迟特性,可以毫无惧色地应对现代云原生应用程序的高流量挑战。
除了性能之外,Coraza 还以其出色的扩展性和规则定制能力而备受推崇,天生支持 OWASP 核心规则集(Core Rule Set),可以高效阻挡 SQL 注入、XSS、代码执行等多种Web攻击威胁。同时,Coraza 也提供了一套功能强大的域特定语言 SecLang,允许用户根据业务需求,自由定制和扩展安全规则,实现个性化的防护策略。因此,无论是基于标准防护还是定制防护,Coraza 都能游刃有余。
现在,Coraza 项目已作为 Traefik Plugin 生态的一部分,具体可参考如下:
接下来,我们来看一下 Coraza plugin 在Traefik 中的应用,具体如下:
# This config was generated by "mage updateVersion". DO NOT EDIT.
entryPoints:
web:
address: :80
providers:
file:
filename: /etc/traefik/config-dynamic.yaml
experimental:
plugins:
coraza:
moduleName: github.com/jcchavezs/coraza-http-wasm-traefik
version: v0.2.1
然后,我们需要更新动态配置中路由器的中间件部分,具体可参考如下所示:
http:
# ...
middlewares:
waf:
plugin:
coraza:
directives:
- SecRuleEngine On
- SecDebugLog /dev/stdout
- SecDebugLogLevel 9
- SecRule REQUEST_URI "@streq /admin" "id:101,phase:1,log,deny,status:403"
为了验证 Coraza WAF 防火墙的配置规则生效情况,我们可以通过发起简单的测试请求,直观地观测到不同请求模式下的响应结果。
首先,我们使用 curl 命令行工具向本地运行的 Traefik 反向代理发起一个 HEAD 请求,尝试访问/admin路径,具体可参考如下:
curl -I 'http://localhost:8080/admin'
由于之前我们在 Coraza 的规则配置中,专门为 /admin 路径设置了拦截策略,因此,这条请求将触发 WAF 的防护规则生效。我们预期会看到 “HTTP 403 Forbidden” 的响应状态码被返回,表明该请求已被视为恶意访问而被 WAF 成功拦截。
相反,如果我们尝试访问另一个未被防护规则覆盖的普通路径,例如:
curl -I 'http://localhost:8080/anything'
由于该请求路径没有匹配任何 WAF 防护规则,因此预计会得到 “HTTP 200 OK” 的正常响应状态码,请求将被成功代理至后端服务处理。
通过这一对反例的测试,我们可以直观地感受到 Coraza WAF 防护规则的生效情况。当请求匹配特定规则时,将被实时拦截并返回对应的状态码或拒绝访问提示;而对于未匹配规则的普通请求则会放行,确保合法业务流量不受影响。
综上所述,WebAssembly 作为一种革命性的技术,使得在沙箱环境中运行各种编程语言编写的代码成为可能,从而大幅提升了可移植性和安全性。通过与 Coraza 结合使用,Traefik v3.0 可以利用 WASM 的优势,在不影响核心代理性能的前提下,动态加载和卸载安全策略,实现高度定制化和灵活的 WAF 防护。
这一创新组合不仅赋予了 Traefik 更出色的模块化架构和可扩展性,还显著增强了其应对各种Web攻击的能力,从 SQL 注入、跨站脚本攻击到机器行为检测,全面守护应用程序的安全。而 Coraza 作为一款全功能 WAF,其高效、低延迟的特性有助于确保 Traefik 的高性能表现。
凭借 WASM 和 Coraza 两大利器的加持,Traefik v3.0 正努力成为云原生时代下最值得信赖的网络代理和安全防护者,为现代应用程序架构提供无缝整合、动态扩展和全方位保驾护航,助力企业安全可靠地向云原生时代转型。
Reference :
[1] https://github.com/traefik/traefik/issues/1336?ref=traefik.io
[2] https://github.com/corazawaf/coraza
[3] https://traefik.io/blog/traefik-3-deep-dive-into-wasm
Adiós !
··································