Nginx安全防护与HTTPS部署

目录

一、Nginx 概述

二、Nginx 核心安全配置

(一)编译安装 Nginx

(二)隐藏版本号

(三)限制危险请求方法

(四)请求限制(CC 攻击防御)

(五)防盗链

三、Nginx 高级防护

(一)动态黑名单

(二)Nginx HTTPS 配置


一、Nginx 概述

在互联网技术蓬勃发展的当下,Web 服务的安全性和可靠性至关重要。Nginx 作为一款高性能的 Web 服务器和反向代理工具,凭借其轻量级架构、卓越的高并发处理能力以及灵活的模块化设计,在全球 Web 服务器市场中占据近三分之一的份额,成为众多企业和开发者的首选。然而,网络攻击手段层出不穷,如 DDoS 攻击、SQL 注入、恶意爬虫等,同时数据隐私保护法规日益严格,如 GDPR、等保 2.0 等,这使得掌握 Nginx 的安全防护策略与 HTTPS 部署能力,成为运维工程师和开发者不可或缺的技能。

二、Nginx 核心安全配置

(一)编译安装 Nginx

  1. 安装支持软件:Nginx 的配置和运行依赖于 pcre、zlib 等软件包,因此需要预先安装这些软件的开发包(devel),以提供相应的库和头文件,确保 Nginx 安装顺利进行。在基于 DNF 包管理器的系统(如 OpenEuler)上,执行以下命令安装相关软件:
[root@localhost ~]# dnf install -y gcc make pcre-devel zlib-devel openssl-devel perl-ExtUtils-MakeMaker git wget tar

  1. 创建运行用户、组和日志目录:为了提高安全性,创建专门的 Nginx 运行用户和组,并设置相应的日志目录。执行以下命令:
[root@localhost ~]# useradd -M -s /sbin/nologin nginx
[root@localhost ~]# mkdir -p /var/log/nginx
[root@localhost ~]# chown -R nginx:nginx /var/log/nginx

  1. 编译安装 Nginx:下载 Nginx 源码包并解压,进入解压目录进行配置和编译安装。假设下载的 Nginx 版本为 1.26.3,执行以下命令:
[root@localhost ~]# tar zxf nginx-1.26.3.tar.gz
[root@localhost ~]# cd nginx-1.26.3
[root@localhost nginx-1.26.3]#./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module
[root@localhost nginx-1.26.3]# make && make install

上述./configure命令中的参数含义如下:

  • --prefix=/usr/local/nginx:指定 Nginx 的安装路径。
  • --user=nginx--group=nginx:指定 Nginx 运行的用户和组。
  • --with-http_ssl_module:启用 HTTPS 支持。
  • --with-http_v2_module:启用 HTTP/2 支持。
  • --with-http_realip_module:用于获取客户端真实 IP 地址。
  • --with-http_stub_status_module:启用状态统计模块。

安装完成后,可以通过以下命令检查 Nginx 是否安装成功,并查看版本号:

[root@localhost ~]# curl -I 192.168.10.101

如果 Nginx 正常运行,会返回类似如下信息,其中包含 Nginx 的版本号:

HTTP/1.1 200 OK
Server: nginx/1.26.3
# 省略部分内容

(二)隐藏版本号

Nginx 的版本号可能会被攻击者利用,获取服务器的相关信息,增加安全风险。因此,需要隐藏 Nginx 的版本号。修改 Nginx 配置文件nginx.conf,在http块中添加server_tokens off;配置项:

