nginx安全防护与HTTPS部署实战

目录

核心安全配置nginx

隐藏版本号

限制危险请求的方法

请求限制(cc攻击防御)

使用Nginx的linit_req模块限制请求速率

压力测试验证

防盗链

高级防护动态黑名单

[nginx https配置](#nginx https配置)

HTTP为什么不安全

安全通信的四大原则

HTTPS通信原理简述

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

nginx配置htps证书


核心安全配置nginx

安装支持软件

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

复制代码
[root@localhost ^]# dnf install -y gcc make pcre-develzlib-devel
openssl-devel perl-ExtUtils-MakeMaker git wget tar

创建运行用户,组和日志目录

复制代码
[root@localhost~]# useradd -M -s /sbin/nologin nginx
[root@localhost~]# mkdir -p /var/log/nginx
[root@localhost~]# chown -R nginx:nginx /var/log/nginx

编译安装nginx

复制代码
[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\
--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
[root@localhost nginx-1.26.3]# make & make install

为程序nfinx创建链接文件

复制代码
[root@localhost_nginx-1.26.3]# ln -s /usr/local/nginx/sbin/nginx
/usr/local/sbin/

添加nginx系统服务

复制代码
[root@localhost ~]# vim /lib/systemd/system/nginx. seervice
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target
[Service]
Type=forking
PIDFile=/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/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

隐藏版本号

在 Nginx 中隐藏版本号可以提高服务器的安全性,减少因版本信息泄露而可能带来的潜在风险。以下是隐藏 Nginx 版本号的几种方法

通过配置文件隐藏

在 Nginx 的配置文件(通常是nginx.conf)中,找到http块或者server块,添加或修改以下配置项

复制代码
server_tokens off;

该配置项用于关闭 Nginx 在响应头中发送服务器版本号等信息。修改配置文件后,需要重新加载 Nginx 配置使更改生效。可以使用以下命令重新加载 Nginx 配置

复制代码
nginx -s reload

通过编译参数隐藏

在编译 Nginx 源代码时,可以通过指定--with-http_headers_more_module模块,并在配置文件中使用more_set_headers指令来隐藏版本号。例如,在编译 Nginx 时添加以下参数

复制代码
./configure --with-http_headers_more_module

然后在 Nginx 配置文件中添加如下配置

复制代码
server {
    listen       80;
    server_name  example.com;

    more_set_headers 'Server: nginx';
    # 其他配置项...
}

这样设置后,服务器返回的响应头中Server字段将显示为nginx,而不是具体的版本号

使用第三方模块隐藏

可以使用一些第三方的 Nginx 模块来更灵活地处理服务器响应头信息,从而隐藏版本号。例如,ngx_http_headers_module模块可以用于修改和删除响应头中的字段。首先需要安装该模块,然后在 Nginx 配置文件中进行如下配置

复制代码
server {
    listen       80;
    server_name  example.com;

    add_header Server nginx;
    # 或者使用以下方式直接删除Server头字段
    # add_header Server "" always;

    # 其他配置项...
}

上述配置中,通过add_header指令将Server头字段设置为自定义的值,或者将其设置为空字符串来隐藏版本号

限制危险请求的方法

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

复制代码
[root@localhost ~]#vim /usr/local/nginx/conf/nginx.conf
vim /usr/local/nginx/conf/nginx.conf
server {
if($request_method !~~(GET|HEAD|POST)$){
return 444;
}
}

测试

复制代码
[root@localhost ^]#curl -XPUT -I 192.168.10.202
curl: (52) Empty reply from server

PS:注意测试TRACE和CONNECT方法时,状态码不是444(原因:1.CONNECT请

求的目标不是代理服务器时,服务器必须返回400BadRequest,Nginx核心层

在请求解析阶段直接拦截,根本不进入后续的location处理流程2.现代Nginx

默认禁用TRACE方法,在ngx_http_core_module阶段直接返回405 Not Allowed)

请求限制(cc攻击防御)

CC攻击(ChallengeCollapsar攻击)是一种常见的网络攻击方式,通过大
量合法或伪造的小流量请求来耗尽服务器资源,导致正常用户无法访问网站。要
在Nginx中有效防止CC攻击,可以采用多种策略和方法。
CC攻击,也称为连接数攻击或请求速率限制攻击,通过模拟力量用户访问
来消耗服务器资源,从而使得正常用户无法正常访问网站。为了防止此类攻击,
可以使用Nginx提供的模块来限制请求速率和并发连接数

使用Nginx的linit_req模块限制请求速率

limit_req 模块是 Nginx 用于限制客户端请求速率的强大工具。它可以有效防止服务器因过多请求而过载

配置速率限制区域

你要在 http 块中定义一个速率限制区域。此区域可跟踪客户端的请求,并按照指定的速率进行限制

复制代码
http {
    # 定义一个名为 one 的速率限制区域,大小为 10m,速率为每秒 1 个请求
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    ...
}

在上述代码里,$binary_remote_addr 表示客户端的 IP 地址,zone=one:10m 定义了名为 one 的区域,其大小为 10MB,rate=1r/s 意味着每秒最多允许 1 个请求

应用速率限制

在需要进行速率限制的 server 或者 location 块中运用该速率限制区域

复制代码
server {
    ...
    location / {
        # 应用名为 one 的速率限制区域
        limit_req zone=one;
        ...
    }
}

处理突发请求 要是你期望允许一定数量的突发请求,可以添加 burst 参数

复制代码
server {
    ...
    location / {
        # 应用名为 one 的速率限制区域,允许 5 个突发请求
        limit_req zone=one burst=5;
        ...
    }
}

在这个配置里,burst=5 表明允许最多 5 个突发请求。若请求速率超出限制,多余的请求会被放入队列,直至队列满了,才会返回 503 错误

完整配置示例

复制代码
http {
    # 定义一个名为 one 的速率限制区域,大小为 10m,速率为每秒 1 个请求
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        location / {
            # 应用名为 one 的速率限制区域,允许 5 个突发请求
            limit_req zone=one burst=5;
            proxy_pass http://backend;
        }
    }
}

重新加载 Nginx 配置在完成配置文件的修改之后,要重新加载 Nginx 配置,使新的配置生效

复制代码
sudo nginx -s reload

通过上述步骤,你就可以使用 limit_req 模块对 Nginx 的请求速率进行限制了

压力测试验证

安装ab测试工具
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.202/

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

复制代码
[root@localhost ^]#tail -300 /usr/local/nginx/logs/acocess. log | grep-c503

防盗链

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

基于 valid_referers 指令的简单防盗链

可以利用 valid_referers 指令指定允许的引用页面(即哪些网站可以引用你的资源),对于不在列表中的引用,可返回 403 状态码

复制代码
server {
    listen 80;
    server_name yourdomain.com;

    location ~* \.(jpg|jpeg|png|gif)$ {
        valid_referers none blocked yourdomain.com *.yourdomain.com;
        if ($invalid_referer) {
            return 403;
        }
        root /path/to/your/images;
    }
}

使用 secure_link 模块进行高级防盗链secure_link 模块可以通过生成加密的链接来实现更高级的防盗链功能,只有拥有有效链接的用户才能访问资源

首先,在 Nginx 配置文件中启用 secure_link 模块配置nginx

复制代码
server {
    listen 80;
    server_name yourdomain.com;

    location /protected/ {
        secure_link $arg_md5,$arg_expires;
        secure_link_md5 "$secure_link_expires$uri yoursecretkey";

        if ($secure_link = "") {
            return 403;
        }
        if ($secure_link = "0") {
            return 410;
        }

        root /path/to/your/protected/files;
    }
}
生成安全链接

在你的应用程序中,可以使用以下 Python 代码生成安全链接

复制代码
import hashlib
import time

def generate_secure_link(uri, secret_key, expires_in=3600):
    expires = int(time.time()) + expires_in
    md5 = hashlib.md5(f"{expires}{uri} {secret_key}".encode('utf-8')).hexdigest()
    return f"http://yourdomain.com{uri}?md5={md5}&expires={expires}"

# 示例
uri = "/protected/file.jpg"
secret_key = "yoursecretkey"
link = generate_secure_link(uri, secret_key)
print(link)

重新加载 Nginx 配置完成配置文件的修改后,需要重新加载 Nginx 配置,使新的配置生效

复制代码
sudo nginx -s reload

高级防护动态黑名单

安装必要的组件要保证 Nginx 已经安装了 Lua 模块(ngx_http_lua_module),同时安装 Redis 数据库

配置 Nginx

在 Nginx 配置文件里添加如下内容

复制代码
http {
    # 加载 Lua 模块
    lua_shared_dict blacklist 10m;
    init_by_lua_block {
        -- 连接 Redis
        local redis = require "resty.redis"
        local red = redis:new()
        red:set_timeout(1000) -- 1 秒超时

        local ok, err = red:connect("127.0.0.1", 6379)
        if not ok then
            ngx.log(ngx.ERR, "Failed to connect to Redis: ", err)
            return
        end

        -- 从 Redis 加载黑名单到共享字典
        local res, err = red:keys("blacklist:*")
        if res then
            for _, key in ipairs(res) do
                local ip = string.sub(key, 11)
                ngx.shared.blacklist:set(ip, true)
            end
        end

        -- 定期从 Redis 同步黑名单
        local function sync_blacklist()
            while true do
                ngx.sleep(60) -- 每分钟同步一次
                local ok, err = red:connect("127.0.0.1", 6379)
                if not ok then
                    ngx.log(ngx.ERR, "Failed to connect to Redis: ", err)
                    goto continue
                end

                local res, err = red:keys("blacklist:*")
                if res then
                    ngx.shared.blacklist:flush_all()
                    for _, key in ipairs(res) do
                        local ip = string.sub(key, 11)
                        ngx.shared.blacklist:set(ip, true)
                    end
                end
                ::continue::
            end
        end

        ngx.timer.at(0, sync_blacklist)
    }

    server {
        listen 80;
        server_name yourdomain.com;

        access_by_lua_block {
            local ip = ngx.var.remote_addr
            if ngx.shared.blacklist:get(ip) then
                ngx.exit(ngx.HTTP_FORBIDDEN)
            end
        }

        location / {
            # 其他配置
        }
    }
}

管理黑名单

可以使用 Redis 命令来管理黑名单添加 IP 到黑名单

复制代码
redis-cli set blacklist:192.168.1.1 true

从黑名单中移除 IP

复制代码
redis-cli del blacklist:192.168.1.1

重新加载 Nginx 配置完成配置文件的修改后,重新加载 Nginx 配置,使新的配置生效

复制代码
sudo nginx -s reload

[nginx https配置](#nginx https配置)

HTTPS,全称HyperText Transfer Protocol over SecureSocket Layer,

设计初衷是为了保证数据传输安全。国内大型互联网巨头在2016开始大力推行

https,期间关于https的重大事件有众所周知,http(超文本传输协议)是客户端浏览器与vveb服务器之间的通

信协议,而https协议可以认为是HTTP+SSL/TLS,在http下tcp之上加了

ss1一层,用于对应用层数据的加解密如图

|---------|
| HTTP |
| SSL/TSL |
| TCP |
| IP |

SSL:由Netscape公司开发,专门用于保护Web通讯。SSL协议位于TCP/IP

协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议又可分为SSL记

录协议(SSLRecord Protocol)和SSL握手协议(SSLHaIndshake Protocol)

两层。SSL经历了多个版本的迭代,包括从未公开发布的SSL1.0、存在严重安

全漏洞且现已废弃的SSL2.0、在2014年因POODLE攻击漏洞而被逐步淘汰的SSL

3.0TLS:是IETF (Internet Engineering Task Foorce,互联网工程任务组)

制定的一种新的协议,它建立在SSL3.0协议规范之上,是SSSL3.0的后续版本。

从历史上看,TLS对SSL首先是继承关系,后来逐步发展并取代了SSL,成为当

前主流的网络安全协议。TLS经历了多个版本的演进,包括TLS 1.0(1999年发

布,基于SSL3.0但进行了改进)、TLS 1.1(2006年发布,增加了对CBC攻击

的保护)、TLS1.2(2008年发布,引入了更强大的加密算法、如AES)和TLS1.3

(2018年发布,进一步简化了握手过程,提高了性能和安全性)。值得注意的

是,TLS 1.0和TLS1.1也在2021年被正式弃用

HTTP为什么不安全

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

安全通信的四大原则

不难猜到HTTPS就是为了解决上述三个风险而生的,一般我们认为安全的
通信需要包括以下四个原则:机密性、完整性,身份认证和不可可否认
机密性:即对数据加密,解决了窃听风险,因为即使被中间间人窃听,由于数
据是加密的,他也拿不到明文;
完整性:指数据在传输过程中没有被篡改,不多不少,保持原样,中途如果
哪怕改了一个标点符号,接收方也能识别出来,从来判定接收报文不合法:
身份认证:确认对方的真实身份,即证明"你妈是你妈"的问题,这样就解
决了冒充风险,用户不用担心访问的是某宝结果却在和钓鱼鱼网站通信的问题:
不可否认:即不可否认已发生的行为,比如小明向小红借了1000元,但没
打借条,或者打了借条但没有签名,就会造成小红的资金损失。

HTTPS通信原理简述

HTTPS(Hypertext Transfer Protocol Secure)即超文本传输安全协议,它的通信原理主要涉及以下几个关键步骤

  1. 客户端发起请求:客户端(如浏览器)向服务器发送一个 HTTPS 请求,请求中包含了客户端支持的加密算法、密钥交换方式等信息。
  2. 服务器响应:服务器收到请求后,会根据客户端提供的信息,选择双方都支持的加密算法和密钥交换方式,并将服务器的数字证书发送给客户端。数字证书包含了服务器的公钥、证书颁发机构(CA)的信息以及证书的有效期等内容。
  3. 客户端验证证书:客户端收到服务器的数字证书后,会验证证书的合法性。它会检查证书是否由受信任的 CA 颁发,证书是否在有效期内,以及证书中的域名是否与请求的域名一致等。如果证书验证通过,客户端就可以从证书中提取出服务器的公钥。
  4. 生成会话密钥:客户端生成一个随机的会话密钥,然后使用服务器的公钥对会话密钥进行加密,并将加密后的会话密钥发送给服务器。
  5. 服务器解密会话密钥:服务器使用自己的私钥解密客户端发送的加密会话密钥,从而得到客户端生成的会话密钥。
  6. 加密通信:双方使用会话密钥对后续通信的数据进行加密和解密。客户端将请求数据使用会话密钥加密后发送给服务器,服务器收到加密数据后,使用会话密钥进行解密并处理请求。然后,服务器将响应数据使用会话密钥加密后发送给客户端,客户端收到后再使用会话密钥解密得到响应内容

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

数字证书的概念

数字证书是一种由权威的证书颁发机构(CA)颁发的电子文件,它将公钥与拥有该公钥的实体(如网站、用户等)的身份信息绑定在一起。证书中包含了公钥、证书持有者的身份信息、证书颁发机构的信息、有效期等内容,并由证书颁发机构使用其私钥对这些信息进行数字签名

解决信任问题的原理

认证证书颁发机构:在 HTTPS 通信中,客户端浏览器内置了一些受信任的根证书颁发机构的公钥。当客户端收到服务器发送的数字证书时,它会首先检查证书的颁发机构是否在受信任的列表中。如果是,客户端就信任该颁发机构。

验证数字签名:客户端使用证书颁发机构的公钥来验证数字证书上的签名。由于数字签名是由证书颁发机构使用其私钥生成的,只有使用对应的公钥才能成功验证。如果签名验证通过,客户端就可以确认证书中的公钥确实是由该证书颁发机构颁发的,并且证书在传输过程中没有被篡改。

绑定身份和公钥:数字证书将服务器的身份信息(如域名)与公钥绑定在一起。客户端通过验证证书中的域名与自己请求的域名是否一致,来确认所获取的公钥是否属于正确的服务器,从而防止中间人攻击。例如,攻击者不能将自己的公钥伪装成某个合法网站的公钥,因为其数字证书中的域名与合法网站的域名不匹配,客户端会发现这种不一致并拒绝连接

nginx配置htps证书

准备证书文件

你需要拥有有效的 SSL/TLS 证书文件,一般包含一个 .crt.pem 格式的证书文件和一个 .key 格式的私钥文件

备份 Nginx 配置文件

在修改配置文件之前,最好先进行备份,以防配置错误导致 Nginx 无法正常工作

复制代码
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.backup

配置 Nginx 以使用 HTTPS

编辑 Nginx 的配置文件,通常位于 /etc/nginx/sites-available/ 目录下

复制代码
server {
    listen 80;
    server_name your_domain_or_ip;
    # 将所有 HTTP 请求重定向到 HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name your_domain_or_ip;

    # 证书文件路径
    ssl_certificate /path/to/your_certificate.crt;
    ssl_certificate_key /path/to/your_private_key.key;

    # SSL 协议和加密套件配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;

    # 其他配置
    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

检查配置文件语法

复制代码
nginx -t

重启服务

复制代码
systemctl restart nginx
相关推荐
用户962377954481 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机1 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机1 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954481 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star1 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954481 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
小时前端1 天前
HTTPS 页面加载 HTTP 脚本被拦?同源代理来救场
前端·https
闲云一鹤2 天前
nginx 快速入门教程 - 写给前端的你
前端·nginx·前端工程化
cipher3 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全