EC2实例置于ALB后无法连接Stripe的问题解决咨询
我正在部署集成Stripe支付功能的NodeJS后端。前端用户点击Checkout按钮时,后端API会调用Stripe SDK创建结账会话,用户将被重定向至Stripe结账页面,本地测试一切正常。
但在ALB后的EC2实例上通过ECS运行容器服务时,前端可正常调用后端多数接口,却无法连接Stripe。点击结账按钮后无响应,等待一段时间后查看任务日志,得到如下错误:
[Nest] 28 - 06/01/2024, 4:54:13 AM ERROR [ExceptionsHandler] Request aborted due to timeout being reached (80000ms) Error: Request aborted due to timeout being reached (80000ms) at /app/node_modules/stripe/cjs/RequestSender.js:326:37 at processTicksAndRejections (node:internal/process/task_queues:95:5)
移除负载均衡器,仅保留运行在5000端口的EC2实例,将任务定义的网络模式从awsvpc改为bridge并做静态端口映射后,运行单个任务,前端可正常访问结账接口。问题仅出现在ECS服务部署时EC2实例置于ALB后的场景。
EC2实例默认放在公有子网以拉取ECR镜像,推测问题与安全组配置有关,当前安全组配置如下:
ALB安全组
入站规则
[允许来自0.0.0.0/0的HTTP(80)和HTTPS(443)流量]
出站规则
[允许所有流量(0.0.0.0/0)到所有端口]
EC2实例安全组
入站规则
[允许来自ALB安全组的所有端口流量,以及来自0.0.0.0/0的SSH(22)流量]
出站规则
[允许所有流量(0.0.0.0/0)到所有端口]
请问在EC2实例置于ALB的情况下,该如何解决此问题?
检查ECS任务的安全组配置
使用awsvpc网络模式时,ECS任务会获得独立的弹性网络接口(ENI),它的网络权限由单独的安全组控制,并非直接复用EC2实例的安全组。你需要给ECS任务的安全组添加出站规则:允许HTTPS(443)流量访问Stripe API地址(api.stripe.com),或者直接放行所有443端口的出站流量。之前用bridge模式时任务复用EC2的网络栈,所以能正常访问,切换到awsvpc后必须单独配置任务的安全组。验证公有子网的路由表
确保ECS任务所在的公有子网路由表已关联互联网网关(IGW),这样任务才能直接访问外部的Stripe API。如果子网没有绑定IGW,哪怕EC2实例在公有子网,awsvpc模式的任务也无法出站访问公网。直接测试容器到Stripe的连通性
进入ECS容器内部,执行curl https://api.stripe.com/v1/payment_intents命令,直接测试与Stripe API的连通性。如果命令超时,说明是网络层面的问题;如果能得到Stripe的返回(比如权限错误),则需要检查Stripe SDK的密钥或配置。排查VPC网络ACL规则
网络ACL是无状态的,要确保任务所在子网的ACL同时允许入站和出站的443端口流量,避免ACL阻断了Stripe API的响应包。确认Stripe SDK的代理设置(如有)
如果你的VPC需要通过NAT网关或代理访问公网,要在Stripe SDK初始化时指定代理地址,示例代码:const stripe = require('stripe')('your_secret_key', { httpClient: require('stripe').createHttpClient({ proxy: 'http://your-proxy-address:port', }), });
内容的提问来源于stack exchange,提问作者Alpha Tran

