[转帖]如何在 NGINX 中安全地分发 SSL 私钥

如何,nginx,安全,分发,ssl,私钥 · 浏览次数 : 0

小编点评

** SSL 密钥保护方法** **1. 密码分发点 (PDP)** - 创建密码分发点 (PDP),通过 HTTPS 服务交付密码列表。 - 使用用户名和密码进行身份验证。 **2. 硬件安全模块 (HSM)** - 远程存储私钥在 HSM 中,按需暴露执行密钥操作。 **3. HashiCorp Vault** - 使用 HashiCorp Vault 保护 NGINX 中的 SSL 私钥。 - 通过从 HashiCorp Vault 生成临时 SSL 密钥并将其存储在 NGINX Plus 内存键值存储中,绕过存储在磁盘上的 SSL 密钥。 **4. NGINX Plus 键值存储** - 使用 NGINX Plus 键值存储保护来自 HashiCorp Vault 的临时 SSL 密钥。 - 通过从 HashiCorp Vault 生成临时 SSL 密钥并将其存储在 NGINX Plus 内存键值存储中,绕过存储在磁盘上的 SSL 密钥。 **5. 密钥保护 API** - 使用 NGINX Plus 键值存储保护来自 HashiCorp Vault 的临时 SSL 密钥。 - 通过 API 在 NGINX Plus 内存中存储和访问 SSL 密钥。

正文

https://my.oschina.net/u/5246775/blog/7812621

 

 

原文作者:Owen Garrett of F5

原文链接:如何在 NGINX 中安全地分发 SSL 私钥

转载来源:NGINX 官方网站


NGINX 唯一中文官方社区 ,尽在 nginx.org.cn

本文介绍了 SSL 加密网站使用 NGINX 时可采用的几种安全分发 SSL 私钥的方法。本文讨论了:

对于多数的部署场景,标准方法就能够满足需求。本文还介绍了两种更复杂的方法,可防止攻击者通过其他方式获得 SSL 私钥。有关更多相关技术的探讨,请参阅以下博文:

  • 使用诸如 HashiCorp Vault 等第三方密钥存储安全地分发密码
  • 自动将证书从 Vault 提供到 NGINX Plus 键值存储,从而确保私钥材料永远不会存储在磁盘上

本文介绍的方法适用于需要自行管理密钥并创建安全密钥分发策略的用户。对于那些运行中的 NGINX 环境已经集成了密钥存储(例如 Kubernetes)的用户来说,无需使用这些方法。

本文适用于 NGINX 开源版和 NGINX Plus。为了便于阅读,我们把两者统称为 NGINX

编者按 —— 本文是有关如何在 NGINX 中保护 SSL 私钥的系列博文的第一篇。另请参阅本系列博文的其他文章:

为什么要保护 SSL 私钥?

SSL/TLS 往往被用于对网络交易的完整性进行身份验证、加密和验证。网站通过由证书颁发机构 (CA) 签名的公共证书表明自身身份,并通过使用相应的私钥(必须保密)进行计算,证明其拥有的证书。

如果私钥遭到泄露(披露给另一个实体),则面临两大风险。

  • 风险 1:伪装。窃取到私钥的攻击者可劫持网络流量,然后发起中间人攻击。此类攻击会捕获并解密所有流量,也可能会在客户或网站毫无察觉的情况下篡改流量。
  • 风险 2:解密。窃取到私钥并且已将网络流量记录下来的攻击者,可离线解密网络流量。值得一提的是,无法向使用完全向前保密 (PFS) 密钥的连接发起此类攻击。

如果私钥遭到泄露,您唯一的找回方式就是与 CA 中心联系,申请撤销证书;然后必须依靠客户来检查并执行撤销状态。

此外,建议使用有效期较短的证书,(例如 Let’s Encrypt 证书的有效期为 90 天)。证书即将到期时,您需要生成一个新的私钥,并从 CA 获得新证书。一旦私钥遭到泄露,这可帮助您降低风险。

