paint-brush
来自实践经验的 25 个 Nginx 提示和技巧经过@mykolaprokopenko
8,818 讀數
8,818 讀數

来自实践经验的 25 个 Nginx 提示和技巧

经过 Mykola Prokopenko11m2022/07/24
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

NGINX 建立在非阻塞、事件驱动的架构之上。它有一个主进程、几个worker_processes和两个缓存管理进程。 Nginx 允许您在不丢失连接、空闲资源或中断客户端服务的情况下更新服务器配置。在不重新启动服务的情况下应用设置是一个很好的做法,即这不会终止当前连接并消除加载服务时的等待时间。在应用之前检查书面配置的正确性。

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - 来自实践经验的 25 个 Nginx 提示和技巧
Mykola Prokopenko HackerNoon profile picture



这篇文章对新手很友好,因为数据是从简单到复杂的。在我作为 DevOps 工程师开始我的职业生涯时,我缺乏这样的材料。我将尝试从实践经验中谈谈 Nginx 的工作原理以及一些技巧和窍门。


NGINX 的工作原理

NGINX 建立在非阻塞、事件驱动的架构之上。它有一个主进程、几个worker_processes和两个缓存管理进程。要看到这一点,您只需要使用开关运行ps 命令


 ps -ef --forest | grep nginx


主进程以 root 身份运行并执行需要提升的操作,例如:

  • 读取配置;

  • 打开端口;

  • 创建新的流程。


工人完成所有工作:

  • 处理网络连接;
  • 读写数据到磁盘;
  • 与后端服务器通信。


通常,worker 的数量等于 CPU 内核的数量。这使您可以尽可能有效地使用系统资源。


Worker_processes 监听两种套接字:

  • 侦听器 - 用于新的客户端事件(连接请求);
  • 连接 - 用于需要处理的事件。


worker_processes 使用两种类型的 API 等待事件: epollkqueue 。当在侦听器套接字上接收到新的客户端事件时,worker_process 会创建一个新的套接字连接。


在连接套接字上收到事件后,worker_process 执行此请求。处理完事件后,它不会被阻塞,而是进入待机模式,从而最大限度地减少操作系统的上下文切换次数。


使用上述架构,更新 NGINX 配置就像向主进程发送 SIGHUP 信号一样简单。通过充分配置 NGINX,每个工作进程能够同时处理数十万个连接。


之后,worker_processes 将停止接受新的连接,并且处理完事件的当前连接将被关闭(无需等待保持活动状态)。一旦所有连接关闭,worker_process 就会结束。这使您可以在不丢失连接、空闲资源或中断客户端服务的情况下更新服务器配置。


技巧和窍门

1. 应用前检查所写配置的正确性

更改或创建配置后,需要检查语法和编写配置文件的正确性。 Nginx 允许您使用以下命令检查编写配置的正确性:


 nginx -t


2.重新加载Nginx而不重启服务

在不重新启动服务的情况下应用设置是一种很好的做法。这不会终止当前连接并消除加载服务时的等待时间,即没有停机时间:


 nginx -s reload


或者


/etc/init.d/nginx reload


或者


service nginx reload


3.禁用Nginx server_tokens

默认情况下,Nginx 中的 server_tokens 指令显示 Nginx 的版本号。它在所有自动生成的错误页面和服务器标头中的所有 HTTP 响应中都直接可见。


这可能导致信息泄露——未经授权的用户可以了解您的 Nginx 版本。如果您通过设置禁用 Nginx 配置文件中的server_tokens指令,将会有所帮助:


 server_tokens off;


4. 禁用旧版 SSL/TLS 协议

ssl_protocols TLSv1.2 TLSv1.3;


5. 禁用任何不需要的 HTTP 方法

禁用任何不会使用且不需要在 Web 服务器上实现的 HTTP 方法。


如果在 Nginx 虚拟主机配置文件的 location 块中添加以下条件,服务器将只允许GET, HEADPOST方法,并会过滤掉DELETETRACE等方法:


 location / { limit_except GET HEAD POST { deny all; } }


另一种方法是将以下条件添加到服务器部分(或服务器块)。它可以被认为更通用,但您必须小心位置上下文中的if 语句


 if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; }


6. 设置和配置 Nginx 访问和错误日志

Nginx 访问和错误日志默认启用,分别位于logs/error.loglogs/access.log,


如果要更改位置,可以使用 Nginx 配置文件中的 error_log 指令。您还可以使用此指令根据其严重性级别指定要记录的日志。


例如,严重严重性将导致 Nginx 记录严重问题以及严重级别高于严重级别的所有问题。要将严重级别设置为严重,请按如下方式设置 error_log 指令:


 error_log logs/error.log crit;


您可以在 Nginx 官方文档中找到 error_log 严重级别的完整列表。