[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
http {
    include       mime.types;
    default_type  application/octet-stream;
    # 隐藏版本号
    server_tokens off;
    # 省略部分内容
}

修改完成后,检查配置文件语法是否正确,并重新加载配置:

[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload

再次使用curl -I命令检查,版本号已被隐藏:

[root@localhost ~]# curl -I 192.168.10.101
HTTP/1.1 200 OK
Server: nginx
# 省略部分内容

(三)限制危险请求方法

TRACE、PUT、DELETE、CONNECT 等请求方法可能存在安全风险,如 TRACE 易引发 XST 攻击,PUT/DELETE 存在文件修改风险,CONNECT 可能导致代理滥用。通过正则表达式匹配请求方法,对非白名单方法返回 444(无响应关闭连接)。在 Nginx 配置文件nginx.confserver块中添加如下配置:

[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
server {
    if ($request_method!~ ^(GET|HEAD|POST)$) {
        return 444;
    }
    # 省略部分内容
}

修改完成后,同样检查配置文件语法并重新加载配置:

[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload

验证测试请求,以 PUT 请求为例:

[root@localhost ~]# curl -XPUT -I 192.168.10.101
curl: (52) Empty reply from server

查看access.log日志,可以看到相应的记录:

192.168.10.101 - - [11/Mar/2025:18:30:46 +0800] "PUT / HTTP/1.1" 444 0 "-" "curl/8.4.0"

需要注意的是,测试 TRACE 和 CONNECT 方法时,状态码可能不是 444。原因如下:

  • CONNECT 请求的目标不是代理服务器时,服务器必须返回 400 Bad Request,Nginx 核心层在请求解析阶段直接拦截,根本不进入后续的 location 处理流程。
  • 现代 Nginx 默认禁用 TRACE 方法,在ngx_http_core_module阶段直接返回 405 Not Allowed。

(四)请求限制(CC 攻击防御)

CC 攻击(Challenge Collapsar 攻击)通过大量合法或伪造的小流量请求耗尽服务器资源,导致正常用户无法访问网站。可以使用 Nginx 的limit_req模块限制请求速率,使用limit_conn模块限制并发连接数。

  1. 使用 limit_req 模块限制请求速率:编辑 Nginx 配置文件nginx.conf,在http块中定义限制区,在server块的location中实施速率限制:
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
http {
    # 定义限制区(10MB内存/每秒10请求)
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
    # 其他全局配置...
    server {
        location / {
            root html;
            index index.html index.php;
            limit_req zone=req_limit burst=20 nodelay;
        }
    }
}

上述配置中关键参数说明如下:

  • limit_req_zone:定义共享内存区。
  • $binary_remote_addr:内置变量,表示客户端 IP 地址的二进制格式。
  • zone=req_limit:10m:创建名为req_limit的共享内存区,大小为 10M,用于存储客户端 IP。
  • rate=10r/s:限制并发数,每个 IP 每秒可以发起的请求次数为 10 次。
  • limit_req:实施速率限制。
  • zone=req_limit:绑定到预定义的共享内存区。
  • burst=20:类似等候区,超出并发数的请求会进入等候区,等候区占满后,多余的请求会立刻返回 503。
  • nodelay:立即处理突发请求而不延迟,相当于立即处理等候区的请求,多余的请求会立刻返回 503。

  1. 压力测试验证:安装 ApacheBench(简称 ab)测试工具,它是 Apache HTTP 服务器自带的轻量级、易用的 HTTP 服务器性能测试工具。执行以下命令安装:
[root@localhost ~]# dnf install httpd-tools -y

发起测试请求,共发起 300 个请求,每次发起 30 个请求:

[root@localhost ~]# ab -n 300 -c 30 http://192.168.10.101/

其中,-n 300表示总请求数为 300 次,即模拟客户端向服务器发送 300 次 HTTP 请求;-c30表示并发用户数为 30,即同时有 30 个请求并行发送到服务器。

查看access.log日志,会发现大量请求日志状态码为 503:

[root@localhost ~]# tail -300 /usr/local/nginx/logs/access.log | grep -c 503
279

(五)防盗链

防盗链用于防止未经授权的用户盗用网站(静态)资源,保护网站的带宽和资源,避免版权侵犯。盗链行为是指一个网站在没有自身页面资源的情况下,链接到其他网站的资源展示给浏览者,增加自身访问量,同时损害原网站的合法利益,加重服务器负担。

  1. 准备工作:本实验需要两台主机,分别为源主机(192.168.10.101,域名www.aaa.com)和盗链主机(192.168.10.102,域名www.bbb.com)。修改 Windows 的C:\Windows\System32\drivers\etc\hosts文件以及两台 OpenEuler 主机的hosts文件,设置域名和 IP 映射关系:
192.168.10.101 www.aaa.com
192.168.10.102 www.bbb.com

在源主机(www.aaa.com)的工作目录(假设为/usr/local/nginx/html)下放置图片kgc.png,并编辑原网站首页文件index.html

[root@localhost ~]# vi /usr/local/nginx/html/index.html
<html>
<body>
<h1>aaa It work!</h1>
<img src="kgc.png"/>
</body>
</html>

  1. 测试盗链:在盗链主机上安装httpd服务(用于模拟盗链网站),编辑盗链网站首页文件index.html
[root@localhost ~]# dnf -y install httpd
[root@localhost ~]# vi /usr/local/nginx/html/index.html
<html>
<body>
<h1>bbb It work!</h1>
<img src="http://www.aaa.com/kgc.png"/>
</body>
</html>
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl start httpd

此时访问盗链网站(www.bbb.com),可以看到盗链成功,显示出源网站的图片。
3. 配置 Nginx 防盗链:在源主机的 Nginx 配置文件nginx.conf中添加防盗链配置:

[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
location ^* \.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|webp|ico)$ {
    root html;
    valid_referers aaa.com *.aaa.com;
    if ($invalid_referer) {
        return 403;
    }
}

上述配置中:

  • ^*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|webp|ico)$:这段正则表达式表示匹配不区分大小写,以.jpg.gif.swf等结尾的文件。
  • valid_referers:设置信任的网站,可以正常使用图片。
  • if ($invalid_referer):如果链接的来源域名不在valid_referers所列出的列表中,$invalid_referer为 1,则执行后面的操作,即返回 403 页面。

修改完成后,检查配置文件语法并重新加载配置:

[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload

再次访问盗链网站(www.bbb.com),会发现盗链失败,显示 403 页面。

三、Nginx 高级防护

(一)动态黑名单

动态黑名单是 Nginx 中一种实时拦截恶意请求的安全机制,允许在不重启服务的情况下,动态更新需要封禁的 IP 地址或网段,相比静态配置的allow/deny指令,更加灵活高效,适用于高并发、多变的攻击防护场景。

  1. 编辑黑名单配置文件:创建或编辑黑名单配置文件blockips.conf,添加需要封禁的 IP 地址或网段,以及对应的封禁动作:
[root@localhost ~]# vi /usr/local/nginx/conf/blockips.conf
192.168.1.0/24 1; # 封禁整个网段
192.168.10.102 1; # 封禁ip

IP 地址后的数字含义如下:

  • 0:允许访问。
  • 1:返回 403,完全封禁。
  • 2:返回 444,静默断开。
  • 3:返回 503,服务不可用。

  1. 编辑主配置文件:在 Nginx 主配置文件nginx.conf中,使用geo模块引入黑名单配置,并设置相应的封禁逻辑:
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
http {
    geo $block_ip {
        default 0; # 默认允许访问
        include /usr/local/nginx/conf/blockips.conf; # 包含黑名单
    }
    server {
        if ($block_ip) {
            return 403; # 封禁动作
        }
    }
}

上述配置中:

  • geo:Nginx 内置模块指令,专门用于处理 IP 地址相关的逻辑,基于客户端 IP 地址生成一个变量值,用于后续的访问控制判断。
  • $block_ip:自定义的变量名,存储计算结果(通常为 0 或 1)。
  • default 0:默认值,表示不在黑名单中的 IP 允许访问。
  • if ($block_ip):当变量值为 1 时触发封禁逻辑。

修改完成后,检查配置文件语法并重新加载配置:

[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload

  1. 使用封禁 ip 测试访问:使用封禁的 IP(如192.168.10.102)访问 Nginx 服务器,会返回 403 Forbidden 页面:
[root@localhost ~]# curl 192.168.10.101
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

  1. 自动添加黑名单:可以编写脚本实现自动封禁访问超过一定次数的 IP。例如,以下脚本可以自动封禁访问超过 100 次的 IP:
#!/bin/bash
# 自动封禁访问超过100次的IP
awk '{print $1}' /var/log/nginx/access.log |sort |uniq -c|sort -nr | awk '{if($1>100) print $2" 1;"}' > /usr/local/nginx/conf/blockips.conf

上述脚本中:

  • awk '{print $1}' /var/log/nginx/access.log:从access.log日志文件中提取客户端 IP 地址。
  • sort:对提取的 IP 地址进行排序。
  • uniq -c:统计连续出现的次数,并在行首显示次数。
  • sort -nr:按数值从大到小排序。
  • awk '{if($1>100) print $2" 1;"}':筛选出访问次数大于 100 的 IP 地址,并添加封禁标记(返回 403)。
  • > /usr/local/nginx/conf/blockips.conf:将结果输出到黑名单配置文件中。

(二)Nginx HTTPS 配置

  1. HTTPS 概念
    • HTTPS 的设计初衷与发展:HTTPS(HyperText Transfer Protocol over Secure Socket Layer)的设计初衷是为了保证数据传输安全。国内大型互联网巨头从 2016 年开始大力推行 HTTPS,期间发生了一系列重大事件。例如,Google 搜索引擎让 HTTPS 的网站在搜索排名中更靠前;从 2017 年开始,chrome 浏览器把只采用 HTTP 的网站标记为不安全网站;苹果要求 App Store 中的所有应用都必须使用 HTTPS 加密链接;新一代的 http/2 协议的支持需要以 HTTPS 为基础。
    • HTTP 不安全的原因:HTTP 由于是明文传输,主要存在三大风险:窃听风险、篡改风险、冒充风险。
      • 窃听风险:中间人可以获取到通信内容,由于内容是明文,所以获取明文后有安全风险。例如在转账场景中,中间人可以截获 “转账 100” 的信息,造成用户信息泄露和资金安全隐患 。
      • 篡改风险:中间人可以篡改报文内容后再发送给对方,风险极大。如将 “转账 100 到 A 账户” 篡改为 “转账 200 到其他账户” 。
      • 冒充风险:用户可能误以为在和合法网站通信,但实际上是在和钓鱼网站通信。比如以为是在和某宝通信,结果却是在和钓鱼网站交互。
    • 安全通信的四大原则:安全的通信需要包括机密性、完整性、身份认证和不可否认这四个原则。
      • 机密性:对数据加密,解决了窃听风险。即使数据被中间人窃听,由于数据是加密的,也无法获取明文。
      • 完整性:数据在传输过程中没有被篡改,接收方能够识别数据是否被修改。一旦数据有任何改动,接收报文就会被判定为不合法。
      • 身份认证:确认对方的真实身份,解决了冒充风险。让用户不用担心访问的是正规网站却实际与钓鱼网站通信的问题。
      • 不可否认:不可否认已发生的行为。避免出现类似小明向小红借钱却不承认的情况,保障交易或行为的可追溯性和不可抵赖性。
    • HTTPS 通信原理简述
      • 对称加密的困境:HTTP 是明文传输,给报文加密可采用对称加密方式,即通信双方使用同一把密钥进行加解密。但问题在于,对称加密的密钥协商存在困难。如果通过报文直接传输密钥,密钥会被中间人截获和替换,导致后续通信依然不安全。例如,客户端向服务器请求密钥,中间人截获真密钥并返回假密钥,客户端使用假密钥加密报文,中间人就能用假密钥解密并篡改内容,再用真密钥加密篡改后的内容发送给服务器 。
      • 非对称加密的引入:非对称加密即加解密双方使用不同的密钥,一把作为公钥可以公开,一把作为私钥不能公开。公钥加密的密文只有私钥可以解密,私钥签名的内容只有公钥可以验签。服务器保管好私钥,发布公钥给客户端,客户端用公钥加密对称加密的密钥(或用于生成对称加密密钥的信息)传给服务器,服务器用私钥解密获得对称加密密钥,之后双方就可以用对称加密密钥进行通信。
      • 数字证书解决公钥传输信任问题:然而,服务器的公钥在传输过程中也存在被中间人调包的风险。为解决此问题,引入数字证书。服务器向证书颁发机构(CA)申请证书,在证书中附上公钥,客户端收到证书后,通过验证证书的合法性以及证书中的域名信息,来确认公钥的真实性。客户端拿到服务器端的公钥后,用公钥加密会话密钥(对称加密的密钥)发送给服务端,服务端用私钥解密获得会话密钥,然后双方就可以安全地进行数据传输。需要注意的是,HTTPS 加密采用混合模式,在握手阶段使用非对称加密,在数据传输阶段使用对称加密,因为对称加密的密钥管理简单且加密和解密效率更高。同时,中间人无法通过申请受信任的证书来替换服务器的证书,因为每个证书中的域名是唯一的,客户端会验证证书中的域名与实际访问的域名是否一致。
  2. Nginx 配置 HTTPS 证书
    • 使用 openssl 生成证书和私钥:由于 SSL 证书需要向 CA 组织申购,在实验环境中可以采用自签名证书(自己给自己签名并颁发证书,这种证书不被信任,仅适用于测试场景)。
      • 创建证书存储目录:执行以下命令创建证书存储目录:
[root@localhost ~]# mkdir -p /etc/nginx/ssl

  • 生成自签名证书:使用 openssl 命令生成自签名证书和私钥,执行以下命令:
[root@localhost ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx-selfsigned.key -out /etc/nginx/ssl/nginx-selfsigned.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=localhost"

  • 参数解释
    • -x509:生成自签名证书(而非 CSR)。
    • -nodes:不加密私钥(无密码保护)。
    • -days 365:证书有效期 1 年。
    • -keyout:指定私钥文件。
    • -out:指定自签名文件。
    • -newkey rsa:2048:生成 2048 位的 RSA 私钥。
    • -subj:设置证书主题信息(可按需修改字段)。
  • CA 签名证书与自签名证书对比
    • CA 签名证书:需要由受信任的第三方证书颁发机构(CA)签发。流程为用户生成私钥和 CSR(证书签名请求),将 CSR 提交给 CA(如 Let's Encrypt、DigiCert 等),CA 机构验证身份后,用 CA 的私钥对证书签名,生成最终证书。这种证书具有较高的信任度,适用于正式的线上环境。
    • 自签名证书:证书的颁发者(Issuer)和主体(Subject)是同一个实体(即自己)。无需第三方 CA 参与,直接用工具(如 OpenSSL)生成私钥和证书。签名时使用自己的私钥,而不是 CA 的私钥。适用于测试、内部环境或无需公开信任的场景。
  • Nginx 启用 HTTPS:编辑 Nginx 配置文件nginx.conf,添加 HTTPS 相关配置:
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
server {
    listen 443 ssl; # 监听HTTPS端口
    server_name localhost; # 域名或IP
    # 指定证书和私钥路径
    ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;
    # SSL协议和加密套件配置(可选,提升安全性)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    # 其他配置(如根目录)
    location / {
        root /usr/local/nginx/html;
        index index.html;
    }
    # 可选:将HTTP请求重定向到HTTPS
    server {
        listen 80;
        server_name localhost;
        return 301 https://$host$request_uri;
    }
}

  • 配置说明
    • listen 443 ssl:表示 Nginx 监听 443 端口,并启用 SSL 加密。
    • server_name:指定服务器的域名或 IP 地址。
    • ssl_certificatessl_certificate_key:分别指定 SSL 证书和私钥的路径。
    • ssl_protocols:指定允许的 SSL/TLS 协议版本,这里启用了 TLSv1.2 和 TLSv1.3,TLSv1.0 和 TLSv1.1 因存在安全风险已被弃用。
    • ssl_ciphers:设置加密套件,选择安全强度较高的加密算法组合。
    • ssl_prefer_server_ciphers on:表示优先使用服务器端配置的加密套件。
    • location /:定义网站的根目录和默认首页。
    • 第二个server块配置用于将 HTTP 请求重定向到 HTTPS,确保所有访问都通过加密连接进行。
  • 检查配置并重启 Nginx:修改完成后,检查配置文件语法是否正确,并重新加载 Nginx 配置:
[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload

  • 通过浏览器验证:访问https://你的服务器ip,由于使用的是自签名证书,浏览器会提示证书不安全。在测试环境中,可以选择 “高级”-“继续前往” 或 “信任此证书”(在正式环境中,应使用受信任的 CA 签名证书)。如果配置正确,将能够正常访问网站内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值