httputil.NewSingleHostReverseProxy本质是转发器而非防火墙,缺乏地址校验、Host头重写、真实IP透传及恶意请求拦截能力;需手动覆盖Director、配置Transport并集成Coraza中间件于路由后/JWT前/代理前位置,协同实现分层防护。

为什么不能直接用 httputil.NewSingleHostReverseProxy 做防火墙网关
它默认不校验目标地址、不重写 Host 头、不透传真实 IP,更不会拦截恶意请求——本质是“转发器”,不是“防火墙”。你把它当网关用,等于在银行金库门口只装了个自动门,却没配安检仪和监控。
常见错误现象包括:502 Bad Gateway 频发、后端日志里全是 127.0.0.1、JWT 校验失败但请求已进下游、SSRF 攻击直达内网数据库。
- 必须手动覆盖
Director函数,否则req.URL.Host和req.Host都指向网关自身 - 不设
Transport的DialContext,就无法阻止访问10.0.0.0/8或file://协议 -
proxy.ErrorHandler只捕获转发失败,对恶意 payload(如 SQL 注入路径)完全无感
如何把 Coraza WAF 插进 Go 网关中间件链
Coraza 不是独立服务,而是一个可嵌入的规则引擎。它能解析 ModSecurity 语法规则,在请求到达反向代理前完成 HTTP 层检测,比如拦截 /api/user?id=1%20UNION%20SELECT%20password%20FROM%20users 这类 SQLi 路径。
关键点在于插入位置:必须在路由匹配之后、身份校验之前、反向代理之前。顺序错了,要么规则不生效,要么误杀合法 JWT。
立即学习“go语言免费学习笔记(深入)”;
- 用
coraza.Middleware(waf)包裹 handler,但别套在最外层——否则会扫描健康检查路径/healthz,拖慢探活 - 规则文件建议从
coraza.conf-recommended起手,禁用SecRuleEngine Off,再逐步启用 OWASP CRS v4 的REQUEST-911-METHOD-ENFORCEMENT等核心规则集 - 注意
SecRequestBodyAccess On—— 若关闭,POST body 不会被扫描,XSS 和 JSON 注入就漏掉了
JWT 校验和防火墙规则怎么协同工作
防火墙(Coraza)管“能不能进”,JWT 校验管“你是谁、能干啥”。两者必须分层协作,不能混在一起做判断。
典型错误是:在 Coraza 规则里硬编码 SecRule REQUEST_HEADERS:Authorization "@contains Bearer",这既绕过签名验证,又无法识别 token 过期或 aud 不匹配。
- Coraza 只负责识别攻击特征(如
args:username含<script></script>),不解析 JWT 内容 - JWT 解析必须用
jwt.ParseWithClaims+ 动态Keyfunc,且强制校验exp(≤15min)、aud(如"gateway-api")、iss - 若 Coraza 拦截成功,返回
403;若 JWT 校验失败,返回401—— 错误码语义要严格区分,下游日志才能准确归因
SSRF 防护必须在网关出向调用前落地
微服务网关常需调用配置中心、认证服务或 webhook 回调,一旦 URL 来自用户输入(如 callback_url 参数),http.Client 就可能被诱导访问 http://127.0.0.1:8080/admin/shutdown。
标准库 http.DefaultClient 完全没防护能力,必须显式构造 client 并注入白名单逻辑。
- 所有出向 client 必须用自定义
http.Transport,其中DialContext调用net.ParseIP+privateIP.IsPrivate()拒绝私有地址 - 域名需实际 DNS 解析后再校验,不能只靠字符串匹配(
localhost.local可能被 DNS 劫持指向内网) - 协议限制为
https,禁用http、file、ftp—— 这些在url.Parse后立刻检查,别等client.Do才报错
真正难的不是写几行校验代码,而是让每个出向调用都走同一套 client 实例——这意味着你要放弃随手 new http.Client() 的习惯,统一从依赖注入容器里取 client。这点容易被忽略,但一旦漏掉一处,整条防线就出现针尖大的洞。


