您还可以更改 Nginx 配置文件中的 access_log 指令,以指定访问日志的非标准位置。


最后,您可以使用 log_format 指令自定义记录消息的格式,如 Nginx 文档中所述。


7. Nginx worker 连接

我们配置的一项关键设置是 Nginx 配置文件/etc/nginx/nginx.conf中的工作进程数和工作连接数。


我们将逐步将工作流和工作人员连接调整为更高或更低的值以应对 DDoS 攻击:


 events { worker_connections 20000; }


此设置允许每个工作进程处理多达 20,000 个连接。


8.请求速率限制

在防止 DDoS 攻击的许多有价值的策略中,最简单和最有效的策略之一是限制传入流量的速率。


例如,您可以将 NGINX 接受传入请求的速率指定为指定时间段内来自特定客户端 IP 地址的服务的平均速率。


我们在 Nginx 配置文件中设置 limit_req_zone 指令来限制请求的数量:


 limit_req_zone $binary_remote_addr zone=req_per_ip:1m rate=30r/m; server { location /login { limit_req zone=req_per_ip; } }


此示例创建一个名为 one 的存储区域,该区域最多可容纳 16,000 (1m) 个唯一 IP 地址,30r/m 意味着每分钟仅允许 30 个请求。


然后我们使用 limit_req 指令来限制到特定位置或文件的连接速度,在这种情况下,登录。


9.限制连接数

您可以限制可以从单个客户端 IP 地址打开的连接数,这里我们设置 limit_conn_zone 和limit_conn指令来限制每个 IP 地址的连接数:


 limit_conn_zone $binary_remote_addr zone=conn_per_ip:1m; server { location / { limit_conn conn_per_ip 10; } }


此示例创建一个名为conn_per_ip的存储区域来存储对指定密钥的请求,在本例中为客户端的 IP 地址 $binary_remote_addr。 limit_conn指令然后设置来自每个客户端 IP 地址的十个连接。


10. 超时选项

慢速连接可能表示尝试长时间保持连接打开。结果,服务器无法接受新连接:


 server { client_body_timeout 5s; client_header_timeout 5s; }


在此示例中, client_body_timeout指令指定 Nginx 在客户端主体条目之间等待多长时间, client_header_timeout指定 Nginx 在客户端标头条目之间等待多长时间。两者都设置为 5 秒。


11.限制请求的大小

同样,大缓冲区值或大 HTTP 请求大小使 DDoS 攻击更容易。因此,我们在 Nginx 配置文件中限制以下缓冲区值以缓解 DDoS 攻击:


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


在哪里,


client_body_buffer_size 1k —(默认 8k 或 16k)该指令指定客户端请求正文缓冲区的大小;


client_header_buffer_size 1k - 指令设置来自客户端的请求标头的标头缓冲区大小。 1Kb 的缓冲区大小足以满足绝大多数请求。


如果您有自定义标头或客户端发送的巨型 cookie(如 wap 客户端),请增加此值;


client_max_body_size 1k - 该指令设置客户端请求正文的最大允许大小,由请求标头中的 Content-Length 行指定。


如果大小大于指定的大小,则客户端会收到“请求实体太大”错误 (413)。使用 POST 方法上传文件时增加此值;


large_client_header_buffers 2 1k - 该指令分配缓冲区的最大数量和大小,用于从客户端请求中读取大型标头。


默认情况下,一个缓冲区的大小等于页面大小,具体取决于平台,它是 4K 或 8K。


如果连接在工作请求结束时进入保持活动状态,则释放这些缓冲区。


例如,2x1k 将接受 2 KB 数据 URI。它还将有助于对抗恶意机器人和 DoS 攻击。


12. IP 黑名单

如果您可以识别用于攻击的客户端 IP 地址,您可以使用拒绝指令将它们列入黑名单,以便 NGINX 和 NGINX Plus 不会接受它们的连接或请求:


 location / { deny 111.111.111.4; deny 111.111.111.0/24; }


在此示例中,第一个拒绝阻止特定 IP 地址,第二个拒绝阻止整个 IP 地址范围。


13. IP 白名单

如果只允许从一组或多组特定的客户端 IP 地址或范围访问您的网站或应用程序,则可以一起使用允许和拒绝指令以仅允许这些地址访问站点或应用程序:


 location / { allow 111.111.111.4; deny all; }


您可以限制仅访问特定本地网络上的地址。在这里,deny all 指令会阻止所有不在 allow 指令指定范围内的客户端 IP 地址。


14. 阻止对文件或位置的访问

您可以使用 Nginx 完全阻止对文件或位置的访问。例如,如果您注意到 register.php 文件是攻击的目标,您可以完全阻止对该文件的访问:


 location /register { deny all; return 444; }


