一.核心安全配置
1.隐藏版本号
在生产环境中,需要隐藏 Nginx 的版本号,以避免泄漏 Nginx 的版本,使攻击者不能针对特定版本进行攻击。在隐藏版本号之前,可以使用 Fiddler 工具抓取数据包,查看Nginx 版本,也可以在 OpenEuler 中使用命令 curl -I http://192.168.10.101/查看
2.限制危险请求方法
不安全的请求方式,是潜在的安全风险,TRACE(易引发XST攻击)、PUT/DELETE(文件修改风险)、CONNECT(代理滥用),通过正则表达式匹配请求方法,非白名单方法返回444(无响应关闭连接)
查看access.log
PS:注意测试TRACE和CONNECT方法时,状态码不是444(原因:1.CONNECT请求的目标不是代理服务器时,服务器必须返回400 Bad Request,Nginx核心层在请求解析阶段直接拦截,根本不进入后续的location处理流程 2.现代Nginx默认禁用TRACE方法,在ngx_http_core_module阶段直接返回405 Not Allowed)
3.请求访问限制(cc攻击防御)
CC攻击(Challenge Collapsar攻击)是一种常见的网络攻击方式,通过大量合法或伪造的小流量请求来耗尽服务器资源,导致正常用户无法访问网站。要在Nginx中有效防止CC攻击,可以采用多种策略和方法。
CC攻击,也称为连接数攻击或请求速率限制攻击,通过模拟大量用户访问来消耗服务器资源,从而使得正常用户无法正常访问网站。为了防止此类攻击,可以使用Nginx提供的模块来限制请求速率和并发连接数
①使用nginx的limit req模块限制请求速率
关键参数说明:
limit_req_zone定义共享内存区
$binary_remote_addr 是一个内置变量,用于表示客户端 IP 地址的二进制格式
zone=req_limit:10m 创建名为req_limit的共享内存区,大小10M,用来存储客户端 IP
rate=10r/s 限制并发数,每个IP每秒可以发起的请求次数
limit_req实施速率限制
zone=req_limit 绑定到预定义的共享内存区
burst=20 类似与等候区,超出并发数的请求会到等候区,等候区占满后,多余的请求会立刻返回503
nodelay 立即处理突发请求而不延迟,相当于立即处理等候区的请求,多余的请求会立刻返回503
②压力测试验证
ApacheBench(简称ab)是Apache HTTP服务器自带的一个轻量级、易用的HTTP服务器性能测试工具。它主要用于评估服务器在并发访问下的性能表现,包括响应时间、吞吐量等关键指标
发起测试请求
共发起300个请求,每次发起30个请求
查看日志文件
5.防盗链
防盗链是一种重要的安全设置,旨在防止未经授权的用户盗用网站(静态)资源。盗链行为不仅侵犯了内容创作者的版权,还可能导致原网站带宽和资源的过度消耗,影响正常用户的访问速度和体验。
一般来说,用户浏览一个完整的页面并不是一次性全部传送到客户端的。如果所请求的页面带有图片或其他信息,那么第一个 HTTP 请求传送的是这个页面的文本,然后通过客户端的浏览器对这段文本进行解释执行。如果发现其中还有图片,那么客户端的浏览器会再次发送一条 HTTP 请求,当这个请求被处理后这个图片文件才会被传送到客户端,最后浏览器会将图片安放到页面的正确位置,就这样一个完整的页面要经过多次发送 HTTP 请求才能够被完整的显示。基于这样的机制,就会产生盗链问题:如果一个网站中没有其页面中所说图片信息,那么它完全可以链接到其他网站的图片信息上。这样,没有任何资源的网站利用了其他网站的资源来展示给浏览者,提高了自己的访问量,而大部分浏览者又不会很容易地发现。一些不良网站为了不增加成本而扩充自己站点内容,经常盗用其他网站的链接。一方面损害了原网站的合法利益,另一方面又加重了服务器的负担
①修改windows映射文件 C:\windows\system32\drivers\etc\hosts文件,设置和IP地址映射关系
②修改两台 OpenEuler 的 hosts 文件,设置域名和 IP 映射关系
③把图片放到源主机工作目录下网页目录
④编辑原网站首页文件
⑤访问源主机网站内容
⑥设置防盗链主机网站
⑦测试访问盗链网站(盗链成功)
⑦配置 Nginx 防盗链
二.高级防护
1.动态黑名单
动态黑名单是Nginx中一种实时拦截恶意请求的安全机制,它允许在不重启服务的情况下,动态更新需要封禁的IP地址或网段。相比静态配置的allow/deny指令,动态黑名单更灵活高效,适用于高并发、多变的攻击防护场景。
①编辑黑名单配置文件
IP地址后的数字含义:
0 “”; # 允许
1 403; # 完全封禁
2 444; # 静默断开
3 503; # 服务不可用
②主配置文件
geo:Nginx 内置模块指令,专门用于处理 IP 地址相关的逻辑。基于客户端 IP 地址生成一个变量值,用于后续的访问控制判断
b
l
o
c
k
i
p
:自定义的变量名,存储计算结果(通常为
0
或
1
)。
d
e
f
a
u
l
t
0
:默认值,表示不在黑名单中的
I
P
允许访问
i
f
(
block_ip:自定义的变量名,存储计算结果(通常为 0 或 1)。 default 0: 默认值,表示不在黑名单中的IP允许访问 if (
blockip:自定义的变量名,存储计算结果(通常为0或1)。default0:默认值,表示不在黑名单中的IP允许访问if(block_ip):当变量值为1时触发封禁逻辑
③使用封禁ip测试访问
2.https概念
HTTPS,全称HyperText Transfer Protocol over Secure Socket Layer,设计初衷是为了保证数据传输安全。国内大型互联网巨头在2016开始大力推行https,期间关于https的重大事件有
Google搜索引擎让https的网站在搜索排名中更靠前。
从2017年开始,chrome浏览器把只采用http的网站标记为不安全网站。
苹果要求App Store中的所有应用都必须使用https加密链接。
微信小程序也要求必须使用https。
新一代的http/2协议的支持需要以https为基础
众所周知,http(超文本传输协议)是客户端浏览器与web服务器之间的通信协议,而https协议可以认为是HTTP + SSL/TLS,在http之下tcp之上加了ssl一层,用于对应用层数据的加解密
SSL:由Netscape公司开发,专门用于保护Web通讯。SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为SSL记录协议(SSL Record Protocol)和SSL握手协议(SSL Handshake Protocol)两层。SSL经历了多个版本的迭代,包括从未公开发布的SSL 1.0、存在严重安全漏洞且现已废弃的SSL 2.0、在2014年因POODLE攻击漏洞而被逐步淘汰的SSL 3.0。
TLS:是IETF(Internet Engineering Task Force,互联网工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。从历史上看,TLS对SSL首先是继承关系,后来逐步发展并取代了SSL,成为当前主流的网络安全协议。TLS经历了多个版本的演进,包括TLS 1.0(1999年发布,基于SSL 3.0但进行了改进)、TLS 1.1(2006年发布,增加了对CBC攻击的保护)、TLS 1.2(2008年发布,引入了更强大的加密算法,如AES)和TLS 1.3(2018年发布,进一步简化了握手过程,提高了性能和安全性)。值得注意的是,TLS 1.0和TLS 1.1也在2021年被正式弃用
2.HTTP为什么不安全
窃听风险
篡改风险
冒充风险
HTTPS 显然是为了解决这三大风险而存在的
3.安全通信四大原则
不难猜到 HTTPS 就是为了解决上述三个风险而生的,一般我们认为安全的通信需要包括以下四个原则: 机密性、完整性,身份认证和不可否认。
机密性:即对数据加密,解决了窃听风险,因为即使被中间人窃听,由于数据是加密的,他也拿不到明文;
完整性:指数据在传输过程中没有被篡改,不多不少,保持原样,中途如果哪怕改了一个标点符号,接收方也能识别出来,从来判定接收报文不合法;
身份认证:确认对方的真实身份,即证明“你妈是你妈”的问题,这样就解决了冒充风险,用户不用担心访问的是某宝结果却在和钓鱼网站通信的问题;
不可否认: 即不可否认已发生的行为,比如小明向小红借了 1000 元,但没打借条,或者打了借条但没有签名,就会造成小红的资金损失
4.HTTPS 通信原理简述
既然 HTTP 是明文传输的,那我们给报文加密不就行了,既然要加密,我们肯定需要通信双方协商好密钥吧。一种是通信双方使用同一把密钥,即对称加密的方式来给报文进行加解密
如图示:使用对称加密的通信双方使用同一把密钥进行加解密。
但是这里有一个关键问题:对称加密的通信双方要使用同一把密钥,这个密钥是如何协商出来的?如果通过报文的方式直接传输密钥,之后的通信其实还是在裸奔,因为这个密钥会被中间人截获甚至替换掉,这样中间人就可以用截获的密钥解密报文,甚至替换掉密钥以达到篡改报文的目的
有人说对这个密钥再次加密不就完了,但对方如果要解密这个密钥,那还是要传加密密钥给对方,依然还是会被中间人截获的,这么看来直接传输密钥无论怎样都无法摆脱俄罗斯套娃的难题,是不可行的。
直接传输密钥无论从哪一端传从上节分析来看是不行了,这里我们再看另一种加密方式:非对称加密。
非对称加密即加解密双方使用不同的密钥,一把作为公钥,可以公开的,一把作为私钥,不能公开,公钥加密的密文只有私钥可以解密,私钥签名的内容,也只有公钥可以验签。
这样的话对serve来说,保管好私钥,发布公钥给其他 client, 其他 client 只要把对称加密的密钥(或用于生成对称加密密钥的信息)使用公钥加密后传给 server 即可。如此一来由于公钥加密只有私钥能解密,而私钥只有 server 有,所以能保证 client 向 server 传输是安全的,server 解密后即可拿到对称加密密钥,这样交换了密钥之后就可以用对称加密密钥通信了。
但是问题又来了, server 怎么把公钥安全地传输给 client 呢???????如果直接传公钥,也会存在被中间人调包的风险,好像没完没了了一样…
数字证书,解决公钥传输信任问题
如何解决公钥传输问题呢?从现实生活中的场景找答案。员工入职时,企业一般会要求提供学历证明,这个学历必须由第三方权威机构(Certificate Authority 证书颁发机构,简称 CA)即教育部颁发。同理,server 也可以向 CA 申请证书,在证书中附上公钥,然后将证书传给 client。
证书是由站点管理者向 CA 申请,申请的时候会提交域名、组织单位信息和公钥等数据(这些数据组成了Certificate Signing Request 证书签名请求,简称CSR),CA会根据这些信息生成证书
这样当 client 拿到证书后,就可以获得证书上的公钥,再用此公钥加密对称加密密钥传给 server 即可。看起来确实很完美,不过在这里大家要考虑一个问题
想象一下上文中我们提到的学历,企业如何认定你提供的学历证书是真是假呢?答案是用学历编号,企业拿到证书后用学历编号在学信网上一查就知道证书真伪了,学历编号其实就是我们常说的证书的数字签名,可以防止证书造假。
证书的数字签名怎么来的?是使用的CA机构的私钥给CSR(确切来说是CSR生成的摘要信息)进行的签名,这样的话 client 得用 CA 的公钥来给签名解密才行,拿到的才是未经篡改合法的证书(私钥签名,公钥验签)
细心的你一定发现了问题,那CA 公钥又是如何安全地传输到 client 的?如果还是从 server 传输到 client,依然无法解决公钥被调包的风险。实际上CA公钥是存在于 CA 证书上,而此证书(也称 Root CA 证书)被操作系统信任,内置在操作系统上的,无需传输,如果用的是windows的同学,可以通过:控制面板—>网络和 Internet—>Internet选项—>内容—>证书—>受信任的根证书颁发机构,可以看到很多内置的被信任的证书
5.nginx 配置https 证书
由于ssl证书需要向CA组织申购,实验采用自签名证书(也就是自己给自己签名并颁发证书,当然这种证书是不被信任的)
①使用 openssl 生成证书和私钥生成证书和私钥
创建证书存储目录
参数解释:
-x509: 生成自签名证书(而非CSR)。
-nodes: 不加密私钥(无密码保护)。
-days 365: 证书有效期1年。
-keyout: 私钥文件。
-out: 自签名文件。
-newkey rsa:2048: 生成2048位的RSA私钥。
-subj: 证书主题信息(按需修改字段)。
CA签名证书:
需要由受信任的第三方证书颁发机构(CA)签发。流程如下:
1.用户生成私钥和CSR(证书签名请求)。
2.将CSR提交给CA(如Let’s Encrypt、DigiCert等)。
3.CA机构验证身份后,用CA的私钥对证书签名,生成最终证书。
自签名证书:
证书的颁发者(Issuer)和主体(Subject)是同一个实体(即自己)。
无需第三方CA参与,直接用工具(如OpenSSL)生成私钥和证书。
签名时使用自己的私钥,而不是CA的私钥。
适用于测试、内部环境或无需公开信任的场景。
③启用https