没有负载均衡器的 EC2 实例上的 AWS SSL - NodeJS
Posted
技术标签:
【中文标题】没有负载均衡器的 EC2 实例上的 AWS SSL - NodeJS【英文标题】:AWS SSL on EC2 instance without Load Balancer - NodeJS 【发布时间】:2017-03-21 15:27:11 【问题描述】:是否可以在没有load balancer
的情况下运行 EC2 实例,监听 port 443
?我现在正在我的Node.JS
应用程序中尝试,但是当我使用https://
调用页面时它不起作用。但是,如果我将其设置为port 80
,那么http://
一切正常。
我之前使用 load balancer
和 route53
让它工作,但我不想再为 ELB 支付 18 美元/月,尤其是当我只有一台服务器运行时。
感谢您的帮助
【问题讨论】:
【参考方案1】:有可能吗?是的当然。听起来您在 ELB 上安装了 SSL 证书,现在您已经删除了 ELB。您现在必须在 EC2 服务器上安装 SSL 证书。如果没有 ELB 或 CloudFront 分配,您将无法使用 AWS ACM SSL 证书。如果您不想为其中任何一项服务付费,则必须在其他地方获得 SSL 证书。
【讨论】:
我有一个来自 Namecheap 的 SSL 证书,它已上传到 IAM。当我设置 ELB 时,我会选择使用来自 IAM 的现有 SSL 证书。如何在我的 EC2 上安装它?我需要通过 SSH 连接它吗? @MarkB 是的,您必须通过 SSH 连接到服务器并手动安装证书。在这种情况下,您将无法使用 IAM 管理证书。【参考方案2】:你是对的,如果它只是一个实例并且你觉得你不需要为流量的大幅增加做准备,你不应该为 ELB 付费。
从高层次的角度来看,您必须完成以下步骤:
-
安装一个 nginx 服务器来为您的 NodeJS 应用程序提供服务。
在 nginx 服务器上安装您的 SSL 证书。
-- 手动执行此操作,通过 ssh 连接到服务器并按照here 的说明安装证书。
-- 或者在您的应用程序中包含必要的文件(我相信这仅适用于弹性 beanstalk?)这将自动覆盖 nginx 配置文件,如 here 所述。
确保 nginx 正在监听 443 端口(应该已经在上一步完成) 打开EC2服务器的安全组,对应于您希望流量进入服务器的位置(端口80/端口443)【讨论】:
只有一个捕获。当您谈论“您的 SSL 证书”时,您指的是亚马逊证书吗? - 是否可以为此使用亚马逊证书? - 一些消息来源声称亚马逊证书只能用于 AWS 负载均衡器和 aws cloudfront AWS Certificate Manager 可以生成公共和私有证书。公共证书经过签名,以便它们可以被标准浏览器等客户端公开验证。但是不能导出 AWS 公共证书。它们只能绑定到其他 AWS 服务(负载均衡器等)。AWS 生成的私有证书可以导出,但不会公开签名。因此,您可以在客户端和服务器代码中手动安装它们以实现安全通信,但浏览器将无法验证它们。更多细节可以在这里找到:aws.amazon.com/certificate-manager/faqs 只是想添加到这个。当 Let's Encrypt 更新时,它会通过端口 80 进行更新。因此,您还必须保持端口 80 处于打开状态。【参考方案3】:对于我们的项目(很像描述的其他海报),我们使用了这种设置:
-
nginx 作为 80 端口上所有调用的负载均衡器和代理(不直接调用对公众开放的 3000 端口上的 node.js 服务器)
pm2 作为 Node.js(和部署)的流程管理器
用于监控的keymetrics.io
Nodejs v6.9.3 boron/lts(通过 NVM)
带有 WiredTiger 引擎 (Compose.io) 的 Mongodb 3.2
用于托管的 Amazon EC2 实例(Amazon Linux 而非 Ubuntu)
这种设置非常适合我们。在这个设置中,我们能够在不使用亚马逊负载均衡器的情况下设置 SSL。
【讨论】:
但是您是否使用了 AWS 证书?还是您从第三方那里获得了一些? 第三方。我们使用letsencrypt.org【参考方案4】:一旦您有了证书文件,就没有那么难了。你甚至可以在没有 Nginx 的情况下做到这一点。
让我们首先创建一个快速网络服务器
const app = express();
例如,您可以将静态网站放在文件夹中。
const wwwFolder = express.static(path.join(__dirname, '/../www'));
app.use(wwwFolder);
接下来,y你基本上需要阅读你的证书文件
const key = readFileSync(__dirname + '/ssl/privkey.pem', 'utf8');
const cert = readFileSync(__dirname + '/ssl/cert.pem', 'utf8');
const ca = readFileSync(__dirname + '/ssl/chain.pem', 'utf8');
const serverOptions: https.ServerOptions = key, cert, ca ;
最后,您使用这些证书创建一个 https 服务器。
const server = https.createServer(serverOptions, app);
server.listen(httpsPort, () => log.debug("createWebServers", `server is listening on port $httpsPort`));
出于安全原因,可能无法直接在端口 443 上侦听。相反,例如使用 4201 之类的端口,然后使用端口转发。
如果您使用 systemd 启动/停止您的服务,则可以在您的服务配置文件中定义此端口转发。一个简单的解决方案:
[Unit]
Description=my.service
After=network.target
[Service]
Type=simple
TimeoutSec=0
User=ubuntu
PermissionsStartOnly=true
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 4201
ExecStart=/usr/local/bin/node /home/ubuntu/project/server.js
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 4201
Restart=on-failure
[Install]
WantedBy=multi-user.target
有多种方法可以创建和刷新您的证书文件。所以,我不会在这里详细介绍。但最重要的是,您不需要亚马逊证书来完成它。 LetsEncrypt 既免费又简单,而且运行良好。
通常我还会添加一个 http 服务器(没有 HTTPS)并应用重定向。然后我也为此使用端口转发。所以,我在服务文件中添加了第二个端口转发规则。
【讨论】:
以上是关于没有负载均衡器的 EC2 实例上的 AWS SSL - NodeJS的主要内容,如果未能解决你的问题,请参考以下文章
服务器上的 AWS 负载均衡器、静态 IP 和 SSL 终止(不是负载均衡器)