【问题标题】:What is the most secure way to use Let's Encrypt certificates with Node.js?在 Node.js 中使用 Let's Encrypt 证书最安全的方法是什么?
【发布时间】:2020-10-18 09:46:44
【问题描述】:

我正在 node.js 上开发一个安全的 Web 服务器,我正在使用带有 https 模块的 Let's Encrypt 证书。 我希望它在 Ubuntu/Debian 机器上运行。 默认情况下,证书和私钥存储在:

/etc/letsencrypt/live/domain.name.example/fullchain.pem
/etc/letsencrypt/live/domain.name.example/privkey.pem

这些文件权限只允许root用户读取,所以问题是node.js服务器无法正常加载使用:

const cert = fs.readFileSync("/etc/letsencrypt/live/domain.name.example/fullchain.pem");
const privKey = fs.readFileSync("/etc/letsencrypt/live/domain.name.example/privkey.pem");

(会抛出权限错误)

我知道的唯一解决方案是:

  1. 以 root 身份运行节点服务器,因此它具有文件权限(不推荐用于节点)。
  2. 将带有sudo cp 的文件复制到本地目录并使用sudo chmod +r 应用权限,以便在每次证书更新后服务器可以访问它们(let's encrypt 不建议复制这些文件,但这是我目前的解决方案)。
  3. 以root身份运行节点,加载证书和私钥,然后将uid更改为具有process.setgid()process.setuid()的非root用户,这将放弃root权限。

我的问题是是否有更好的解决方案来实现这一点,或者其中一种方法就可以了?

【问题讨论】:

  • 致任何对此投反对票的人:您能解释一下如何改进我的问题吗?我已经说明了问题所在并提供了我自己的解决方案。
  • 观察:人们出于各种愚蠢的原因投反对票。为什么要问为什么?问题:您的节点 https 模块是否使用端口 443?问题:您是否决定不使用 nginx(或 apache)作为网络和 nodejs 应用程序之间的反向代理和 TLS 终止?如果您专注于安全性,这可能是一个不错的选择,并且 certbot 在该设置中没有任何文件权限问题。
  • @O.Jones 我不使用端口 433。而 nginx 作为反向代理可能是一个很好的解决方案。我会试试看它是否有效。
  • 我在 apache 后面使用节点,使用 apache 作为反向代理,没有 prlbem。 @ojones TLS 终止是什么意思?在反向代理之后,我从 https 转到 http,然后从 wss 转到 ws。你能详细说明一下吗?谢谢!

标签: node.js linux ssl root lets-encrypt


【解决方案1】:

使用setgid

将目录的组所有权设置为您用于运行 nodejs 的组。例如,如果您的用户和组是itay:staff,请这样说

chgrp -R staff /etc/letsencrypt/live/domain.name.example

然后像这样设置目录权限的setgid位。

chmod 02755 staff /etc/letsencrypt/live/domain.name.example

此后,写入该目录的任何文件都将归该组所有,在此示例中为staff。因此,您的 nodejs 程序将能够毫不费力地读取它们。

【讨论】:

    【解决方案2】:

    根据 O. Jones 的评论,我通过使用 nginx 作为我的 nodejs 服务器的反向代理解决了这个问题。这样nginx处理SSL无权限问题,nodejs只需要运行一个http服务器。

    【讨论】:

      【解决方案3】:

      问题是通过遵循letsencrypt文档(引用B)此处的第二个建议解决的,该文档不需要我创建任何脚本来在证书自动更新时移动或复制文件(我使用--apache安装了我的插件,作为旁注,如果您在虚拟主机中从 http 重定向到 https,当您第一次运行 certbot 时,请使用 --no-redirect 以避免在安装证书期间报告错误)。

      尽管我发现没有必要移动或复制 pem 文件。在 certbot 文档here 中,我没有发现letsencrypt 不建议移动证书,在他们的文档中他们甚至告诉你如何正确地做:

      引用 A:

      如果您想要其符号链接位置的实时证书文件 Certbot 在每次运行时更新以驻留在不同的位置,首先 将它们移动到该位置,然后指定每个 续订配置文件中的四个文件。由于符号链接是 相对链接,您必须遵循此调用 certbot 更新符号链接。

      例如,假设证书的续订配置文件 以前包含以下指令:

      archive_dir = /etc/letsencrypt/archive/example.com
      cert = /etc/letsencrypt/live/example.com/cert.pem
      privkey = /etc/letsencrypt/live/example.com/privkey.pem
      chain = /etc/letsencrypt/live/example.com/chain.pem
      fullchain = /etc/letsencrypt/live/example.com/fullchain.pem
      

      以下命令可用于指定这些文件的位置 位于:

      mv /etc/letsencrypt/archive/example.com /home/user/me/certbot/example_archive
      sed -i 's,/etc/letsencrypt/archive/example.com,/home/user/me/certbot/example_archive,' /etc/letsencrypt/renewal/example.com.conf
      mv /etc/letsencrypt/live/example.com/*.pem /home/user/me/certbot/
      sed -i 's,/etc/letsencrypt/live/example.com,/home/user/me/certbot,g' /etc/letsencrypt/renewal/example.com.conf
      certbot update_symlinks
      

      引用B (我的解决方案,只是因为它是简单的-KISS原则)

      关于权限和组所有权,他们说如下:

      由于历史原因,包含目录是用 0700 的权限意味着证书只能访问 以 root 用户身份运行的服务器。如果你永远不会降级到 旧版本的 Certbot,那么您可以使用 chmod 安全地修复此问题 0755 /etc/letsencrypt/{live,archive}.

      对于在尝试读取之前放弃 root 权限的服务器 私钥文件,您还需要使用 chgrp 和 chmod 0640 来 允许服务器读取 /etc/letsencrypt/live/$domain/privkey.pem。

      这很有趣,它们只有 700 个,仅出于历史原因。他们没有澄清的是 /etc/letsencrypt/live 和 keys 文件夹是 700,而在 20.04 Ubuntu 中,除非您成为 root,否则您甚至看不到该文件夹​​存在,是的 sudo 不起作用,找不到文件夹错误。 -d 或域文件夹是 755 (/etc/letsencrypt/live.domain.com),而 .pem 文件的符号链接本身是 777。

      Letsencrypt 文档说:

      上述目录中的 pem 文件只是符号链接: /etc/letsencrypt/archive 和 /etc/letsencrypt/keys 包含所有 以前的密钥和证书,而 /etc/letsencrypt/live 符号链接 到最新版本

      密钥本身有权限:600 在我的带有 cerbot --apache 证书和安装的 Ubuntu 20.04 系统中,我发现 keys 文件夹有 000x_key-certbot.pem 文件,权限为 600,存档目录有实际的 cert1.pem、chain1.pem、fullchain1.pem 和privkey1.pem 文件,权限分别为:644、644、644 和 600。

      /etc/letsencrypt/archive/domain.com# 文件夹的权限为 755,/etc/letsencrypt/archive 文件夹的权限为 700。 因此,通过隐藏目录并阻止密钥本身来阻止访问。

      【讨论】:

        猜你喜欢
        • 2019-08-05
        • 2022-08-10
        • 1970-01-01
        • 1970-01-01
        • 2016-03-10
        • 2021-06-20
        • 2020-04-25
        • 1970-01-01
        相关资源
        最近更新 更多