继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Nginx高级安全加固指南

慕运维8079593
关注TA
已关注
手记 247
粉丝 19
获赞 62

Nginx 是最常用的网页服务器之一,并已成为现代企业架构的重要组成部分。在这篇文章里,我们会看看简化监控、提高性能和加强安全的配置选项——最终增强您基础设施的韧性。

图片由 Taylor Vick 拍摄,来自 Unsplash

JSON 日志

JSON 是 Nginx 日志文件的一个非常好的格式,有以下两个原因。首先,它更易于阅读。其次,将日志传输到 OpenSearch 等系统以进行进一步监控或 SIEM 处理变得更加简单。

这里有一个简单的 nginx.conf 示例:

    log_format json-logger escape=json '{  
       "type": "访问日志条目",  
       "time": "$time_iso8601",  
       "远端IP": "$remote_addr",  
       "X-Forwarded-For": "$proxy_add_x_forwarded_for",  
       "请求ID": "$request_id",  
       "请求长度": "$request_length",  
       "响应字节数": "$bytes_sent",  
       "响应体大小": "$body_bytes_sent",  
       "状态码": "$status",  
       "虚拟主机": "$host",  
       "协议": "$server_protocol",  
       "路径": "$uri",  
       "查询字符串": "$args",  
       "请求耗时": "$request_time",  
       "后端响应时间": "$upstream_response_time",  
       "后端状态码": "$upstream_status",  
       "请求方法": "$request_method",  
       "Referer": "$http_referer",  
       "User-Agent": "$http_user_agent",  
       "活动连接数": "$connections_active"  
      }';  

     access_log /var/log/nginx/access.log json-logger;

这导致了以下内容出现在 access.log 文件中:

    {  
       "type": "访问日志条目",  
       "time": "2025-02-25T16:02:54+00:00",  
       "remote-ip": "130.61.78.239",  
       "x-forward-for": "X-Forwarded-For",  
       "request-id": "38750f2a1a51b196fa0a76025b0d1be9",  
       "request-length": "258",  
       "response-bytes": "353",  
       "response-body-size": "响应体大小",  
       "status": "404",  
       "vhost": "3.69.78.187",  
       "protocol": "HTTP/1.1",  
       "path": "/lib/phpunit/Util/PHP/eval-stdin.php",  
       "query": "",  
       "duration": "0.016",  
       "backend-duration": "0.016",  
       "backend-status": "404",  
       "method": "GET",  
       "referer": "",  
       "user-agent": "Custom-AsyncHttpClient",  
       "active-connections": "活动连接数"  
      }
请求参数设置

较大的请求体大小、较长的超时时间和过长的长连接(KeepAlive)设置会显著影响性能。为了优化效率,尽量将这些参数设得小一些——但仍要满足应用程序的需求。

来自nginx.conf的一个例子:

client_max_body_size 10M;  # 设置客户端请求的最大大小为10MB
client_body_timeout 10s;  # 设置客户端请求体超时时间为10秒
client_header_timeout 10s;  # 设置客户端请求头超时时间为10秒
keepalive_timeout 5s 5s;  # 设置keep-alive连接超时时间为5秒,分别针对客户端和服务端

**client_max_body_size**
定义了客户端发送 HTTP 请求正文的最大允许大小。如果超过限制,Nginx 会返回 413 Request Entity Too Large 错误。

**client_body_timeout**
设定Nginx等待完整请求数据的最大时限。如果在此时间内仍未收到完整的请求数据,连接将会被关闭。

**client_header_timeout**
设置Nginx等待客户端发送完整HTTP头的最长等待时间。如果超时,连接将被关闭。

**keepalive_timeout**
定义了在最后一个请求之后,连接保持开启的时间长度。第一个值(例如 5s)设置了超时时间。并将此建议发送给客户端,建议保持连接开启的时间长度。

限制请求

如果客户端试图通过发送大量请求来淹没 web 服务器,Nginx 提供了配置“限制请求的数量区域”的选项,可以根据不同的参数限制请求的流量。

这里有个例子(反向代理,并设置了请求速率限制):

限制请求区域 $binary_remote_addr 区域=限制请求区域byaddr:20m 率=15r/s;
限制请求状态 429;

上游 app.localhost {
  服务器 localhost:8080;
}

服务器 {
  监听 443 ssl;
  服务器名称 app.devlab.intern;

  位置 / {
    限制请求 区域=限制请求区域byaddr 突增=10;
    代理传递 http://app.localhost;
  }
}

