如何用 Traefik 的 EncodedCharacters 中间件过滤 URL 编码路径中的危险字符

发布时间:2026/9/9 15:43:26
如何用 Traefik 的 EncodedCharacters 中间件过滤 URL 编码路径中的危险字符 如何用 Traefik 的 EncodedCharacters 中间件过滤 URL 编码路径中的危险字符【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik当后端服务没有完全遵循 RFC 3986、并且会自行解码请求路径中的保留字符时Traefik 与后端可能对同一个 URL 给出不同理解split-view这就可能让路径穿越等攻击借编码字符绕过路由层面的检查。Traefik 的EncodedCharacters中间件就是用来在路由层面解决这个问题它控制请求路径中允许出现哪些含糊的保留字符的 URL 编码形式启用该中间件后默认会拒绝路径中携带这些潜在危险编码字符的请求以增强安全性原文by default, potentially dangerous encoded characters are rejected for security enhancement。本文说明如何为该中间件编写配置、把它挂到某个 HTTP 路由器上并用请求验证过滤是否生效。这个中间件会拒绝哪些请求EncodedCharacters中间件检查的是转义后的请求路径EscapedPath按下面这张配置项表逐项判断表中每个开关默认都是false即默认拒绝对应编码字段控制的编码字符默认值必填allowEncodedSlash编码斜杠%2F和%2ffalse否allowEncodedBackSlash编码反斜杠%5C和%5cfalse否allowEncodedSemicolon编码分号%3B和%3bfalse否allowEncodedPercent编码百分号%25false否allowEncodedQuestionMark编码问号%3F和%3ffalse否allowEncodedHash编码井号%23false否命中被拒绝字符时的行为可以从中间件实现 encoded_characters.go 中确认路径中出现配置所禁止的编码序列如%2F时直接返回400 Bad Request路径末尾残留孤立%这类非法百分号编码同样返回400若所有选项都允许拒绝集为空请求原样放行被拒绝时会在 Debug 级别日志中输出类似Rejecting request because it contains encoded character %2F in the URL path: ...的调试信息可用于确认是哪条规则拦截了请求。注意与入口点级过滤的默认值方向相反在 EntryPoints 的http.encodedCharacters配置中过滤默认是关闭的true表示允许而使用本中间件时默认是拒绝。也就是说中间件适合作为对某条路由单独收紧的路径安全层。配置中间件前提你有一套正在运行的 Traefik且目标应用已经通过 HTTP 路由器暴露文件 provider、Docker/Swarm 标签或 Kubernetes CRD 均可。修改配置前先按 middleware 文档 的提醒确认你的后端是否完全符合 RFC 3986。如果后端会把路径中的编码保留字符解码就应该把这些allow*选项保持为false以避免 split-view、防止路径穿越Request Path 安全文档 中给出了同样的安全建议。方式一动态配置文件TOML在 file provider 加载的动态配置文件中定义中间件并挂到目标路由器上下面的 service 部分只是示例骨架url需替换为你自己的后端地址写法参照仓库集成测试夹具 simple_encoded_chars.toml 中的 whoami 服务[http.routers.app-router] rule Host(app.example.com) service app middlewares [enc-filter] [http.middlewares.enc-filter.encodedCharacters] # 未列出的选项默认为 false拒绝。 # 这里显式写出想拦截的编码字符若想允许某类编码把对应项设为 true。 allowEncodedSlash false allowEncodedBackSlash false [http.services.app.loadBalancer] [[http.services.app.loadBalancer.servers]] url http://127.0.0.1:9000 # 替换为你的后端地址YAML 形式的动态配置等价于http: middlewares: enc-filter: encodedCharacters: allowEncodedSlash: false allowEncodedBackSlash: false方式二Docker / Swarm 标签可选如果你的应用用 Docker 或 Swarm 标签暴露middleware 文档给出的标签写法如下注意标签键全小写labels: - traefik.http.middlewares.test-encodedchars.encodedcharacters.allowencodedslashtrue上例表示允许编码斜杠做过滤收紧时把值设为false或干脆不写该标签默认false。方式三Kubernetes CRD可选apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: test-encodedchars spec: encodedCharacters: allowEncodedSlash: true同样true是放行过滤场景应设为false或省略。验证过滤是否生效验证方法参照仓库集成测试TestEncodedCharactersDifferentEntryPointssimple_test.go的做法用一条带编码斜杠的路径和一条普通路径分别请求看状态码是否符合预期。该测试的实际断言是GET /path%2Fwith%2Fslash在严格过滤的入口上得到400在放行的入口上得到200GET /regular/path在任何入口都得到200。对应到中间件场景可以用 curl 执行--path-as-is用于阻止 curl 自行把%2F归一化成/这样才能真正把编码字符发到 Traefik# 路径中含被拒绝的编码斜杠 %2F预期被中间件拦截返回 400 curl -i --path-as-is -H Host: app.example.com \ http://127.0.0.1:8000/path%2Fwith%2Fslash # 普通路径预期正常代理到后端返回 200 curl -i -H Host: app.example.com \ http://127.0.0.1:8000/regular/path把app.example.com换成你路由器规则里的 Host端口换成你的入口点端口。判断标准与上述测试一致状态码是文档与测试中展示的事实不承诺响应体内容。另外可以把日志级别调到DEBUG被拒请求会留下Rejecting request because it contains encoded character ...的日志便于核对拦截原因。限制与差异说明过滤层级不同入口点级的http.encodedCharacters见 entrypoints.md在整个入口点生效且发生在路径净化path sanitization之前EncodedCharacters中间件则是 per-route 的补充手段。Request Path 文档 明确建议需要按路由配置编码字符过滤时就使用本中间件。默认值方向相反入口点级过滤默认关闭编码字符默认放行中间件默认拒绝。配置时不要拿两边的默认值互相推断。空字符选项差异入口点级比中间件多一个allowEncodedNullCharacter%00选项中间件的配置项表中没有列出它但其实现 encoded_characters.go 中同样会把%00列入拒绝集对应动态配置里的AllowEncodedNullCharacter。如果你的安全清单要求覆盖%00建议同时在入口点级配置该选项。开关语义所有选项都是“允许”语义true 放行与sanitizePath这类“功能开关”方向不同配置时容易弄反。下一步需要在整个入口点统一拦截、而不是只针对某条路由时阅读 EntryPoints 配置文档 中http.encodedCharacters一节YAML / TOML / CLI 三种写法都有。想了解编码字符过滤与路径净化sanitizePath移除..、.、重复斜杠在请求处理中的先后关系参考 Request Path 安全文档。【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考