大虾居

谈笑有鸿儒,往来无白丁。

0%

Nginx默认站点生成空SSL证书

为什么要使用默认站点空证书

开启HTTPS通信可以有效防范中间人攻击,是当前web安全的最佳实践之一。但是在默认情况下
通过IP直接访问443(HTTPS默认端口),nginx会认为是在访问第一个已配置的ssl server,将
请求发送至web节点,并在TLS通讯握手过程中返回该节点对应的证书信息。

这种默认行为会带来以下安全威胁:

服务器响应随意的攻击扫描请求

在公网上充斥各各种扫描攻击程序,他们会大范围的扫描IP和常用端口,对服务器发送无差别的请求。
处理这些请求可能导致额外的安全风险,以及额外的资源损耗。

泄露隐藏于站点防护之后的源站点信息

有时为了防御来自互联网的流量攻击,如DDos攻击,我们会把源站点部署在防御节点之后,即用户请求
先发送到防御服务器,web服务器处理由防御服务器转发来的请求。

这种情况下web服务器不应该直接处理任何流量,也不应该由用户直接访问。处于运维调试等目的,我们
仍然希望https端口可以访问,同时web服务器可以根据某些规则处理请求以便维护人员可以检查服务状态。
此时源站点信息应该是对外保密的,但如果证书信息泄露,可能导致攻击者绕过防御节点直接访问源站点,
造成损失。

如何解决?

通过制定nginx在处理没有制定域名(host)的请求直接返回默认http消息,可以避免信息泄露。

在http端口上的配置如下:

server {
    listen       80  default_server;
    server_name  _;
    return       444;
}

指定server_name为空_可以指定处理所有未匹配的server_name匹配规则的请求。http://nginx.org/en/docs/http/server_names.html

配置SSL端口也是相同的思路,但是SSL配置必须指定SSL证书私钥,因此我们需要生成一个本地的证书,
不带有任何站点信息。

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/conf.d/nginx.key -out /etc/nginx/conf.d/nginx.crt

运行后需要命令行交互输入一些参数,一直Enter使用默认值即可。生成的公钥证书为nginx.crt,私钥证书为nginx.key

按需要将证书文件复制到nginx需要访问的位置。然后配置nginx ssl站点。

server {
    listen              443 ssl default_server;
    server_name         _;
    ssl_certificate     /etc/nginx/conf.d/nginx.crt;
    ssl_certificate_key /etc/nginx/conf.d/nginx.key;
    return              444;
}

可以将以上默认站点http端口和https端口配置在同一个文件中,如/etc/nginx/conf.d/default.conf

server {
    listen              80  default_server;
    server_name         _;
    return              444;
}

server {
    listen              443 ssl default_server;
    server_name         _;
    ssl_certificate     /etc/nginx/conf.d/nginx.crt;
    ssl_certificate_key /etc/nginx/conf.d/nginx.key;
    return              444;
}