**$binary_remote_addr**
配置一个基于IP地址的请求限制,以限制每个IP地址的请求次数。

**zone=limitreqsbyaddr:20m**
创建一个名为 limitreqsbyaddr 的共享内存区域,大小为 20 MB,。这个区域用来存储不同 IP 地址的限速数据。

**请求速率=15r/s**
限制每个IP每秒最多15个请求。如果客户端超过此限制,超出的请求将被拒绝。

**limit_req_status 429;**
当请求速率超出限制时,返回 429 请求过多 状态码,表示在设定的时间段内请求次数太多。

这种设置有助于防止这些服务遭受恶意使用和过载。

仅限必要的HTTP请求类型,以满足功能需求

在我看来,将允许的HTTP方法限制为仅必要的或支持的方法是使得web服务器设置与应用程序(比如REST API)同步的一种干净方式。这不仅有助于防止API滥用或使用不必要的HTTP方法,还还能阻止像TRACE这样的潜在危险HTTP请求。此外,这样还能避免不必要的服务器负载,通过消除不支持或无关的HTTP请求。

    # HEAD 隐含
    limit_except GET {   
     拒绝所有;  
    }

另一个允许所有方法的示例,不过不包括 Trace 和 Patch 方法。


    如果 $request_method 相等于 ^(PATCH|TRACE)$ {  
     则返回 405;  
    }

简单的防机器人措施

如果发现机器人或者配置不当的扫描器——它们通常带有会话式的用户代理——我们就可以制造最大的混乱,通过返回Nginx的一个内部HTTP状态。要做到这一点,我们会在 /etc/nginx/snippets 目录下创建一个名叫 bot.protection.conf 的文件,并添加以下内容:

# 将一些已知的恶意爬虫工具的User-Agent添加到黑名单中
map $http_user_agent $blacklist_user_agents {  
   ~*wpscan            1;  
   ~*dirbuster         1;  
   ~*gobuster          1;  
}

当然可以根据需要随时添加条目。在 VHost 的配置中,可以按照如下方式加载文件:

# 不翻译代码段,保持原样

例如:

    include /etc/nginx/snippets/bot.protection.conf;  # 包含防爬虫保护配置文件

    if ($blacklist_user_agents) {  # 如果用户代理在黑名单中
     return 444;  # 返回444状态码,关闭连接
    }

HTTP 444 有时也被认为是“有趣的”,在猜测某些常见文件(例如 .env)时:

    # 类型为 <your-domain>/.bash_history 的请求可能返回 HTTP 444。
    location ~ /\. {  
     return 444  
    }

HTTP 444 究竟是什么意思?

HTTP 444 是一个非标准的状态码,指示 NGINX 服务器在不发送响应头的情况下关闭连接。它最常用于拒绝恶意或格式不正确的请求。使用此状态码的一个有趣副作用是,一些扫描程序无法正确处理此状态码,从而增加了额外的安全防护层。

启用TCP快速连接

TCP 快速连接是 Nginx 中的一项重要增强功能,提供了一种更高效的建立 TCP 连接的方法。此功能允许在初始握手阶段传输数据,显著加快了连接速度。它特别有助于减少延迟并优化性能,尤其是在高延迟的网络条件下。

你可以通过运行命令行来验证你的 Linux 内核是否支持这个 tcp_fastopen 选项。

    cat /proc/sys/net/ipv4/tcp_fastopen # 查看 tcp 快速打开设置

返回值为1表示已开启,否则直接运行:

echo 1 > /proc/sys/net/ipv4/tcp_fastopen

你现在可以按照以下方式使用这些设置:

通过以下方法:(via)

     listen [::]:443 ssl http2 fastopen=500;  
     监听 443 ssl http2 fastopen=500; 

或者更自然的表达可以是:

     监听 [::]:443 ssl http2 fastopen=500;  
     监听 443 ssl http2 fastopen=500; 
gZIP 压缩。

GZip是一种数据压缩方法,它通过减小文件大小来实现压缩。通过解压(或称为“解压缩”)压缩文件,可以完全恢复原始数据。

对于网页和网站应用来说,GZip 压缩很重要,因为 HTTP 支持在数据发送前进行压缩。

当 GZip 启用时,提供的文件大小会变小。这意味着带宽使用减少,从而使得网站托管和内容分发的成本降低。访客同样也会受益,因为他们下载的文件较小,页面加载速度会更快。

配置示例:

开启gzip;
设置gzip压缩类型 text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP