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
相关推荐
Blossom.1184 小时前
机器学习在网络安全中的应用:守护数字世界的防线
人工智能·深度学习·神经网络·安全·web安全·机器学习·计算机视觉
计算机毕设定制辅导-无忧学长5 小时前
ActiveMQ 安全机制与企业级实践(一)
安全·activemq
Lw老王要学习6 小时前
25_05_02Linux架构篇、第1章_03安装部署nginx
linux·运维·nginx·架构·云计算·it
IT成长日记6 小时前
【Hive入门】Hive安全管理与权限控制:审计日志全解析,构建完善的操作追踪体系
hive·hadoop·安全·审计日志
夜风Sec11 小时前
【挖洞利器】Goby&Awvs&解放双手
安全
柴郡猫^O^11 小时前
OSCP - Proving Grounds - NoName
安全·网络安全·安全性测试
极小狐11 小时前
极狐Gitlab 里程碑功能介绍
运维·数据库·安全·c#·gitlab
Hello.Reader11 小时前
NGINX `ngx_http_auth_request_module` 模块详解基于子请求的认证授权方案
运维·nginx·http
IT主机CV12 小时前
端口安全基本配置
服务器·网络·安全
IT成长日记12 小时前
【Hive入门】Hive安全管理与权限控制:用户认证与权限管理深度解析
hive·hadoop·安全·权限管理·用户认证