百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

如何让Nginx更安全?_nginx怎么保证高可用

nanshan 2025-02-17 13:19 13 浏览 0 评论

网络安全的重要性不言而喻。


那么小伙伴们有没有在日常使用 Nginx 的时候,特意去关注下它的安全配置呢?


今天松哥和小伙伴们讨论一下如何安全的使用 Nginx,给大伙几个建议。

一 使用最新版

建议使用最新版的 Nginx,对于已经部署的 Nginx,要及时更新到最新版本,以确保所有已知的安全漏洞都已修补。


Nginx 下载地址:
https://nginx.org/en/download.html

二 限制连接数量

Nginx 可以通过 limit_conn_zone 和 limit_conn 两个组件来对客户端访问目录和文件的访问频率和次数进行限制,两个模块都能够对客户端访问进行限制,具体如何使用要结合公司业务环境进行配置。


举个简单的例子:


http {
  limit_conn_zone $binary_remote_addr zone=ops:10m;

  # ...

  server {
    listen       80;
    server_name  www.javaboy.org;
    location / {
      limit_conn ops 1;  #这将指定一个地址只能同时存在一个连接。“one” 与上面的对应,也可以自定义命名
      limit_rate 300k;
  }

}


这里涉及到三个配置项:


  • limit_zone: 是针对每个 IP 定义一个存储 session 状态的容器,这个示例中定义了一个 10m 的容器,假设每个 session 的大小是 32bytes,那么可以处理 327680 个 session。
  • limit_conn ops 1:限制每个 IP 只能发起一个并发连接。
  • limit_rate 300k: 对每个连接限速 300k. 注意,这里是对连接限速,而不是对 IP 限速。如果一个 IP 允许两个并发连接,那么这个 IP 就是限速 limit_rate × 2。

三 限制请求频率

Nginx 可以通过限制请求频率来防止服务器过载,最常见的场景就是登录请求,可以通过限制请求频率防止账号暴力破解。


Nginx 官方版本限制 IP 的连接和并发分别有两个模块:


  • limit_req_zone:用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "leaky bucket"。
  • limit_req_conn 用来限制同一时间连接数,即并发限制。


举个栗子


http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;

    server {
        listen 80;

        location / {
            limit_req zone=mylimit burst=5 nodelay;;
            proxy_pass http://javaboy.org;
        }
    }
}


limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;


  • 第一个参数:$binary_remote_addr 表示通过 remote_addr 这个标识来做限制,“binary_” 的目的是缩写内存占用量,是限制同一客户端 ip 地址。
  • 第二个参数:zone=mylimit:10m 表示生成一个大小为 10M,名字为 mylimit 的内存区域,用来存储访问的频次信息。
  • 第三个参数:rate=1r/s 表示允许相同标识的客户端的访问频次,这里限制的是每秒 1 次,还可以有比如 30r/m 的。


limit_req zone=mylimit burst=5 nodelay;


  • 第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面 limit_req_zone 里的 name 对应。
  • 第二个参数:burst=5,重点说明一下这个配置,burst 爆发的意思,这个配置的意思是设置一个大小为 5 的缓冲区,当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
  • 第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回 503,如果没有设置,则所有请求会等待排队。

四 防止目录遍历

在 Nginx 配置中设置 autoindex off 来防止目录遍历攻击。


这个一般是如果你要做文件服务器,根据自己的实际需求,有需要的话这个功能可以打开,否则将之关闭即可。


location / {
    autoindex off;
}

五 隐藏 Nginx 版本号

攻击者如果能够确定服务器使用的 Nginx 版本,可能会利用这个信息来寻找和利用已知的漏洞进行攻击。因此,隐藏版本信息可以提高服务器的安全性,使攻击者难以通过版本信息推断出服务器可能存在的安全漏洞。


要隐藏 Nginx 版本号,有三个办法,一般来说我们使用第一种方式就可以了。

修改配置文件

在 Nginx 的配置文件中,在 http 块中添加以下配置:


server_tokens off;


这样设置后,Nginx 将不会在错误页面上显示版本号。


配置完成之后,保存配置文件并重新加载 Nginx 以应用更改:


nginx -t   # 测试配置文件是否正确
nginx -s reload   # 重新加载Nginx配置


这种方法可以隐藏错误页面上的版本信息,但可能无法完全隐藏所有响应头中的版本信息 。

修改 Nginx 源码

如果想要从根源上修改 Nginx 版本信息,需要重新编译 Nginx,步骤如下:


  • 修改 src/core/nginx.h 文件中的版本定义。
  • 修改 src/http/ngx_http_header_filter_module.c 文件中的服务器字符串。
  • 修改 src/http/ngx_http_special_response.c 文件中的错误页面底部信息。


