Nginx 安全优化

目录

            前言
            1、使用 SSL/TLS 证书
            2、使用安全密钥交换机制
            3、禁用旧的 SSL/TLS 协议
            4、禁用 SSL/TLS 弱密码套件
            5、禁用不需要的 HTTP 方法
            6、防止缓冲区溢出攻击
            7、防止 CSP、XSS 攻击
            8、防止 Click-jacking 劫持
            9、禁用内容嗅探
            10、图片防盗链
            11、启用 HSTS 功能
            12、仅允许通过域名访问
            13、禁止自动用户代理
            14、防止服务器信息泄露
            15、升级 Nginx 版本
                    附件

前言

作为混迹于 IT 行业的一员,相信大家都接触过 Nginx Web 服务,不管是开发、运维、测试、还是算法都离不开 Nginx,而且大家对于 Nginx 的部署也是得心应手。但有的时候我们只局限于部署应用层面,没有考虑其运行在 Internet 上的安全问题,接下来将总结常用也是生产环境上有必要配置的一些安全策略。
1、使用 SSL/TLS 证书

传统的 HTTP 是一种以明文形式在端到端的超文本传输协议,在数据传输上存在很大的安全问题,如:窃听、篡改、冒充等安全问题。因此我们需要采用 SSL/TLS 证书来实现数据加密,SSL/TLS 证书是一种加密数字证书,用于对客户端(Web 浏览器)和服务器之间的流量进行加密。通过这样做,加密是安全的,并且可以防止攻击者使用中间人攻击来窃听和窃取机密信息,例如用户名、密码和信用卡信息等。

如何在 Nginx 服务器上配置?

server {
    listen              443 ssl;
    ssl_certificate     /etc/nginx/ssl/bundle.pem;
    ssl_certificate_key /etc/nginx/ssl/mytechnix.com.key;
}

# 当然,在我们实际应用中,不同的云厂商会提供相应的参考配置

2、使用安全密钥交换机制

DH 参数的目的是允许交换一个秘密,该秘密将用于加密会话中的消息副本。临时 DH 提供前向安全性,这意味着会话密钥在会话终止时被删除。因此,攻击者无法检索超过上一个会话的两方之间交换的消息。

使用 OpenSSL 生成至少 2048 位的唯一 DH 组:

openssl dhparam -out /etc/ssl/dhparam.pem 2048

如何在 Nginx 服务器上配置?

ssl_dhparam  /etc/ssl/dhparam.pem;

3、禁用旧的 SSL/TLS 协议

较弱的 SSL/TLS 协议(SSLv2.0、SSL v3.0、TLSv1.0 和 TLSv1.1)可能容易受到攻击并导致诸如 BEAST(针对 SSL/TLS 的浏览器漏洞利用)、POODLE(在降级的旧版上填充 Oracle )等攻击。因此建议使用更新和安全的 SSL/TLS 协议。

如何在 Nginx 服务器上配置?

server {
    listen              443 ssl;
    ssl_certificate     /etc/nginx/ssl/bundle.pem;
    ssl_certificate_key /etc/nginx/ssl/mytechnix.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
}


4、禁用 SSL/TLS 弱密码套件

较弱且旧的密码套件配置可能会很容易使你的网站受到攻击,比如攻击者可能会拦截或修改传输中的数据。因此,你可以更具你不同的 Nginx 版本和 SSL/TLS 版本来选择更佳的密码套件,大家可以通过该网站来评估出最佳方案 —> 传送门。输入 nginx 和 SSL/TLS 版本后,会为你自动生成最佳配置文件,比如我输入的 Nginx 版本为 1.18.0、SSL/TLS 版本为 1.1.1,则会生成如下结果:

# generated 2022-04-27, Mozilla Guideline v5.6, nginx 1.18.0, OpenSSL 1.1.1k, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&guideline=5.6
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
    ssl_dhparam /path/to/dhparam;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;  # 需要使用的时候改为on即可

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    # replace with the IP address of your resolver
    resolver 127.0.0.1;
}

 
5、禁用不需要的 HTTP 方法