这将丢弃所有尝试访问此文件的请求。代码 444 关闭连接而没有响应。


15.启用基于sysctl的保护

启用基于 sysctl 的保护。我们可以调整服务器上的内核和系统变量。编辑/etc/sysctl.conf文件并将这两行设置为 1,如下所示:


 net.ipv4.conf.all.rp_filter = 1 net.ipv4.tcp_syncookies = 1


第一个设置启用 IP 地址欺骗保护,第二个设置启用 TCP SYN cookie 保护。


16. Nginx 作为负载均衡器

当 Nginx 用作负载均衡器时,可以配置设置以限制每台服务器的连接数:


 upstream domain { server 111.111.111.4:80 max_conns=100; server 111.111.111.5:80 max_conns=100; queue 20 timeout=10s; }


在这里,max_conns 指令指定 Nginx 可以打开到服务器的连接数。当该组中的所有服务器都达到连接限制时,队列指令限制排队的请求数。


最后,超时指令指定请求可以在队列中保留多长时间。


17.拒绝某些用户代理

您可以轻松阻止用户代理,即可能滥用服务器的爬虫、机器人和垃圾邮件发送者:


 ## Block download agents ## if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; }


 ## Block some robots ## if ($http_user_agent ~* msnbot|scrapbot|PxBroker) { return 403; }


18. 阻止推荐垃圾邮件

推荐垃圾邮件是危险的。这可能会损害您通过博客(如果已发布)的 SEO 排名,因为推荐人字段链接到他们的垃圾邮件站点。使用这些行,您可以阻止对推荐垃圾邮件发送者的访问:


 if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ) { return 403; }


19. 停止图片盗链

图片热链接或 HTML 意味着有人将您的网站链接到您的一张图片,但将其显示在他们的网站上。


您最终将支付带宽费用并使内容看起来像网站的一部分。这通常在论坛和博客上完成。我强烈建议您在服务器的同一级别阻止和停止图像盗链:


 location /images/ { valid_referers none blocked www.domain.com domain.com; if ($invalid_referer) { return 403; } }


20.在防火墙级别限制每个IP地址的连接数

Web 服务器必须监控连接并限制每秒的连接数。这服务于 101。 pf 和 iptables 都可以在访问您的 Nginx 服务器之前阻止最终用户。

Linux Iptables:每秒限制 Nginx 连接。

在以下示例中,如果 IP 在 60 秒内对端口 80 进行超过 15 次连接尝试,传入连接将被丢弃:


 /sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set && \ /sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 15 -j DROP && \ service iptables save


21.在某些浏览器中禁用内容类型嗅探

如果响应指定了不正确的内容类型,则浏览器可能会以意想不到的方式处理响应。


如果内容类型被确定为可呈现的基于文本的格式,则浏览器通常会尝试将响应解释为该格式,而不管响应的实际内容如何。


此外,由于特定浏览器的怪癖,某些其他指定的内容类型有时可能会被解释为 HTML。这可能会导致其他“安全”内容,例如将图像呈现为 HTML,从而在某些条件下启用跨站点脚本攻击。将以下内容添加到您的配置中:


add_header X-Content-Type-Options nosniff;


22.启用跨站点脚本(XSS)过滤器

将以下行添加到您的配置文件中,以在您的 Nginx Web 服务器上启用 X-XSS-Protection 标头。完成后,保存更改并重新加载 Nginx:


add_header X-XSS-Protection "1; mode=block";


23. 配置 HTTP/2 支持

HTTP/2 是 HTTP 1.x 网络协议的继承者。 HTTP/2 被广泛用于减少延迟、最小化协议开销、添加对请求优先级的支持以及加速 Web 应用程序加载。


因此,及时了解性能优化技术和策略至关重要。 HTTP/2 的主要重点是减少网页的整体加载时间,从而优化性能。


它还关注网络和服务器资源的使用,以及增强的安全性,因为在使用 HTTP/2 时 SSL/TLS 加密是强制性的。


作为先决条件,请确保构建时 Nginx 版本为 1.9.5 或更高版本,否则您必须手动添加它,并且服务器必须启用 SSL/TLS。您的 HTTPS 服务器块现在应该如下所示:


 server { listen 443 ssl http2; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; }


24.添加内容安全策略(CSP)

CSP 是额外的安全层,有助于检测和缓解某些类型的攻击,包括跨站点脚本 (XSS) 和数据注入攻击。这些攻击用于数据盗窃、网站损坏和恶意软件分发:


 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;


25.监控Nginx

必须不断监控服务器的状态。您可以通过定期向其发送请求来查看服务器返回的内容,例如通过第三方付费服务。或者你可以微调一切,有很多方法可以做到这一点——更多关于它的信息在Nginx 博客中。


而是结论

必须灵活并为每种情况分别开发配置。