修改完这些文件后,需要重新编译 Nginx。这样编译安装后,Nginx 的版本信息将被彻底修改 。

使用第三方模块

如果需要动态修改响应头中的版本信息,可以使用如 headers-more-nginx-module 模块。这个模块允许你动态地添加、修改或删除 Nginx 的响应头。通过这个模块,可以完全控制 Server 响应头的内容 。


选择哪种方法取决于你的具体需求和环境。


如果你只是想简单地隐藏版本信息,修改配置文件可能是最简单的方法。如果你需要更彻底地控制版本信息,可能需要考虑修改源码并重新编译 Nginx。

六 设置超时时间

设置 Nginx 的超时配置是非常重要的,因为它可以影响服务器的性能和资源的有效利用。


比较常见的超时配置有四个:


  1. keepalive_timeout:这个指令设置了与客户端的 keep-alive 连接超时时间。如果连接在指定时间内没有数据传输,Nginx 将关闭该连接。默认值通常是 75 秒。这个设置对于频繁访问的站点尤其重要,因为它减少了连接建立和断开的开销。
  2. client_body_timeout:这个指令指定了客户端与服务端建立连接后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx 返回 HTTP 408(Request Timed Out)。默认值通常是 60 秒。
  3. client_header_timeout:这个指令指定了客户端向服务端发送一个完整的 request header 的超时时间。如果在指定时间内没有发送一个完整的 request header,Nginx 返回 HTTP 408(Request Timed Out)。默认值通常是 60 秒。
  4. send_timeout:这个指令设置了服务端向客户端传输数据的超时时间。如果在指定时间内客户端没有接收到任何数据,连接将被关闭。默认值通常是 60 秒。


针对这四个比较常见的超时配置,松哥这里也给大家一个配置案例。

keepalive_timeout

这个指令控制了客户端与服务器之间的连接保持活动状态的时间。这对于减少 TCP 连接的开销非常有用,特别是在高流量的网站上。


http {
    keepalive_timeout 60s;

    server {
        listen 80;
        server_name javaboy.org;

        location / {
            proxy_pass http://javaboy.org;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
        }
    }
}


在这个配置中,keepalive_timeout 被设置为 60 秒,意味着如果 60 秒内没有数据传输,连接将被关闭。

client_body_timeout

这个指令设置了客户端发送请求体到服务器的超时时间。


http {
    client_body_timeout 10s;

    server {
        listen 80;
        server_name javaboy.org;

        location /upload {
            client_max_body_size 100M;
            client_body_timeout 30s;
        }
    }
}


在这个配置中,client_body_timeout 被设置为 10 秒,适用于上传大文件的场景,确保如果客户端在 30 秒内没有完成文件上传,请求将被终止。

client_header_timeout

这个指令控制了客户端发送完整的 HTTP 请求头到服务器的超时时间。


http {
    client_header_timeout 5s;

    server {
        listen 80;
        server_name javaboy.org;

        location / {
            proxy_pass http://javaboy.org;
        }
    }
}


在这个配置中,client_header_timeout 被设置为 5 秒,意味着如果客户端在 5 秒内没有发送完整的 HTTP 请求头,服务器将终止连接。

send_timeout

这个指令设置了服务器发送响应到客户端的超时时间。


http {
    send_timeout 10s;

    server {
        listen 80;
        server_name javaboy.org;

        location / {
            proxy_pass http://javaboy.org;
            proxy_read_timeout 10s;
        }
    }
}


在这个配置中,send_timeout 被设置为 10 秒,适用于后端服务响应慢的场景,确保如果后端服务在 10 秒内没有发送数据,客户端将收到超时响应。

七 仅允许域名访问

限制仅允许域名访问可以防止未授权的 IP 直接访问服务器,减少未备案域名解析到服务器 IP 导致的安全风险。


这个也有三种不同的配置方式,我们逐一来看。

使用两个 server 块

在 Nginx 配置文件中,你可以设置一个默认的 server 块,它将捕获所有不明确的域名请求,并返回 403 错误。然后,为特定的域名设置 server 块。


server {
    listen 80 default_server;
    server_name _;
    return 403;
}

server {
    listen 80;
    server_name www.javaboy.org;
    location / {
        # 你的配置
    }
}


在这个配置中,第一个 server 块会拦截所有不明确域名的请求,并返回 403 错误。第二个 server 块则是为特定域名 www.javaboy.org 提供服务的配置。


这个配置有两点需要注意:


  1. 如果没有显式声明 default server 则第一个 server 会被隐式的设为 default server。
  2. server_name 中的 _;,并不是重点 __ 也可以, ___ 也可以。

使用 if 语句

还可以在特定的 server 块中使用 if 语句来检查 $host 变量,如果它不匹配你的域名,则返回 403 错误。


