一、实战背景
Nginx 作为高性能 Web 服务器和反向代理工具,凭借轻量级、高并发、模块化设计的优势,占据全球近三分之一 Web 服务器市场份额。但随着 DDoS、SQL 注入、恶意爬虫等网络攻击手段升级,以及 GDPR、等保 2.0 等数据隐私法规的要求,做好 Nginx 安全防护与 HTTPS 部署,是运维工程师的核心必备技能。
本次实战将从核心安全配置 、高级安全防护 、HTTPS 原理与部署三部分展开,包含完整实操代码,同时补充关键知识点,兼顾实用性和易理解性。
二、核心安全配置
核心安全配置是 Nginx 安全的基础,涵盖编译安装、版本隐藏、请求限制、防盗链等关键操作,从服务器基础部署到请求层安全做全方位防护。
2.1 编译安装 Nginx(含安全模块)
编译安装可自主选择安全相关模块,相比 yum 安装更灵活,是生产环境的首选方式。
2.1.1 安装依赖软件包
Nginx 运行依赖 pcre(正则支持)、zlib(压缩支持)、openssl(加密支持)等开发包,需提前安装:
[root@localhost ~]# dnf install -y gcc make pcre-devel zlib-devel openssl-devel perl-ExtUtils-MakeMaker git wget tar
补充知识点 :openssl-devel是 HTTPS 部署、SSL 加密的核心依赖,缺少则无法编译http_ssl_module模块。
2.1.2 创建专用运行用户和日志目录
避免 Nginx 以 root 用户运行,降低权限泄露风险,同时创建专属日志目录并授权:
[root@localhost ~]# useradd -M -s /sbin/nologin nginx # 不创建家目录、禁止登录
[root@localhost ~]# mkdir -p /var/log/nginx
[root@localhost ~]# chown -R nginx:nginx /var/log/nginx
补充知识点 :/sbin/nologin让用户仅能运行 Nginx 进程,无法通过终端登录服务器,从账户层面提升安全。
2.1.3 编译安装 Nginx(启用安全模块)
以 nginx-1.26.3 为例,启用 SSL、真实 IP、请求状态统计等核心安全模块:
[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 \ # HTTPS核心模块
--with-http_v2_module \ # HTTP/2模块,需基于HTTPS
--with-http_realip_module \ # 获取客户端真实IP,防代理隐藏
--with-http_stub_status_module \ # 监控Nginx连接状态
--with-http_gzip_static_module \ # 静态资源压缩,降低带宽消耗
--with-pcre \
--with-stream # 四层转发,支持TCP/UDP代理
[root@localhost nginx-1.26.3]# make && make install
2.1.4 创建软链接 + 添加系统服务
创建软链接让系统识别 nginx 命令,添加 systemd 服务实现开机自启和便捷管理:
# 创建软链接
[root@localhost nginx-1.26.3]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
# 编写系统服务文件
[root@localhost ~]# vi /lib/systemd/system/nginx.service
服务文件内容:
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target
[Service]
Type=forking
ExecStartPre=/usr/local/sbin/nginx -t # 启动前检查配置文件语法
ExecStart=/usr/local/sbin/nginx
ExecReload=/usr/local/sbin/nginx -s reload # 平滑重启,不中断服务
ExecStop=/bin/kill -s QUIT $MAINPID
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
User=root
Group=root
[Install]
WantedBy=multi-user.target
重载服务并设置开机自启:
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start nginx
[root@localhost ~]# systemctl enable nginx
补充知识点 :ExecStartPre=/usr/local/sbin/nginx -t是关键安全操作,避免配置文件错误导致 Nginx 启动失败,保障服务可用性。
2.2 隐藏 Nginx 版本号
攻击者常通过版本号针对性利用漏洞,隐藏版本号可大幅降低被攻击概率。
2.2.1 查看当前版本号
[root@localhost ~]# curl -I 192.168.10.101 # 服务器IP
# 输出会显示 Server: nginx/1.26.3,暴露版本
2.2.2 修改配置文件隐藏版本
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
在http块中添加server_tokens off;,注释或保留原有核心配置:
nginx
http {
include mime.types;
default_type application/octet-stream;
server_tokens off; # 隐藏Nginx版本号
# 其他配置...
}
2.2.3 验证配置并生效
[root@localhost ~]# nginx -t # 语法检查
[root@localhost ~]# nginx -s reload # 平滑重启
# 再次查看,版本号消失
[root@localhost ~]# curl -I 192.168.10.101
# 输出 Server: nginx,无版本信息
2.3 限制危险 HTTP 请求方法
HTTP 的 PUT、DELETE、TRACE、CONNECT 等方法存在安全风险(如 PUT 可上传文件、TRACE 引发 XST 攻击),仅保留业务必需的 GET、HEAD、POST 方法。
2.3.1 修改配置文件
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
在server块中添加请求方法判断,非白名单方法返回 444(静默断开连接):
nginx
server {
listen 80;
server_name localhost;
# 限制请求方法,仅允许GET、HEAD、POST
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
# 其他配置...
}
2.3.2 验证配置并测试
[root@localhost ~]# nginx -t && nginx -s reload
# 测试PUT方法,返回空响应(444)
[root@localhost ~]# curl -XPUT -I 192.168.10.101
# 输出 curl: (52) Empty reply from server
补充知识点:Nginx 默认禁用 TRACE 方法,直接返回 405;CONNECT 方法若目标非代理服务器,会被核心层拦截返回 400,因此这两种方法无需额外配置。
2.4 限制请求速率(防御 CC 攻击)
CC 攻击通过大量小流量请求耗尽服务器资源,利用 Nginx 的limit_req模块限制单 IP 请求速率,是防御 CC 攻击的核心手段。
2.4.1 修改配置文件开启限速
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
在http块定义限速内存区,在server块的location中启用限速:
nginx
http {
# 定义限速区:10M内存存储IP,单IP每秒最多10个请求
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# 其他配置...
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
# 启用限速,突发请求缓冲区20个,无延迟处理
limit_req zone=req_limit burst=20 nodelay;
}
# 其他配置...
}
}
补充知识点 :$binary_remote_addr以二进制存储客户端 IP,相比普通 IP 存储更节省内存;burst=20为突发请求设置缓冲区,避免正常突发请求被拦截;nodelay表示缓冲区请求立即处理,超出部分直接返回 503。
2.4.2 安装压测工具验证
使用 ApacheBench(ab)压测,验证限速效果:
# 安装ab工具
[root@localhost ~]# dnf install httpd-tools -y
# 发起300个请求,并发30个
[root@localhost ~]# ab -n 300 -c 30 http://192.168.10.101/
# 查看日志,大量请求返回503(服务暂时不可用)
[root@localhost ~]# tail -300 /usr/local/nginx/logs/access.log | grep -c 503
2.5 配置防盗链(防止资源盗用)
盗链指其他网站未经授权引用本站静态资源(图片、视频、SWF),导致本站带宽消耗、版权受损,通过 Nginx 配置可限制资源引用来源。本次实战需两台主机:源主机(192.168.10.101,www.aaa.com)、盗链主机(192.168.10.102,www.bbb.com)。
2.5.1 配置域名与 IP 映射
Windows 主机 :修改C:\Windows\System32\drivers\etc\hosts
plaintext
192.168.10.101 www.aaa.com
192.168.10.102 www.bbb.com
两台 OpenEuler 主机 :修改/etc/hosts
[root@localhost ~]# vi /etc/hosts
192.168.10.101 www.aaa.com
192.168.10.102 www.bbb.com
2.5.2 配置源主机(www.aaa.com)
# 将图片kgc.png放入Nginx根目录
[root@localhost ~]# cp kgc.png /usr/local/nginx/html/
# 编辑源网站首页,引用图片
[root@localhost ~]# vi /usr/local/nginx/html/index.html
<html>
<body>
<h1>aaa It work!</h1>
<img src="kgc.png"/>
</body>
</html>
2.5.3 配置盗链主机(www.bbb.com)
安装 httpd 并编辑首页,未经授权引用源主机图片:
[root@localhost ~]# dnf -y install httpd
[root@localhost ~]# vi /var/www/html/index.html
<html>
<body>
<h1>bbb It work!</h1>
# 引用源主机图片,构成盗链
<img src="http://www.aaa.com/kgc.png"/>
</body>
</html>
# 关闭防火墙并启动httpd
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl start httpd
此时访问www.bbb.com可看到源主机图片,盗链成功。
2.5.4 源主机配置 Nginx 防盗链
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
在server块中添加防盗链规则,仅允许本站域名引用资源:
nginx
server {
listen 80;
server_name www.aaa.com;
# 对图片、SWF等静态资源做防盗链
location ~* \.(jpg|gif|swf|png)$ {
root html;
# 信任的域名:本站及子域名
valid_referers aaa.com *.aaa.com;
# 非信任来源返回403
if ($invalid_referer) {
return 403;
}
}
# 其他配置...
}
2.5.5 验证防盗链效果
[root@localhost ~]# nginx -t && nginx -s reload
再次访问www.bbb.com,图片位置显示 403 错误,盗链失败。补充知识点 :~*表示正则匹配不区分大小写;valid_referers后可添加none(允许直接访问资源,如直接输入图片 URL)、blocked(允许来源地址被隐藏的请求)。
三、高级安全防护
核心配置解决基础安全问题,高级防护针对动态攻击场景做优化,包括动态黑名单 (实时封禁恶意 IP),相比静态allow/deny更灵活,无需重启 Nginx 即可更新封禁规则。
3.1 配置静态动态黑名单
3.1.1 创建黑名单配置文件
[root@localhost ~]# vi /usr/local/nginx/conf/blockips.conf
# 格式:IP/网段 标记值(0=允许,1=403封禁,2=444静默断开,3=503服务不可用)
192.168.1.0/24 1; # 封禁整个网段
192.168.10.102 1; # 封禁盗链主机IP
3.1.2 修改 Nginx 主配置文件引入黑名单
利用 Nginx 内置geo模块处理 IP 逻辑,动态识别黑名单 IP:
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
在http块中添加geo配置,在server块中添加封禁规则:
nginx
http {
# 定义geo模块,判断客户端IP是否在黑名单
geo $block_ip {
default 0; # 默认允许所有IP
include /usr/local/nginx/conf/blockips.conf; # 引入黑名单文件
}
# 其他配置...
server {
listen 80;
server_name localhost;
# 若IP在黑名单(block_ip=1),返回403
if ($block_ip) {
return 403;
}
# 其他配置...
}
}
3.1.3 验证黑名单效果
[root@localhost ~]# nginx -t && nginx -s reload
# 用被封禁的IP测试访问,返回403
[root@localhost ~]# curl 192.168.10.101
# 输出403 Forbidden页面
3.2 编写脚本实现自动封禁恶意 IP
手动维护黑名单效率低,编写 Shell 脚本,自动封禁访问次数超过阈值的 IP,适配高并发攻击场景。
3.2.1 编写自动封禁脚本
[root@localhost ~]# vi /root/auto_block_ip.sh
#!/bin/bash
# 自动封禁访问次数超过100次的IP
# 从Nginx访问日志提取IP,统计访问次数,按次数倒序
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr \
# 过滤访问次数>100的IP,写入黑名单文件
| awk '{if($1>100) print $2" 1;"}' > /usr/local/nginx/conf/blockips.conf
# 平滑重启Nginx,使黑名单生效
/usr/local/sbin/nginx -s reload
3.2.2 赋予脚本执行权限并测试
[root@localhost ~]# chmod +x /root/auto_block_ip.sh
[root@localhost ~]# sh /root/auto_block_ip.sh
补充知识点 :可通过crontab设置脚本定时执行,实现实时监控封禁,例如每 5 分钟执行一次:
[root@localhost ~]# crontab -e
# 添加以下内容
*/5 * * * * /root/auto_block_ip.sh
四、HTTPS 部署实战
HTTP 为明文传输,存在窃听、篡改、冒充三大风险,HTTPS(HTTP+SSL/TLS)通过加密解决上述问题,同时是 HTTP/2、小程序开发、搜索引擎优化的必备条件。
4.1 HTTPS 核心基础知识点
- 加密模式:混合加密(握手阶段非对称加密,传输阶段对称加密),兼顾安全性和传输效率;
- 核心协议:SSL 已废弃,主流使用 TLS1.2/TLS1.3(TLS1.0/TLS1.1 于 2021 年弃用);
- 数字证书:解决公钥传输信任问题,由 CA 机构签发,包含域名、公钥、数字签名等信息,操作系统内置根 CA 公钥,可验证证书真伪;
- 证书类型:CA 签名证书(公网环境使用,如 Let's Encrypt 免费证书)、自签名证书(测试 / 内网环境使用,不被公网信任)。
4.2 生成自签名证书(测试环境)
生产环境需向 CA 机构申请证书,测试环境可通过 OpenSSL 生成自签名证书,步骤如下:
4.2.1 创建证书存储目录
[root@localhost ~]# mkdir -p /etc/nginx/ssl
4.2.2 生成自签名证书和私钥
[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:不加密私钥,避免 Nginx 启动时需要输入密码;-days 365:证书有效期 1 年;(现实不建议怎么长时间)-newkey rsa:2048:生成 2048 位 RSA 私钥(密钥越长越安全,推荐 2048 位及以上);-subj:证书主题信息(C = 国家,ST = 省份,L = 城市,O = 组织,CN = 域名 / IP)。
4.3 Nginx 配置 HTTPS 并实现 HTTP 重定向
4.3.1 修改 Nginx 主配置文件
[root@localhost ~]# vi /usr/local/nginx/conf/nginx.conf
配置 443 端口(HTTPS 默认端口),指定证书 / 私钥路径,同时将 80 端口 HTTP 请求重定向到 HTTPS:
http {
# 其他全局配置...
# 配置HTTPS服务
server {
listen 443 ssl; # 监听443端口,启用SSL
server_name localhost; # 对应证书的CN字段(域名/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 index.htm;
}
}
# 将80端口HTTP请求永久重定向到443端口HTTPS
server {
listen 80;
server_name localhost;
return 301 https://$host$request_uri; # $host为域名,$request_uri为请求路径
}
}
补充知识点 :return 301为永久重定向,搜索引擎会将 HTTP 地址的权重转移到 HTTPS 地址,利于 SEO;ssl_prefer_server_ciphers on让服务器端选择更安全的加密套件,避免客户端选择低安全套件。
4.3.2 验证配置并生效
[root@localhost ~]# nginx -t # 语法检查
[root@localhost ~]# nginx -s reload # 平滑重启
4.4 验证 HTTPS 访问
通过浏览器访问https://服务器IP(如https://192.168.10.101),浏览器会提示 "证书不安全"(自签名证书未被 CA 信任),选择高级 →继续前往 ,即可看到 HTTPS 加密的站点页面,同时访问http://服务器IP会自动跳转到 HTTPS 地址。
补充知识点:生产环境使用 CA 签名证书后,浏览器会显示绿色锁标,无安全警告,可通过 Let's Encrypt 申请免费的 CA 签名证书,有效期 3 个月,支持自动续期。
五、实战总结
本次 Nginx 安全防护与 HTTPS 部署实战,从基础编译安装 到核心安全配置 ,再到高级动态防护 和HTTPS 加密部署,形成了完整的 Nginx 安全防护体系,核心要点如下:
- 编译安装 Nginx 时,需启用
http_ssl_module、http_realip_module等安全模块,同时使用专用低权限用户运行; - 核心安全配置需做到:隐藏版本号、限制危险请求方法、限速防 CC 攻击、配置防盗链,从请求层阻断大部分攻击;
- 动态黑名单可实时封禁恶意 IP,结合 Shell 脚本和定时任务,实现自动化攻击防护;
- HTTPS 是公网站点的必备配置,采用混合加密模式,配置时需启用 TLS1.2/TLS1.3,同时实现 HTTP 到 HTTPS 的自动重定向;
- 测试环境使用自签名证书,生产环境需使用 CA 机构签发的证书(如 Let's Encrypt 免费证书),保障证书被公网信任。
通过以上配置,可大幅提升 Nginx 服务器的安全性和可靠性,有效抵御常见的网络攻击,同时满足数据隐私保护的法规要求。