NGINX 安全边界

哪些人员和流程可以访问 NGINX 中的 SSL 私钥?

首先,拥有 root 权限的任何用户都能够接入运行 NGINX 的服务器,并读取和使用 NGINX 本身所使用的全部资源。例如,通过一些已知方法从运行中的进程所使用内存中提取 SSL 私钥。

因此,不管私钥如何存储和分发,都无法保护私钥免遭在主机服务器上拥有 root 权限的攻击者的窃取。

其次,凡是能修改和提交 NGINX 配置的用户,都能通过多种方式使用该配置,例如开启对内部服务的代理访问、绕过身份验证措施等。这些用户可修改 NGINX 配置以获得对服务器的 root 权限(或同等权限),尽管 SELinux 和 AppArmor 等工具可帮助降低此类风险。

因此,通常无法保护私钥免遭可修改和提交 NGINX 配置的攻击者的窃取。

幸运的是,只要部署周密的安全流程,组织就可以加大攻击者获取 root 权限或修改 NGINX 配置的难度。

但是,权限较低的攻击者还可通过另外两种方式获取私钥:

  • 用户可能有合法的理由需要查看 NGINX 配置,或者可能获取到对配置数据库或备份的访问权限。NGINX 私钥通常存储在配置中。
  • 用户可通过管理程序或系统备份获得对 NGINX 服务器文件系统的访问权限。存储在文件系统上的任何数据,包括私钥材料,都存在被访问的可能性。

下文所述流程能够拦截这两种攻击方法。

标准 NGINX 配置

首先,让我们来看一下包含 SSL/TLS 的典型 NGINX 配置:

server {
    listen 443 ssl;

    server_name a.dev0; 

    ssl_certificate         ssl/a.dev0.crt;
    ssl_certificate_key     ssl/a.dev0.key;

    location / {
        return 200 "Hello from service A\n";
    }
}

SSL 公共证书 (a.dev0.crt) 和私钥 (a.dev0.key) 存储在位于 /etc/nginx/ssl/ 的文件系统中。该私钥仅可由 NGINX 主进程读取,通常以 root 身份或权限运行,因此可为其设置最严格的访问权限,如下所示。

root@web1:/etc/nginx/ssl# ls -l a.dev0.key
-r-------- 1 root root 1766 Aug 15 16:32 a.dev0.key

私钥必须始终可用;每当启动 NGINX 软件、重载配置或执行语句检查时 (nginx -t),NGINX 主进程就会读取私钥。

有关 SSL/TLS 配置的更多信息,请参阅《NGINX Plus 管理指南》

标准配置的安全隐患

如上所述,当攻击者已窃取到运行 NGINX 的容器、虚拟机或服务器的 root 权限,攻击者就可以读取 SSL 私钥。

加密 SSL 私钥

NGINX 支持使用诸如 AES256 等安全算法加密私钥:

root@web1:/etc/nginx/ssl# mv a.dev0.key a.dev0.key.plain
root@web1:/etc/nginx/ssl# openssl rsa -aes256 -in a.dev0.key.plain -out a.dev0.key
writing RSA key
Enter PEM pass phrase: secure password
Verifying - Enter PEM pass phrase: secure password again

然后,当启动 NGINX 、重新加载或测试 NGINX 配置时,NGINX 就会交互请求解密密码:

root@web1:/etc/nginx# nginx -t
Enter PEM pass phrase: secure password
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

使用 SSL 密码文件

以交互的方式输入密码很不方便,且难以自动化,但是您可以通过 ssl_password_file 命令将 NGINX 配置为使用此命令所指定的单独文件中的密码列表。当 NGINX 需要读取私钥时,它会尝试使用该文件中的每个密码解密密钥。如果密码都无效,NGINX 将拒绝启动。

ssl_password_file /var/lib/nginx/ssl_passwords.txt;