常用的 HTTP 方法是 GET 和 POST,如果允许其他方法如 TRACE、DELETE、PUT 和 OPTIONS 是有风险的,因为这可能允许攻击者发起跨站点跟踪攻击并从您的网站窃取 cookie 信息,因此建议禁用不需要的和未使用的 HTTP 方法。

如何在 Nginx 服务器上配置?

# 配置方式1:此时,服务器将只允许 GET、HEAD 和 POST 方法。
location / {
    limit_except GET HEAD POST { deny all; }
}

# 配置方式2:效果同1
# 服务器只允许 GET、HEAD 和 POST 方法,并通过发出 444 No Response 状态代码过滤掉任何其他 HTTP 方法。
if ($request_method !~ ^(GET|HEAD|POST)$ )
{
    return 444;
}

6、防止缓冲区溢出攻击

缓冲区是系统内存中的一个小型存储位置,当数据开始从一个内存位置传输到另一个内存位置时,它可以暂时容纳数据。当数据大小超过缓冲区大小的容量时,就会发生缓冲区溢出。因此,攻击者可以利用此漏洞注入可以危害系统的恶意代码。

如何在 Nginx 服务器上配置?

client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;

7、防止 CSP、XSS 攻击

CSP(内容安全策略)是额外的安全层,有助于缓解某些攻击,如 XSS 跨站脚本攻击。通过添加 CSP 标头,可以告诉浏览器它只能从你明确允许的域下载内容,包括 Javascript 和 CSS 文件。

如何在 Nginx 服务器上配置?

add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;

针对 XSS 跨站脚本攻击,可做以下参数配置:

add_header X-XSS-Protection "1; mode=block";


8、防止 Click-jacking 劫持

Click-jacking(即点击劫持)是一种 Web 应用程序漏洞,攻击者利用该漏洞强制用户在未经用户同意的情况下点击,导致重定向到未知网站。HTTP 响应标头中的 X-Frame -Option 可用于指示 Web 浏览器是否应在框架或 iframe 中加载页面。因此,在 nginx.conf 文件的 HTTP 标头中附加 X-Frame-Options,这将指示浏览器仅从同一来源加载资源。

如何在 Nginx 服务器上配置?

add_header X-Frame-Options "SAMEORIGIN";

9、禁用内容嗅探

内容嗅探,也称为 MIME(Multipurpose Internet Mail Extensions)嗅探,即多用途网络邮件扩展嗅探,是一种用于检查字节流内容以确定其中数据的文件格式的技术。这也可能导致安全漏洞,因为攻击者可以利用 MIME 嗅探来发送 XSS 跨站点脚本攻击。

例如,如果你的网站允许用户上传图片等媒体内容,攻击者可能会上传包含一些 JavaScript 代码的恶意图片文件。当浏览器进行内容嗅探时,可能会被诱骗执行该恶意文件。为了防止内容嗅探攻击,可将 X-Content-Type-Options 响应标头设置为 nosniff,这告诉浏览器避免猜测响应类型并仅依赖 Content-Type 头。

如何在 Nginx 服务器上配置?

add_header X-Content-Type-Options nosniff;

10、图片防盗链

“图片防盗链”顾名思义就是防止别人盗用你的图片链接,这可能会导致你的带宽使用量增加,尤其是在现的服务器带宽使用策略中基本上都是按量付费的,因此这可能会间接性造成你们公司经济损失。

例如,假设在你 web 服务器根目录中有一个名为 images 的目录,其中存储了你在站点中使用的所有图像。为了防止其他方使用你的图像,你需要在 Nginx web 服务器上做如下配置。

如何在 Nginx 服务器上配置?

location /images/ {
  valid_referers none blocked www.hello.com hello.com;
   if ($invalid_referer) {
     return   403;
   }
}

11、启用 HSTS 功能

