如何在AWS EC2中隐藏无需对公网暴露的HTTP端点?
针对EC2 NodeJS服务隐藏指定公网端点的可行方案
以下方案按改造成本从低到高排序,可根据自身架构选型:
方案1:应用层直接做来源IP校验(改造量最小)
直接在/health对应的路由逻辑上加访问来源白名单,只放行信任来源的请求,其他来源请求直接返回404,公网扫描感知不到这个端点存在。
以最常用的Express框架为例,代码逻辑参考:
import ipaddr from 'ipaddr.js'; // 配置允许访问健康检查端点的IP段 const ALLOWED_HEALTH_CIDR = [ '10.0.0.0/16', // 替换为自身VPC内网网段 '192.168.0.0/16', 'x.x.x.x/32' // 替换为公司固定出口IP、内部监控服务IP ]; app.get('/health', (req, res) => { const clientIp = req.ip.replace('::ffff:', ''); // 处理IPv4映射的IPv6地址 const parsedIp = ipaddr.parse(clientIp); // 校验请求来源是否在白名单内 const isAllowed = ALLOWED_HEALTH_CIDR.some(cidr => { const [range, prefix] = cidr.split('/'); return parsedIp.match(ipaddr.parse(range), parseInt(prefix)); }); if (!isAllowed) return res.sendStatus(404); res.json({ status: 'running', timestamp: Date.now() }); });
- 优点:不需要调整现有AWS架构,仅修改少量业务代码即可生效,适配所有部署模式
- 缺点:防护逻辑在应用层生效,若后续代码迭代出逻辑漏洞可能导致权限泄露,IP白名单更新需要重新发布服务
方案2:通过ALB应用负载均衡做路径级流量管控(生产环境首选)
不要直接给EC2实例绑定公网IP对外提供服务,在实例前挂载公网ALB承接所有公网流量:
- EC2实例的安全组仅放通ALB所属安全组的入站访问,公网直接访问EC2的请求会被安全组直接丢弃
- ALB监听器配置默认转发规则,所有公网请求默认转发到后端EC2的NodeJS服务,保证正常业务端点可访问
- 新增一条优先级最高的转发规则:当请求路径匹配
/health时,判断来源IP是否属于信任网段,不属于则直接返回403/404,不向后端EC2转发该请求
- 优点:防护规则在基础设施层生效,和后端业务逻辑完全解耦,就算后端代码出问题公网也无法访问
/health端点,同时可顺便实现SSL卸载、流量限流、DDoS防护等能力,ALB自身的健康检查走内网转发,不需要额外放通公网IP - 缺点:会产生少量ALB服务费用,配置步骤比直接改代码稍多
方案3:拆分端口实现网卡级网络隔离
调整NodeJS服务的监听逻辑,拆分内外网服务分别绑定不同网卡、不同端口:
- 公网服务:监听公网网卡的指定端口(比如3000),挂载所有需要对外暴露的业务端点,安全组放通公网对该端口的入站访问
- 内网服务:仅监听EC2内网网卡的单独端口(比如3001),只挂载
/health这类内部使用的端点,安全组仅放通VPC内网、信任IP对该端口的访问,公网流量从路由层面就无法到达该端口
参考实现代码:
const express = require('express'); // 公网服务 const publicServer = express(); publicServer.get('/api/user', /* 业务逻辑 */); publicServer.get('/api/order', /* 业务逻辑 */); // 绑定0.0.0.0即监听所有网卡,配合安全组放通公网 publicServer.listen(3000, '0.0.0.0'); // 内网服务 const internalServer = express(); internalServer.get('/health', (req, res) => res.json({status: 'ok'})); // 仅绑定EC2内网IP,公网网卡不监听该端口 internalServer.listen(3001, '10.0.1.23'); // 替换为EC2实例的实际内网IP
- 优点:隔离性最强,公网流量从网络层就无法接触到内部端点,不需要写复杂的IP校验逻辑
- 缺点:需要调整服务启动配置,部署时要明确区分内外网卡的绑定关系
方案4:WAF层做路径拦截
如果现有架构已经接入AWS WAF做公网流量防护,直接新增一条WAF规则即可:匹配请求路径为/health且来源IP不在信任白名单内的请求,直接拦截返回403,不需要修改后端代码、也不需要调整负载均衡配置,适合已经部署WAF的场景。
注意:不要用修改
/health路径为复杂随机字符串的方式做防护,这类“靠保密实现安全”的方案完全不可靠,公网路径扫描、端口爆破很容易扫到隐藏的端点,必须做权限或网络层面的硬隔离。
内容的提问来源于stack exchange,提问作者Srikanth Ganesan
相关产品推荐
相关产品推荐