ssl_password_file 必须独立于配置分发,并且仅可供 root 用户读取。您可将其视为放置在可信服务器上的授权令牌。NGINX 在使用授权令牌的服务器上运行时,才能解密私钥。

将加密密钥存储在单独文件中的安全隐患

该方法对攻击者而言,其仅仅获取到单独的 NGINX 配置是无用的,从而减少攻击面。攻击者还必须获取 ssl_password_file 中的内容。

如果攻击者获取了 ssl_password_file 所在文件系统的 root 权限(例如从备份中或通过主机系统),攻击者就可以读取文件并使用密码解密 SSL 私钥。

可通过将 ssl_password_file 存储在 RAM 磁盘或 tmpfs 中,降低该风险。外部攻击者通常不太能够访问此类存储(例如在服务器重启时会被清除),并且可以将此类存储排除在系统备份范围之外。您需要确保在系统启动时初始化密码文件。

更安全地分发 SSL 密码列表

下述流程描述了一种从中央分发点更安全地分发 SSL 密码列表的方法。

每当 NGINX 需要解密 SSL 密钥时,它就会向中央分发点发起请求并使用密码,但不会将密码存储在本地磁盘上。为了使用中央密码服务器验证自身身份,NGINX 实例会用到令牌,您可以随时撤消该令牌,以切断对密码的访问。

创建中央密码分发点

首先,创建密码分发点 (PDP)。一个简单的实施方法就是通过 HTTPS 服务来交付密码列表,并使用用户名和密码进行身份验证:

$ curl -u dev0:mypassword https://pdpserver.local/ssl_passwords.txt
password1
password2
...

然后,在 PDP 上通过按需添加或删除身份验证令牌,来启用或撤销访问权限。可利用 Web 服务器(例如 NGINX )实施密码分发服务器,并视情况使用任何类型的身份验证令牌。

接下来,需要将 NGINX 设置为从 PDP 检索密码。首先,使用下列内容创建名为 connector.sh 的 shell 脚本:

#!/bin/sh

# Usage: connector.sh   

CONNECTOR=$1
CREDS=$2
PDP_URL=$3

[ -e $CONNECTOR ] && /bin/rm -f $CONNECTOR

mkfifo $CONNECTOR; chmod 600 $CONNECTOR

while true; do
    curl -s -u $CREDS -k $PDP_URL -o $CONNECTOR
done

该脚本需要作为后台进程运行,调用代码如下所示:

root@web1:~# ./connector.sh /var/run/nginx/ssl_passwords \
dev0:mypassword https://pdpserver.local/ssl_passwords.txt &

该连接器连接到指定的本地路径 (/var/run/nginx/ssl_passwords),并使用 ssl_password_file 指令将 NGINX 配置为访问该路径:

ssl_password_file /var/run/nginx/ssl_passwords;

通过读取连接器路径,测试连接器:

root@web1:~# cat /var/run/nginx/ssl_passwords
password1
password2
...

验证 NGINX 能否读取密码并解密 SSL 密钥:

root@web1:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

可使用中央 PDP 方法安全地分发 NGINX 通常从磁盘上需要读取的任何资源,例如单独的私钥或其他敏感数据。

PDP 的安全隐患

与 SSL 密码存储在磁盘上的方法相对比,该解决方案有几个好处:

  • SSL 密码从不存储在服务器的文件系统上,因此即便攻击者能够访问文件系统,也无法直接访问 SSL 密码。
  • 从中央接入点分发密码,这可简化监控和审计。
  • 可集中控制对各台服务器的访问。举例来说,一旦服务器被淘汰,就可以撤销其访问令牌。

请注意,可以访问文件系统的用户或许可以提取用于访问 PDP 的凭证。因此,撤销不再需要的凭证至关重要。

总结

下列几种方法可保护 SSL 私钥免遭泄露,并且安全性和复杂性越来越高:

  • 对于大多数组织,对运行 NGINX 的环境严格限制访问权限,使得未经授权的用户无法获得 root 权限,或查看 NGINX 配置。
  • 而在某些环境中,可能无法完全限制对 NGINX 配置的访问权限,则可以使用 SSL 密码文件。
  • 在少数情况下,组织可能希望永远不将密钥和密码存储在磁盘上。这时,可通过密码分发点流程实现这一点。