server {
    listen 80;
    server_name javaboy.org;
    location / {
        if ($host != 'www.javaboy.org') {
            return 403;
        }
        # 你的配置
    }
}


这种方法允许你在特定域名的 server 块中直接控制访问权限,只有当 $host 变量与你的域名匹配时,才会允许访问。

直接禁止 IP

http {
    server {
        listen 80;
        server_name www.javaboy.org;
        ...
    }
    
    server {
        listen 80;
        server_name www.itboyhub.com;
        ...
    }
    
    # 直接指定 ip server_name
    server {
        listen 80;
        server_name 11.11.11.11;
        return 403; # 403 forbidden
    }
    
}


这样配置后,只有通过指定的域名才能访问网站,直接通过 IP 地址访问将会受到限制。

八 限制 Nginx 请求方法

通过限制特定的 HTTP 请求方法,可以减少服务器受到自动化攻击的风险,并且可以防止某些类型的 Web 漏洞,如 SQL 注入或跨站脚本(XSS)攻击。


有两种配置方式,松哥来和大家逐一说明。

只允许 GET 和 POST

在 server 或 location 块中,使用 if 语句来检查请求方法,并返回 403 错误码以拒绝其他方法。


server {
    listen 80;
    server_name javaboy.org;

    location / {
        if ($request_method !~* (GET|POST)) {
            return 403;
        }
        # 其他配置...
    }
}


这种方法会拒绝所有非 GET 和 POST 的请求方法。

使用 map 模块

对于更复杂的限制逻辑,可以使用 Nginx 的 map 模块来动态设置请求方法的限制。


http {
    map $request_method $block_request {
        default 0;
        POST 1;
        PUT 1;
    }

    server {
        listen 80;
        server_name javaboy.org;

        location / {
            if ($block_request) {
                return 403;
            }
            # 其他配置...
        }
    }
}


在这个例子中,所有 POST 和 PUT 请求都会被拒绝。

九 错误页面重定向

在 Nginx 中配置错误页面重定向,除了安全因素之外,还有很多好处,比如:


  1. 提升用户体验:通过提供更友好的错误页面,可以减少用户在遇到错误时的困惑和挫败感。
  2. 增强 SEO 效果:自定义错误页面可以帮助搜索引擎更好地理解网站结构,避免因错误页面导致的 SEO 问题。
  3. 维护品牌形象:错误页面是网站的一部分,通过自定义错误页面,可以保持品牌一致性,提升专业形象。
  4. 提供错误信息:自定义错误页面可以提供有用的错误信息或解决方案,帮助用户理解问题所在。


在 Nginx 配置文件中,可以使用 error_page 指令来定义特定错误代码的重定向页面。例如,将 404 错误重定向到自定义的 404 页面:


server {
    listen 80;
    server_name javaboy.org;

    error_page 404 /404.html;
    location = /404.html {
        root /path/to/error/pages;
        internal;
    }
}


在这个配置中,当 Nginx 返回 404 错误时,它会显示位于
/path/to/error/pages/404.html 的自定义错误页面,而不是默认的错误页面。internal 指令确保这个页面只对 Nginx 内部请求可见,不会被外部直接访问 。


当然,上面这个配置也可以同时枚举多个错误状态码:


error_page 500 502 503 504 /50x.html;
location = /50x.html {
    root /usr/share/nginx/html;
}


这个配置会将所有 500 系列错误重定向到 /50x.html,并显示位于
/usr/share/nginx/html/50x.html 的自定义错误页面 。

十 日志保留半年

保留 Nginx 日志半年的原因有很多,比如:


  1. 安全审计:日志文件可以用于安全审计,帮助分析和追踪潜在的攻击或异常行为。
  2. 故障排查:在系统出现故障时,日志文件是诊断问题的重要工具,可以帮助快速定位问题原因。
  3. 性能监控:通过分析日志,可以了解网站的访问情况和性能瓶颈,从而进行相应的优化。
  4. 合规性要求:某些行业法规可能要求保留一定期限的日志记录,以满足合规性检查。


要配置 Nginx 日志保留半年,通常需要使用 logrotate 工具来实现日志文件的定期轮换和压缩。


这个工具配置并不难,松哥给大家举个栗子。


在 /etc/logrotate.d/ 目录下创建一个名为 nginx 的配置文件,内容如下:


/var/log/nginx/*.log {
    daily
    rotate 180
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}


这个配置会每天检查 Nginx 日志文件,并将它们保留 180 天(约 6 个月),然后自动压缩旧的日志文件。postrotate 部分的命令会在日志轮换后重新打开 Nginx 日志文件,以便继续记录新的日志信息。


通过这些配置,我们可以确保 Nginx 的日志文件被保留半年,同时旧的日志文件会被压缩以节省磁盘空间。

十一 设置缓冲区

Nginx 的缓冲区溢出攻击是一种常见的安全漏洞,它发生在程序试图向一个缓冲区写入超出其预分配大小的数据时。


这种攻击可能导致数据覆盖了相邻的内存区域,可能破坏程序的执行流程,甚至可以被恶意攻击者利用来执行恶意代码。


为了防止缓冲区溢出类攻击事件,可以设置客户端请求体、请求头和客户端最大请求体的缓冲区大小。


配置方式如下:


client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;


这四行配置含义如下:


  • client_body_buffer_size 1K;:这条指令设置了 Nginx 用来读取客户端请求体(比如 POST 请求中的数据)的缓冲区大小。在这个例子中,缓冲区大小被设置为 1KB。如果请求体的大小超过了这个缓冲区的大小,Nginx 会使用磁盘来暂存超出部分的数据。
  • client_header_buffer_size 1k;:这条指令定义了 Nginx 用来读取客户端 HTTP 请求头部的缓冲区大小。这里设置的大小是 1KB。如果请求头部的大小超过了这个缓冲区的大小,Nginx 会使用 large_client_header_buffers 定义的缓冲区。
  • client_max_body_size 1k;:这条指令限制了 Nginx 服务器愿意接收的最大请求体大小。如果客户端发送的请求体超过了这个大小(在这个例子中是 1KB),Nginx 将返回一个 413(Request Entity Too Large)错误。
  • large_client_header_buffers 2 1k;:这条指令定义了 Nginx 用于处理大于 client_header_buffer_size 指定大小的请求头的缓冲区数量和大小。这里配置了 2 个大小为 1KB 的缓冲区。当请求头的大小超过了 client_header_buffer_size 定义的缓冲区大小时,Nginx 会使用这两个额外的缓冲区来处理请求头。


这些配置对于防止缓冲区溢出攻击和处理大请求都是非常重要的。

十二 使用普通用户启动

在 Linux 系统中,只有 root 用户或者具有特定权限的用户才能绑定 1024 以下的端口,如 80 端口(HTTP)和 443 端口(HTTPS)。


如果 Nginx 以 root 用户运行,它将拥有过高的权限,这可能会带来安全风险。因此,为了最小化权限,通常会创建一个普通用户来运行 Nginx,以减少潜在的安全漏洞。


配置方式如下:


  1. 创建用户


首先,你需要创建一个普通用户和用户组,例如 nginx。


groupadd nginx
useradd -g nginx -d /usr/local/nginx nginx


这里创建了一个名为 nginx 的用户和组,并设置了用户的家目录。


  1. 授权访问


确保新用户有权访问 Nginx 的配置文件、日志文件和服务器文件。


chown -R nginx:nginx /usr/local/nginx/


这条命令将 Nginx 目录及其所有子目录和文件的所有权更改为新创建的 nginx 用户和组。


  1. 配置Nginx


编辑 Nginx 配置文件(通常位于 /etc/nginx/nginx.conf),设置 user 指令以指定 Nginx 工作进程的用户。


user nginx;


这行配置指定 Nginx 应该以 nginx 用户的身份运行。


  1. 设置权限


如果需要,可以使用 setcap 命令赋予 Nginx 监听 1024 以下端口的能力,而不需要以 root 用户运行。


setcap cap_net_bind_service=+ep /usr/local/nginx/sbin/nginx


这个命令允许 Nginx 以普通用户身份绑定到 80 和 443 端口。


  1. 启动Nginx


使用普通用户启动 Nginx。


su - nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf


这里首先切换到 nginx 用户,然后启动 Nginx 服务。


  1. 验证


检查 Nginx 是否以普通用户启动。


ps -ef | grep nginx


这条命令将显示 Nginx 的进程信息,你可以验证它是否以 nginx 用户运行。


好啦,小伙伴们还有哪些 Nginx 安全配置建议?欢迎留言讨论。

相关推荐

0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)

文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...

ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes

为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...

生产环境starrocks 3.1存算一体集群部署

集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...

在CentOS上添加swap虚拟内存并设置优先级

现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...

国产深度(deepin)操作系统优化指南

1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...

postgresql-15.4 多节点主从(读写分离)

1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...

Docker 容器 Java 服务内存与 GC 优化实施方案

一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...

虚拟内存设置、解决linux内存不够问题

虚拟内存设置(解决linux内存不够情况)背景介绍  Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...

Elasticsearch性能调优(5):服务器配置选择

在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...

Es如何落地

一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...

针对Linux内存管理知识学习总结

现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...

MySQL进阶之性能优化

概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...

Linux Cgroups(Control Groups)原理

LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...

linux 常用性能优化参数及理解

1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...

如何在 Linux 中使用 Sysctl 命令?

sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...

取消回复欢迎 发表评论: