从 Nginx 反向代理到阿里云 ESA:一次降本增效的架构升级实践

29 阅读9分钟

从 Nginx 反向代理到阿里云 ESA:一次降本增效的架构升级实践

一、背景:一个非标网络环境的无奈

我的项目是一个微信小程序后端服务,部署在内网服务器上。服务器通过电信家宽上网,虽然有一个电信公网 IP,但运营商毫不意外地封禁了 80 和 443 端口——也就是说,这台机器没法直接对外提供 HTTP/HTTPS 服务。而微信小程序强制要求所有接口走 https://,这就很尴尬了——服务在本地跑得好好的,外网就是访问不了。

最初的方案:阿里云 ECS 做 Nginx 反向代理

当时的思路很直接:在内网服务前面加一层跳板。

用户(微信小程序)
    │  https://api.xxx.com:443
    ▼
阿里云 ECS(有 80/443,做 HTTPS 终结)
    │  http://电信公网IP:8080(家宽同样没 80/443,只能走非标端口)
    ▼
内网服务器(Spring Boot :8080

在阿里云另开一台 ECS,装 Nginx,配置 SSL 证书,把所有请求反向代理到内网服务器的电信公网 IP 的 8080 端口(路由器做了端口转发到内网机器)。注意,ECS 回源时面对的也是那台被运营商封了 80/443 的家宽机器,所以只能走 8080 这种非标端口。

这个方案跑了一年多,能用,但有几个明显的痛点:

  1. 成本高:一台 ECS 一年下来几百上千块,就为了跑个 Nginx 转发,太浪费了。
  2. 多一层维护:Nginx 配置、证书续期、系统安全补丁、磁盘监控……这些都是运维成本。
  3. 单点故障:ECS 挂了整个服务就不可用,除非再加钱做高可用。
  4. 延迟增加:多一跳就是多几十毫秒,对用户体验多少有影响。

重新思考:能不能把这一层"云化"?

本质上我要做的事情很简单:

  • 对外暴露 https://api.xxx.com:443(需要 443 端口和 SSL 证书)
  • 把请求转发到 http://电信公网IP:8080(家宽没有 80/443,只能走非标端口)

也就是说,ECS 和 ESA 回源时面对的是同一个问题——目标机器都没有 80/443。那何必为了一层 HTTPS 终结专门养一台云服务器?这不就是 CDN/边缘加速的典型场景吗?于是我开始调研阿里云的边缘安全加速产品 ESA(Edge Security Acceleration)。


二、什么是阿里云 ESA?

ESA(Edge Security Acceleration)是阿里云推出的边缘安全加速一体化产品,你可以把它理解成 CDN + DDoS 防护 + WAF + 边缘计算 的集合体。

对我来说最香的一点是:ESA 天然支持自定义回源端口。这意味着:

用户访问 https://api.xxx.com:443
    →  ESA 边缘节点(HTTPS 终结 + 证书管理)
    →  http://电信公网IP:8080(走公网到路由器 → 端口转发 → 内网 Nginx)127.0.0.1:后端端口(内网转发到 Spring Boot)

完美绕过了运营商对 80/443 的封禁——ESA 边缘节点也是通过公网打到我那台家宽机器的 :8080,跟 ECS 回源路径完全一样。区别只是我不需要自己维护那台云服务器了。

更关键的是,ESA 有免费版套餐,对于小流量项目来说完全够用——这意味着一分钱不花就能替代掉 ECS 的角色。


三、整体架构对比

旧架构(ECS Nginx 反代)

在这里插入图片描述

新架构(阿里云 ESA)

在这里插入图片描述

📌 关键点:两个方案回源时打的是同一个电信公网 IP,都只能用 :8080 非标端口——家宽 80/443 被运营商封了,跟前面用 ECS 还是 ESA 无关。区别仅在于 HTTPS 终结这一层是自建 ECS 还是用 ESA 边缘节点。

一眼看出区别:少了一台服务器。ESA 把证书管理、HTTPS 终结、DDoS 防护、全球加速全部在边缘节点完成,我只管好自己内网那台机器的 8080 端口就行。


四、完整迁移步骤

下面是我从零开始配置 ESA 的完整过程,记录备忘,也希望能帮到同场景的朋友。

约定信息(请替换为你自己的):

  • 加速域名:api.xxx.com
  • 内网公网 IP:X.X.X.X
  • 内网服务端口:8080(HTTP,内网不配置 SSL)
  • 接入方式:CNAME 接入(强烈推荐,别选 NS)
  • 套餐:免费版

步骤 1:添加站点 & 域名验证

  1. 登录阿里云控制台 → 搜索【边缘安全加速 ESA】→【站点管理】→【新增站点】
  2. 站点域名:填写 api.xxx.com
  3. 接入方式:选择 CNAME 接入
  4. 加速区域:中国大陆(域名需已备案)
  5. 套餐:免费版
  6. 域名所有权验证:推荐 TXT 记录验证,去你的域名 DNS 后台添加 TXT 解析后点验证

⚠️ 千万别选 NS 接入!NS 会接管全部域名的 DNS 解析,万一配错影响整个域名,风险极高。

步骤 2:添加 DNS 记录(配置源站)

验证通过后进入站点详情页 → 左侧【DNS】→【记录】→【添加记录】:

参数
主机记录api
记录类型A 记录
代理状态开启代理加速(必须开!否则无防护无加速)
记录值/源站X.X.X.X(你的内网公网 IP)
TTL默认自动

步骤 3:【最关键】配置回源规则——自定义回源端口 8080

这是整个配置的核心,ESA 默认回源端口是 80,不配这一步直接超时。

左侧【规则】→【回源规则】→【新增规则】:

  1. 规则名称api回源内网8080

  2. 匹配条件: http.host eq "api.xxx.com"

  3. 执行动作

    • 回源 HOST:$host
    • 回源协议:HTTP(内网只开 http,不用 https)
    • HTTP 回源端口:8080
    • HTTPS 回源端口:留空

保存,优先级保持默认。

📌 数据流:用户 → https://api.xxx.com:443(ESA 边缘,HTTPS 终结)→ http://X.X.X.X:8080(电信公网 IP,路由器端口转发至内网 Nginx)→ 127.0.0.1:后端端口(Spring Boot)

步骤 4:配置 HTTPS 证书

左侧【SSL/TLS】→【边缘证书】:

  1. 证书来源:阿里云免费 DV 证书
  2. 选择域名 api.xxx.com,一键申请
  3. 证书下发后开启【强制 HTTPS 跳转】(301)

免费的 DV 证书一年有效期,到期前 ESA 应该会自动续期,比之前手动在 Nginx 上用 acme.sh 续期省心多了。

步骤 5:缓存规则——API 必须绕过缓存!

这是最容易踩的坑。API 接口和图片上传请求绝对不能缓存,否则会出现旧数据返回、提交异常等问题。

左侧【规则】→【缓存规则】→【新增规则】:

  • 规则名称:动态API禁止缓存
  • 匹配条件:http.host eq "api.xxx.com"
  • 执行动作:绕过缓存(Bypass Cache)

所有 API 请求实时回源,不经过 CDN 缓存。

💡 如果后续添加了静态资源(如 /assets/ 路径的图片、JS),可以单独创建缓存规则来加速;当前全是 API 的话全局绕过最简单省心。

步骤 6:【安全核心】回源签名鉴权

这个非常重要!内网服务的 8080 端口是对公网开放的,不做防护的话,任何人扫描到 IP:8080 就能绕过 ESA 直接访问你的后端。

ESA 提供了回源签名鉴权机制:

左侧【访问控制】→【回源鉴权】:

  1. 鉴权方式:回源签名鉴权
  2. 点击生成密钥,保存好鉴权密钥
  3. 开启开关
配套:内网 Nginx 增加签名校验

你内网那台机器上还是需要一个轻量的 Nginx(或者直接在 Spring Boot 里加 Filter),用来校验 ESA 回源请求的签名。参考配置:

server {
    listen 8080;
    server_name api.xxx.com;

    # ESA 回源鉴权密钥,替换成你控制台生成的密钥
    set $esa_secret "你的ESA回源鉴权密钥";

    location / {
        # 校验 ESA 签名 — 没有签名参数的直接返回 403
        if ($arg_esa_sign = "") {
            return 403;
        }

        # 透传真实客户端 IP(日志、风控需要)
        proxy_set_header X-Real-IP $http_x_forwarded_for;
        proxy_set_header X-Forwarded-For $http_x_forwarded_for;
        proxy_set_header Host $host;

        proxy_pass http://127.0.0.1:你的后端端口;
    }
}

🔐 原理:所有 ESA 回源请求自动带上 esa_sign 参数,经过 HMAC 签名;直接访问 IP:8080 不带签名,直接返回 403。双重防护,安全性拉满。

步骤 7:切 DNS——正式迁移流量

回到你的域名 DNS 后台:

  1. 找到 api.xxx.com 原有的 A 记录,删除
  2. 新建一条 CNAME 记录:
    • 主机记录:api
    • 记录类型:CNAME
    • 记录值:ESA 控制台给出的 CNAME 地址(类似 xxx.esa.aliyun.com
    • TTL:10 分钟

等待 5~30 分钟 DNS 生效。

步骤 8:防火墙收尾

  1. 确保内网防火墙放行 8080 端口入站
  2. 不要把 8080 对全公网开放,配合步骤 6 的 Nginx 签名鉴权做防护
  3. 不建议手动维护阿里云回源 IP 白名单(ESA 边缘节点 IP 是动态的),用签名鉴权就够了

五、上线验证清单

切流量前一定逐条验证:

#验证项预期结果
1修改本机 host(X.X.X.X api.xxx.com)直连测试内网服务正常响应
2删掉 host,浏览器访问 https://api.xxx.com正常打开,证书有效
3小程序测试登录、上传图片等核心接口功能正常
4直接访问 http://内网公网IP:8080返回 403(签名鉴权生效)

这 4 条全部通过,说明迁移成功。此时就可以把原来那台 ECS Nginx 反代机器关机观察一周,确认稳定后直接释放


六、成本对比:实打实省了多少

项目旧方案(ECS Nginx)新方案(ESA)
计算资源ECS 1核1G ~¥800/年ESA 免费版 ¥0
SSL 证书免费(Let's Encrypt / acme.sh)免费 DV 证书,自动续期
带宽ECS 按带宽计费ESA 免费版含一定流量
DDoS 防护无(ECS 被打直接挂)内置,免费版就有基础防护
运维成本Nginx 配置、证书续期、安全补丁近乎为零
年费总计~¥800-1000¥0

一年省下小一千块,对于个人项目或小团队来说不少了。流量大了之后升级 ESA 套餐的费用也远低于同等规格的 ECS。


七、我踩过的坑(请务必注意)

  1. ❌ 回源端口忘记填 8080 ESA 默认回源端口是 80。不配回源规则 → 请求到了内网 80 端口 → 连接超时。这一步卡了我半小时。

  2. ❌ 缓存没设置绕过 上线后小程序偶尔拉到旧数据,排查半天才发现是 ESA 默认缓存了 API 响应。所有 API 必须设置 Bypass Cache

  3. ❌ 没开启回源签名鉴权 一开始图省事没配签名鉴权,后来用 curl http://IP:8080 一试直接通了——这意味着任何人都能绕过 ESA 直连后端。赶紧补上。

  4. ❌ DNS 接入方式差点选 NS NS 接入会接管整个域名的解析,一旦出错整个域名都受影响。CNAME 接入只影响你指定的那个子域名,风险可控。

  5. ❌ 内网 Nginx 配了 SSL,但 ESA 用 HTTP 回源 内网服务和 ESA 之间走内网 HTTP 就够了,SSL 终结在 ESA 边缘。内网配了 SSL 反而导致回源握手失败。


八、总结

这次架构升级的核心思路就是:把能用云服务替代的基础设施"外包"出去

原来需要自己买服务器、装 Nginx、配 SSL、做安全加固的事情,现在一个 ESA 免费套餐全搞定了,而且做得更好——自带全球加速节点、DDoS 防护、自动证书管理。回源链路本身没变,打的是同一台电信家宽机器的 :8080,变的只是前面那层 HTTPS 终结是谁来做——从自建 ECS 换成了 ESA 边缘节点。我只用关注自己的业务代码,这一层转发的事交给专业的边缘加速产品。

如果你的场景和我的类似(家宽/内网服务器 + 运营商封端口 + 需要 HTTPS),强烈建议试试 ESA 这个方案,免费、省心、还更安全。


本文基于实际项目迁移经验整理,项目为微信小程序虾苗计数系统,后端 Spring Boot,部署于内网服务器,通过阿里云 ESA 对外提供服务。