本系列中的其他文章介绍了更多 SSL 密钥保护方法:

与[转帖]如何在 NGINX 中安全地分发 SSL 私钥相似的内容:

[转帖]如何在 NGINX 中安全地分发 SSL 私钥

https://my.oschina.net/u/5246775/blog/7812621 原文作者:Owen Garrett of F5 原文链接:如何在 NGINX 中安全地分发 SSL 私钥 转载来源:NGINX 官方网站 NGINX 唯一中文官方社区 ,尽在 nginx.org.cn 本文介

[转帖]Nginx禁止ip访问或非法域名访问

https://www.jb51.net/article/243661.htm 这篇文章主要介绍了Nginx禁止ip访问或非法域名访问,需要的朋友可以参考下 在生产环境中,为了网站的安全访问,需要Nginx禁止一些非法访问,如恶意域名解析,直接使用IP访问网站。下面记录一些常用的配置示例: 1)禁止

[转帖]k8s部署-22-yaml文件怎么写,规则是什么,在k8s中分别有什么含义

https://www.jianshu.com/p/ba5e3d9ecc1e 在前面的文章中,我们使用了较多的yaml文件,例如测试kubespary方式搭建的集群可用性,亦或者前文中我们搭建ingress-nginx的时候也是用了yaml文件,那么k8s中的yaml文件到底该如何来写,针对k8s中

[转帖]查看请求在nginx中消耗的时间

需求:查看请求在nginx中消耗的时间,不包括程序响应时间。 1.声明日志的格式,在nginx配置文件nginx.conf里的http下添加如下内容: log_format test '$remote_addr - $remote_user [$time_local] "$request" ' '$

[转帖]将nginx.conf文件的内容拆分成多个

nginx的如果有多个server模块都配置在同一个nginx.conf文件会显得比较臃肿,后续维护起来也会比较困难,所以可以将内容写入到多个配置文件中然后在nginx.conf文件中通过include命令引入。 1.nginx.conf配置文件内容 user nginx; worker_proce

[转帖]Nginx服务器性能调优

Worker 相关worker设置比较简单,只需要设置正确的数量。 Worker Processes 如果您的站点流量不大,Nginx,数据库和Web应用程序都运行在同一台服务器上。则在/etc/nginx/nginx.conf中,设置worker_processes 1; 如果您的站点流量比较大或

[转帖]nginx中用到的kill命令

1、kill命令 1.1、kill命令简介 我们都知道,想要在Linux中终止一个进程有两种方式,如果是前台进程可以使用Ctrl+C键进行终止;如果是后台进程,那么需要使用kill命令来终止。(其实Ctrl+C也是kill命令)。 kill命令的格式是: kill -signal pid 其中 pi

[转帖]Nginx Ingress 高并发实践

概述 Nginx Ingress Controller 基于 Nginx 实现了 Kubernetes Ingress API,Nginx 是公认的高性能网关,但如果不对其进行一些参数调优,就不能充分发挥出高性能的优势。之前我们在 Nginx Ingress on TKE 部署最佳实践 一文中讲了

[转帖]k8s中nginx工作线程的问题

https://www.cnblogs.com/lizexiong/p/15198863.html 本次环境背景信息为,需要在k8s里面跑一些前端界面,所以在pod容器中还是使用到了nginx,但是发现,如果nginx worker_processes参数为auto,pod容器会读取node节点的c

[转帖]Nginx 禁止直接访问目录或文件的操作方法

https://www.jb51.net/article/266355.htm 前言 Nginx 默认是不允许列出整个目录的。 如需此功能,打开 nginx.conf 文件或你要启用目录浏览虚拟主机的配置文件,在 location server 或 http 段中加入 1 autoindex on;