SSL 权限错误:使用 HTTPS 的 Node.js + Let's Encrypt SSL + Apache + 非 root 用户

SSL 权限错误:使用 HTTPS 的 Node.js + Let's Encrypt SSL + Apache + 非 root 用户

我已设置 Node.js 服务器,并尝试在 Apache 上使用我的 Let's Encrypt 证书进行 HTTPS 传输。以下是我设置的相关代码:

var fs = require('fs'),
https = require('https'),
express = require('express'),
options = {
  key: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/privkey.pem'),
  cert: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/fullchain.pem'),
  ca: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/chain.pem')
}, ...

当我尝试启动脚本时,出现此错误:

Error: EACCES: permission denied, open '/etc/letsencrypt/live/www.mysite.com/privkey.pem'

这是因为只有 root 所有者才拥有 SSL 的 Let's Encrypt 目录和文件,目前我在 Apache 上的 30 多个常规网站都在使用 SSL。我正在尝试为一个网站设置一个 Node App。我的 node app.js 项目文件归 mysite1:mysite1 所有,我知道以非 root 用户身份运行 node app 应该更安全(例如“mysite1”)。

什么是使我的 Let's Encrypt HTTPS 与 Node.js 应用程序(在 Apache 上)安全地协同工作的正确方法,而不必授予我的 /etc/letsencrypt 目录 755 权限?

编辑-澄清:

Node.js 和 Apache 并行运行。在我的网站的 virtualHost .conf 文件中,443 DocumentRoot 是 /home/mysite1/mysite1.com ,这就是我安装 Let's Encrypt SSL 的目的。

我的 Node.js 应用程序设置在 /home/mysite1/app 中。在网站上,我使用 socket.io 作为站点范围的聊天室,并且它可以完美地连接/运行,如下所示(如果应用程序以 root 用户身份启动),不需要 ProxyPass:

<script src="//www.mysite1.com:3000/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com:3000');</script>

当我以非 root 用户身份运行应用程序时(出于安全目的),我看到的唯一错误是我的节点应用程序在尝试访问/配置 SSL 文件时出现权限错误。我具体应该怎么做,我不太清楚如何在 Apache“后面”运行它,或者是否有更简单的解决方案?

似乎必须有一个更简单的解决方案,也许 node.js 以 root 身份运行以获取 SSL 数据并在将其交给用户之前使服务器运行,就像 Apache 一样?

编辑2:

根据 Michael 和 ezra-s 的建议,我在 Google 上搜索了一段时间,并做了一些修改,但还是无法正常工作。在 Apache 中,我做了类似的事情:

<VirtualHost *:443>
  ServerAlias mysite1.com
  DocumentRoot /home/mysite1/mysite1.com
  DirectoryIndex index.html index.php
  <Directory /home/mysite1/mysite1.com>
    .. web config stuff
  </Directory>

  ProxyRequests Off
  ProxyPreserveHost On
  ProxyVia Full
  <Proxy *>
    Require all granted
  </Proxy>

  <Location /node>
    ProxyPass http://127.0.0.1:3000
    ProxyPassReverse http://127.0.0.1:3000
  </Location>

  SSLEngine on
  Include /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile /etc/letsencrypt/live/www.letshangout.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/www.letshangout.com/privkey.pem
</VirtualHost>

在我的 node app.js 项目文件中,我删除了 require('https') 和证书选项,并用“http”包替换它并尝试初始化脚本。

在我的网站的一个页面上,我有一些脚本尝试加载 socket.io 并连接到节点应用程序:

<script src="https://www.mysite1.com/node/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com/node/');</script>

当我加载页面时,出现 500 错误,并且脚本无法加载。我应该在 Apache 配置或脚本 URL 中更改什么?我以前从未在节点中使用过代理,这是我的第一个节点应用程序。

解决方案:

我明白了,这是需要涉及 Web 套接字和 JavaScript 的其他事情的组合:

1)用于处理 websockets 的 Apache 配置https://stackoverflow.com/a/41685748/2317571

2)客户端的 JavaScript 套接字连接配置https://stackoverflow.com/questions/22919276/how-to-connect-socket-io-through-a-reverse-proxy

3)(额外提示):感谢 Michael 和 ezra-s 的建议,他们将 node 应用程序置于 Apache 后面,我可以使用 ufw 防火墙并将 node/socket.io 端口 3000 锁定到本地主机 - 向世界开放的端口(和安全漏洞)少了一个。希望这些信息可以帮助其他人。

答案1

1. 在端口上单独运行 Node.js 应用程序。

2. 对其执行反向代理。

笔记:Node.js 应用程序与 Apache 之间的连接将使用 HTTP。但是,它只会在“localhost”级别进行。因此,这样就没问题了。

虚拟主机配置:

<VirtualHost *:443>
        ServerName nodeapp.com
        ServerAdmin webmas@localhost
        DocumentRoot /var/www/nodeapp

        SSLEngine on
        SSLCertificateFile      /path/to/cert
        SSLCertificateKeyFile   /path/to/key


        ProxyRequests off
        ProxyPass "/" "http://127.0.0.1:node_app_port/"
        ProxyPassReverse "/" "http://127.0.0.1:node_app_port/"

        ErrorLog ${APACHE_LOG_DIR}/nodeapp_error.log
        CustomLog ${APACHE_LOG_DIR}/nodeapp_access.log combined

</VirtualHost>

相关内容