Nginx安全防护与HTTPS部署实战

一.核心安全配置

1.编译安装Nginx

(1)安装支持软件

Nginx的配置及运行需要pcre、zlib等软件包的支持,因此应预先安装这些软件的开发包(devel),以便提供相应的库和头文件,确保Nginx的安装顺利完成

**命令:**dnf install -y gcc make pcre-devel zlib-devel openssl-devel perl-ExtUtils-MakeMaker git wget tar

(2)创建运行用户、组和日志目录

**命令:**useradd -M -s /sbin/nologin nginx

mkdir -p /var/log/nginx

chown -R nginx:nginx /var/log/nginx

(3)编译安装Nginx

**命令:**tar zxf nginx-1.26.3.tar.gz

cd nginx-1.26.3

./configure --prefix=/usr/local/nginx --pid-path=/var/run/nginx.pid --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream

make && make install

ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin (为主程序nginx创建链接文件)

(4)添加Nginx系统服务

命令:vim /lib/systemd/system/nginx.service

Unit

Description=The NGINX HTTP and reverse proxy server
After=network.target

Service

Type=forkingPIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/sbin/nginx -t
ExecStart=/usr/local/sbin/nginx
ExecReload=/usr/local/sbin/nginx-s reload
ExecStop=/bin/ki11 -S QUIT $MAINPID
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
User=root
Group=root

Install

WantedBy=multi-user.target

systemctl daemon-reload

systemctl start nginx

systemctl enable nginx

2.隐藏版本号

生产环境中,需要隐藏Nginx版本号,以避免Nginx的版本,使攻击者不能针对特定版本进行攻击。隐藏版本号之前,可以使用Fiddler工具抓取数据包查看Nginx版本,也可以在OpenEuler中使用curl -I 192.168.10.202查看

修改配置文件

**命令:**vim /usr/local/nginx/conf/nginx.conf

http {

include mime.types;

......

server_tokens off; (隐藏版本号)

nginx -t

nginx -s reload

3.限制危险请求方法

不安全的请求方式,是潜在的安全风险,TRACE(易引发XST攻击)、PUT/DELETE(文件修改风险)、CONNECT(代理滥用),通过正则表达式匹配请求方法,非白名单方法返回444(无响应关闭连接)

修改配置文件

命令:vim /usr/local/nginx/conf/nginx.conf

sercer {

.......

if (request_method ! \~ \^(GET\|HEAD\|POST)) {

return 444;

}

.......

}

测试PUT/DELETE请求

**命令:**curl -XPUT -I 192.168.10.202

测试TRACE和CONNECT方法时,状态码不是444的原因:

a.CONNECT请求的目标不是代理服务器时,服务器必须返回400 Bad Request,Nginx核心层在请求解析阶段直接拦截,根本不进入后续的location处理流程

b.现代Nginx默认禁用TRACE方法,在ngx_http_core_module阶段直接返回405Not Allowed

4.请求限制(CC攻击防御)

CC攻击是一种常见的网络攻击方式,通过大量合法或伪造小流量请求来耗尽服务器资源,导致正常用户无法访问网站。要在Nginx中有效防止CC攻击,可以采用多种策略和方法

CC攻击,也称为连接数攻击或请求速率限制攻击,通过模拟大量用户访问来消耗服务器资源,从而使得正常用户无法正常访问网站。为了防止此类攻击,可以使用Nginx提供的模块来限制请求速率和并发连接数

(1)使用Nginx的limit_req模块限制请求速率

编辑配置文件

命令:vim /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;

}

...

}

}

关键参数说明:

a.limit_req_zone定义共享内存区

b.$binary_remote_addr 是一个内置变量,用于表示客户端IP地址的二进制格式

c.zone=req_limit:10m 创建名为req_limit的共享内存区,大小10M,用来存储客户端Ip

d.rate=10r/s 限制并发数,每个IP每秒可以发起的请求次数

e.limit_req 实施速率限制

f.zone=req_limit 绑定到预定义的共享内存区