HSTS 功能只允许客户端(Web 浏览器)使用 HTTPS 进行通信,这 return 和 rewrite 方法的概念不同。当浏览器接收到 HSTS 标头时,它不会在指定的时间内以 HTTP 的形式与 web 服务端通信,保证了 HTTPS 严格安全传输问题。

如何在 Nginx 服务器上配置?

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;


12、仅允许通过域名访问

上线过 web 应用的同志都知道,上线完成后 IP 或域名形式我们都可以访问,如果你不想允许使用 IP 地址的请求,那只需要在 Nginx 做以下配置即可。

if ($host !~ ^(mytechnix.com|www.mytechnix.com)$ ) {
    return 301 https://mytechnix.com$request_uri;
}


13、禁止自动用户代理

为了保护你的服务器免受机器人、脚本和其他自动网页检索方法的侵害,请明确拒绝这些用户代理。

例如,像 wget 这样的应用程序可以检索整个文档根目录结构,使它们成为有用的 DoS 攻击者或只是访问网站上的受保护文件。

如何在 Nginx 服务器上配置?

if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
    return 403;
}

14、防止服务器信息泄露

什么意思呢?Nginx 服务器的默认配置 server_tokens 指令在所有自动生成的错误页面以及 HTTP 响应标头上会显示 Nginx 版本号,我在之前做的一个项目中就存在这个问题,当时客户的安全工程师用工具扫出了这个问题。这可能会导致 web 服务器信息泄露,攻击者可以获得有关 Nginx 版本的信息,从而缩小攻击范围。因此,我们必须禁止在客户端(浏览器)显示 Nginx 版本号等相关信息。

如何在 Nginx 服务器上配置?

server_tokens off;


15、升级 Nginx 版本

建议将您的 Nginx 服务器更新到最新和稳定的版本,因为有很多性能改进、安全修复和新功能实现。
附件

    通过上面的基础配置,现整合出完整的配置

#==========全局配置文件============

# 避免 Nginx 版本信息泄露
server_tokens off;

# 防止 Click-jacking 点击劫持
add_header X-Frame-Options SAMEORIGIN;

# 禁用内容嗅探,防止 XSS 跨站脚本攻击
add_header X-Content-Type-Options nosniff;

# CSP 内容安全策略,告诉浏览器它只能从你明确允许的域下载内容,防止 XSS 跨站脚本攻击
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;

# 启用 HSTS 功能,只允许客户端(Web 浏览器)使用 HTTPS 进行通信,保证了 HTTPS 严格安全传输问题。
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# 防止缓冲区溢出攻击,免密攻击者恶意代码注入
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;

#==========虚拟主机配置============

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name hello.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name hello.com;

    # SSL/TLS 证书/密钥
    ssl_certificate     /etc/nginx/ssl/bundle.pem;
    ssl_certificate_key /etc/nginx/ssl/hello.com.key;

    # DH 密钥交换机制,会话密钥在会话终止时被删除,攻击者无法检索双方之间交换的消息。
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

    ssl_prefer_server_ciphers on;

    # 禁用旧的 SSL/TLS 协议
    ssl_protocols TLSv1.2 TLSv1.3;

    # 禁用 SSL/TLS 弱密码套件
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

    # 禁用不需要的 HTTP 方法
    if ($request_method !~ ^(GET|HEAD|POST)$ ){
        return 444;
    }

    # 图片防盗链
    location /images/ {
        valid_referers none blocked www.hello.com hello.com;
        if ($invalid_referer) {
            return   403;
        }
    }
    # 仅允许通过域名形式访问 web 服务器
    if ($host !~ ^(hello.com|www.hello.com)$ ) {
        return 301 https://hello.com$request_uri;
    }
    # 禁止自动用户代理,防止 Dos 攻击
    if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
        return 403;
    }

}

 



  


posted @ 2023-02-28 18:37  锐洋智能  阅读(224)  评论(0编辑  收藏  举报