g.burst=20 类似与等候区,超出并发数的请求会到等候区,等候区占满后,多余的请求会立刻返回503

h.nodelay 立刻处理突发请求而不延迟,相当于立刻处理等候区的请求,多余的请求会立刻返回503

(2)压力测试验证

安装ab测试工具

ApacheBench(简称ab)是Apache HTTP服务器自带的一个轻量级,易用的HTTP服务器性能测试工具。主要用于评估服务器在并发访问下的性能表现,包括响应时间、吞吐量等关键指标。

**命令:**dnf install httpd-tools -y

发起测试请求

共发起300个请求,每次发起30个请求

**命令:**ab -n 300 -c 30 http://192.168.10.202/

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

**命令:**tail -300 /usr/local/nginx/logs/access.log | grep -c 503

5.防盗链

防盗链是一种重要的安全设置,旨在防止未经授权的用户盗用网站(静态)资源。盗链行为不仅侵犯了内容创作者的版权,还可能导致原网站带宽和资源的过度消耗,影响正常用户的访问速度和体验。

一般来说,用户浏览一个完整的页面并不是一次性全部传送到客户端的。如果所请求的页面带有图片或其他信息,那么第一个HTTP请求传送的是这个页面的文本,然后通过客户端的浏览器对这段文本进行解释执行。如果发现其中还有图片,那么客户端的浏览器会再次发送一条HTTP请求,当这个请求被处理后这个图片文件才会被传送到客户端,最后浏览器会将图片安放到页面的正确位置,就这样一个完整的页面要经过多次发送HTTP请求才能够被完整的显示。基于这样的机制,就会产生盗链问题:如果一个网站中没有其页面中所说图片信息,那么它完全可以链接到其他网站的图片信息上。这样,没有任何资源的网站利用了其他网站的资源来展示给浏览者,提高了自己的访问量,而大部分浏览者又不会很容易地发现。一些不良网站为了不增加成本而扩充自己站点内容,经常盗用其他网站的链接。一方面损害了原网站的合法利益,另一方面又加重了服务器的负期

|-----------|-------------|----------------|------|
| 操作系统 | 域名 | IP | 服务 |
| OpenEuler | www.aaa.com | 192.168.10.202 | 源主机 |
| OpenEuler | www.bbb.com | 192.168.10.201 | 盗链主机 |

(1)修改Windows的C:\Windows/System32\drivers\etc\hosts文件,设置域名和IP映射关系

192.168.10.202 www.aaa.com

192.168.10.201 www.bbb.com

(2)修改两台CentOS的hosts文件,设置域名和IP映射关系

192.168.10.202 www.aaa.com

192.168.10.201 www.bbb.com

(3)把图片logo.jpg放到源主机的工作目录下

命令:ls /usr/local/nginx/html

index.html kgc.png

(4)编辑源网站首页文件

命令:vim /usr/local/nginx/html/index.html

<html>

<body>

<h1>aaa It work!

<img src="kgc.png"/> (网页中显示图片的代码)

</h1>

</body>

</html>

(5)测试访问源网站

(6)编辑盗链网站首页文件

命令:vim /usr/local/nginx/html/index.html

<html>

<body>

<h1>bbb It work!

<img src="http://www.aaa.com/kgc.png"/> (网页中显示图片的代码)

</h1>

</body>

</html>

(7)测试访问盗链网站(盗链成功)

(8)配置Nginx防盗链

命令:vim /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

}

}

nginx -t

nginx -s reload

~*\.(jpglgif|swf)$:这段正则表达式表示匹配不区分大小写,以jpg或.gif或.swf结尾的文件;

Valid referers:设置信任的网站,可以正常使用图片;2

后面的网址或者域名:referer中包含相关字符串的网址:

>If语句:如果链接的来源域名不在validreferers所列出的列表中$invalid_referer为1,则执行后面的操作,即进行重写或返回403页面

(8)测试访问盗链网站(盗链失败)

二.高级防护

1.动态黑名单

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

(1)编辑黑名单配置文件

命令:vim /usr/local/nginx/conf/blockips.conf

192.168.1.0/24 1 ; #封禁整个网段

192.168.10.201 1 ;#封禁ip

IP地址后的数字含义

0 ""; # 允许

1 403; #完全封禁

2 444; #静默断开

3 503; #服务不可用

(3)编辑主配置文件

命令:vim /usr/local/nginx/conf/nginx.conf

http {

......

geo $block_ip {

default 0; #默认允许访问

include /usr/lcoal/nginx/conf/blockips.conf ; # 包含黑名单

}

......

server {

......

if ($block_ip) { #判断标记值

return 403 ; # 封禁动作

}

.......

}

}

nginx -t

nginx -s reload

geo:Nginx内置模块指令,专门用于处理ip地址相关的逻辑。基于客户端ip地址生成一个变量值,用于后续的访问控制判断

$block_ip:自定义的变量名,存储计算结果(通常为0或1)

default 0 :默认值,表示不在黑名单中的ip允许访问

if ($block_ip):当变量值为1时触发封禁逻辑

(3)使用封禁ip测试访问

命令:curl 192.168.10.202

<html>

<head><title>403 Forbidden</title></head>

<body>

<center><h1>403 Forbidden</h1></center>

<hr><center>nginx</center>

</body>

</html>

(4)自动添加黑名单

自动封禁访问超过100次的ip

#!/bin/bash

#自动封禁访问超过100次的IP

awk'{print l}'/var/log/nginx/access.logsort \|uniq -c\|sort -nrawk '{if(1>100) print $2"1;"}'>/usr/local/nginx/conf/blockips. conf

每小时更新攻击ip

#!/bin/bash

#每小时更新攻击IP

awk'/攻击特征/(print $l}'/var/log/nginx/access.logsort|uniq >/usr/local/nginx/conf/blockips. conf

2.nginx https配置

HTTP由于是明文传输,主要存在三大风险:窃听风险、篡改风险、冒充风险

2.1安全通信的四大原则

不难猜到 HTTPS就是为了解决上述三个风险而生的,一般我们认为安全的通信需要包括以下四个原则:机密性、完整性,身份认证和不可否认。
**机密性:**即对数据加密,解决了窃听风险,因为即使被中间人窃听,由于数据是加密的,他也拿不到明文;

**完整性:**指数据在传输过程中没有被篡改,不多不少,保持原样,中途如果哪怕改了一个标点符号,接收方也能识别出来,从来判定接收报文不合法;

**身份认证:**确认对方的真实身份,即证明"你妈是你妈"的问题,这样就解决了冒充风险,用户不用担心访问的是某宝结果却在和钓鱼网站通信的问题:

**不可否认:**即不可否认已发生的行为,比如小明向小红借了1000元,但没打借条,或者打了借条但没有签名,就会造成小红的资金损失。

2.2通信原理简述

既然HTTP是明文传输的,那我们给报文加密不就行了,既然要加密,我们肯定需要通信双方协商好密钥吧。一种是通信双方使用同一把密钥,即对称加密的方式来给报文进行加解密。

但是这里有一个关键问题:对称加密的通信双方要使用同一把密钥,这个密钥是如何协商出来的?如果通过报文的方式直接传输密钥,之后的通信其实还是在裸奔,因为这个密钥会被中间人截获甚至替换掉,这样中间人就可以用截获的密钥解密报文,甚至替换掉密钥以达到篡改报文的目的。

有人说对这个密钥再次加密不就完了,但对方如果要解密这个密钥,那还是要传加密密钥给对方,依然还是会被中间人截获的,这么看来直接传输密钥无论怎样都无法摆脱俄罗斯套娃的难题,是不可行的。

直接传输密钥无论从哪一端传从上节分析来看是不行了,这里我们再看另

种加密方式:非对称加密。非对称加密即加解密双方使用不同的密钥,一把作为公钥,可以公开的,把作为私钥,不能公开,公钥加密的密文只有私钥可以解密,私钥签名的内容,也只有公钥可以验签。这样的话对serve来说,保管好私钥,发布公钥给其他client,其他client只要把对称加密的密钥(或用于生成对称加密密钥的信息)使用公钥加密后传给server 即可。如此一来由于公钥加密只有私钥能解密,而私钥只有server 有所以能保证client向server传输是安全的,server解密后即可拿到对称加密密钥,这样交换了密钥之后就可以用对称加密密钥通信了。

但是问题又来了,server 怎么把公钥安全地传输给client呢???????

如果直接传公钥,也会存在被中间人调包的风险,好像没完没了了一样.........

数字证书,解决公钥传输信任问题

如何解决公钥传输问题呢?从现实生活中的场景找答案。员工入职时,企业般会要求提供学历证明,这个学历必须由第三方权威机构(CertificateAuthority证书颁发机构,简称CA)即教育部颁发。同理,server也可以向CA申请证书,在证书中附上公钥,然后将证书传给client。证书是由站点管理者向CA申请,申请的时候会提交域名、组织单位信息和公钥等数据(这些数据组成了 Certificate Signing,Reguest 证书签名请求,简称 CSR),CA会根据这些信息生成证书

这样当client拿到证书后,就可以获得证书上的公钥,再用此公钥加密对称加密密钥传给server即可。看起来确实很完美,不过在这里大家要考虑一个问题

想象一下上文中我们提到的学历,企业如何认定你提供的学历证书是真是假呢?答案是用学历编号,企业拿到证书后用学历编号在学信网上一查就知道证书真伪了,学历编号其实就是我们常说的证书的数字签名,可以防止证书造假。

证书的数字签名怎么来的?是使用的CA机构的私钥给CSR(确切来说是CSR生成的摘要信息)进行的签名,这样的话c1ient得用CA的公钥来给名解密才行,拿到的才是未经篡改合法的证书(私钥签名,公钥验签)

细心的你一定发现了问题,那CA 公钥又是如何安全地传输到client的?如果还是从server传输到client,依然无法解决公钥被调包的风险。实际上CA公钥是存在于CA证书上,而此证书(也称RootCA证书)被操作系统信任,内置在操作系统上的,无需传输,如果用的是windows的同学,可以通过:控制面板一>网络和Internet->Internet选项一>内容一>证书一>受信任的根证书颁发机构,可以看到很多内置的被信任的证书

https 总结:

server传输CA颁发的证书给client,client收到证书后使用系统内置的CA证书的公钥来验签,验签通过证明证书是受信任的,证书受信任那么证书中的公钥也就是受信任的,这样的话就解决了公钥传输过程中被调包的风险。

Client拿到server端的公钥后,使用公钥加密会话密钥(也就是对称加密的密钥),然后发送给服务端,服务端通过私钥解密获得会话密钥(对称加密的密钥),然后就可以安全愉快的进行数据传输了。

1.这里可能有同学会有疑问,为什么client拿到了server 给的公钥,不直接使用公钥进行加密通信,反而用公钥加密会话密钥,用会话密钥来加密通信,多此一举,这是因为会话密钥是对称加密,而对称加密的密钥管理简单且具有更高的加密和解密效率。所以https加密是混合模式,在握手阶段是非对称加密,在数据传输阶段是对称加密

2.还有个问题,中间人如果也去CA申请一个受信任的证书呢,把server发送的证书截取并替换成自己的行不行呢,答案是不行的,因为client除了要验证证书的合法性外,每个证书中包含的域名也是唯一的

相关推荐
用户962377954481 天前
VulnHub DC-3 靶机渗透测试笔记
安全
叶落阁主2 天前
Tailscale 完全指南:从入门到私有 DERP 部署
运维·安全·远程工作
十二7403 天前
前端缓存踩坑实录:从版本号管理到自动化构建
前端·javascript·nginx
可观测性用观测云3 天前
云原生网关 Ingress-Nginx 链路追踪实战:OpenTelemetry 采集与观测云集成方案
nginx·kubernetes
用户962377954484 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机5 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机5 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954485 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star5 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954485 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全