配置Nginx以提升性能和安全性
在本教程中,我们将看看如何为生产环境配置Nginx Web服务器。
生产环境中的Web服务器与测试环境中的Web服务器在性能、安全性等方面有所不同。
默认情况下,一旦成功安装了Nginx Web服务器,就会始终有一个可用的配置设置。然而,默认配置对于生产环境来说并不够好。因此,我们将着重介绍如何配置Nginx在高负载和正常流量激增时提供更好的性能,以及如何保护它不被有意滥用的用户。
如果您尚未在计算机上安装Nginx,您可以查看如何进行安装 here. 它会向您展示如何在Unix平台上安装Nginx。选择通过源代码安装Nginx,因为预编译的Nginx没有一些在本教程中使用的模块。
要求
您需要在计算机上安装以下软件,并确保在像Ubuntu这样的任何基于Debian的平台上运行本教程。
- Ubuntu或其他基于Debian的平台
- wget
- Vim(文本编辑器)
此外,您需要以root用户身份通过sudo
命令来运行或执行本教程中的一些命令。
理解Nginx配置结构
在本节中,我们将了解以下内容:
- Nginx的结构
- 诸如事件、HTTP和邮件等的部分
- Nginx的有效语法
在本节结束时,您将了解Nginx配置的结构,各个部分的目的或作用,以及如何在各个部分中定义有效的指令。
完整的Nginx配置文件具有逻辑结构,由指令组成,这些指令分组到多个部分中,例如event section
,http section
,mail section
等。
主配置文件位于/etc/nginx/nginx.conf
,而其他配置文件位于/etc/nginx
。
主上下文
此部分或上下文包含特定部分之外的指令,如mail section
。
任何其他指令,如user nginx;
,worker_processes 1;
,error_log /var/log/nginx/error.log warn;
和pid /var/run/nginx.pid
都可以放在主节或上下文中。
但是,其中一些指令,如worker_processes
,也可以存在于event section
中。
部分
Nginx中的部分定义了Nginx模块的配置。
例如,http section
定义了ngx_http_core module
的配置,event section
定义了ngx_event_module
的配置,而mail section定义了ngx_mail_module
的配置。
您可以查看here以获取Nginx中的完整部分列表。
指令
Nginx中的指令由变量名和若干参数组成,如下所示:
worker_processes
是一个变量名,而auto
是一个参数。
worker_processes auto;
指令以分号结尾,如上所示。
最后,Nginx配置文件必须遵循特定的规则。以下是Nginx配置的有效语法:
- 有效的指令以变量名开头,接着是一个或多个参数
- 所有有效的指令以分号
;
结尾 - 使用花括号
{}
定义段落 - 一个段落可以嵌套在另一个段落中
- 任何段落外的配置都属于Nginx的全局配置
- 以井号
#
开头的行是注释
优化Nginx性能
在本节中,我们将配置Nginx以在高流量和流量峰值时表现更好。
我们将看看如何配置:
- Workers
- 磁盘I/O活动
- 网络活动
- 缓冲区
- 压缩
- 缓存
- 超时
在已激活的虚拟环境中,键入以下命令切换到Nginx目录并列出其内容。
cd nginx && ls
搜索文件夹conf
。在这个文件夹中是nginx.conf
文件。
我们将使用这个文件来配置Nginx
现在执行以下命令导航到conf
文件夹并使用vim editor
打开文件nginx.conf
cd conf
sudo vim nginx.conf
下面是默认情况下nginx.conf
文件的屏幕截图。
Workers
为了使Nginx表现更好,我们需要在事件部分配置workers
。配置Nginx workers使您能够有效地处理来自客户端的连接。
假设您尚未关闭vim编辑器,请按下键盘上的i按钮编辑nginx.conf
文件。
复制并粘贴以下内容到events section
中,如下所示:
events {
worker_processes auto;
worker_connections 1024;
worker_rlimit_nofile 20960;
multi_accept on;
mutex_accept on;
mutex_accept_delay 500ms;
use epoll;
epoll_events 512;
}
worker_processes
:此指令控制Nginx中的worker数量。此指令的值设置为auto
,允许Nginx确定可用的核心数、磁盘、服务器负载和网络子系统的数量。但是,您可以通过在终端上执行lscpu
命令来查看核心数。
worker_connections
:此指令设置工作进程可以打开的同时连接数的值。默认值为512
,但我们将其设置为1,024
,以允许一个工作进程从客户端接受更多的同时连接。
worker_rlimit_nofile:
此指令与worker_connections
有关。为了处理大量同时连接,我们将其设置为一个大值。
multi_accept:
此指令允许工作进程一次接受多个连接。在此上下文中,队列指的是等待处理的数据对象的序列。
mutex_accept:
默认情况下,此指令关闭。但是因为我们已经在Nginx中配置了多个worker,所以我们需要将其设置为上面的代码中的打开状态,以允许工作进程逐个接受新连接。
mutex_accept_delay:
此指令确定工作进程在接受新连接之前应等待多长时间。一旦启用了accept_mutex
,互斥锁将在指定的accept_mutex_delay
时间段内分配给工作进程。时间段结束后,下一个工作进程准备好接受新连接。
用途:
该指令指定处理来自客户端的连接的方法。在本教程中,我们决定将值设置为epoll
,因为我们使用的是Ubuntu
平台。对于Linux平台来说,epoll
方法是最有效的处理方法。
epoll_events:
该指令的值指定了Nginx将传输给内核的事件数量。
磁盘I/O
在本节中,我们将配置Nginx中的异步I/O活动,以使其能够执行有效的数据传输并提高缓存效果。
磁盘I/O简单地指的是硬盘和RAM之间的写入和读取操作。我们将使用内核中的sendfile()
函数来发送小文件。
您可以在这个区域中使用http部分
,location部分
和server部分
的指令。
location部分
,server部分
可以嵌套或放置在http部分
中,以使配置更具可读性。
将以下代码复制并粘贴到嵌套在HTTP部分内的location部分中。
location /pdf/ {
sendfile on;
aio on;
}
location /audio/ {
directio 4m
directio_alignment 512
}
sendfile:
将该指令的值设置为on
以利用操作系统资源。sendfile在操作系统内核空间内的文件描述符之间传输数据,而不将其发送到应用程序缓冲区。此指令将用于提供小文件。
directio:
通过允许直接将读取和写入发送到应用程序,该指令提高了缓存效果。directio
是每个现代操作系统的文件系统功能。此指令将用于提供像视频这样的较大文件。
aio:
将该指令设置为on
以启用写入和读取操作的多线程。多线程是一种执行模型,允许多个线程在彼此独立执行的同时共享其主进程资源。
directio_alignment:
该指令为数据传输分配了一个块大小值。它与directio
指令相关。
网络层
在本节中,我们将使用tcp_nodelay
和tcp_nopush
等指令来防止小数据包在等待约200毫秒后才一起发送。
通常情况下,当数据包以“片段”方式传输时,它们往往会占满高负载网络。因此,John Nagle构建了一个buffering algorithm来解决这个问题。 Nagle缓冲算法的目的是防止小数据包占满高负载网络。
将以下代码复制并粘贴到HTTP部分中。
http {
tcp_nopush on;
tcp_nodelay on;
}
tcp_nodelay:
默认情况下,该指令被禁用,以允许小数据包在一段时间内等待后再发送。要让所有数据一次性发送,可以启用此指令。
tcp_nopush:
因为我们已经启用了tcp_nodelay
指令,所以小数据包会立即发送。然而,如果您仍然想使用John Nagle的缓冲算法,我们也可以启用tcp_nopush
以将数据包合并并一次性发送。
缓冲区
让我们来看看如何在Nginx中配置请求缓冲区以有效处理请求。缓冲区是一个临时存储,数据在其中暂时保存并进行处理。
您可以将以下代码复制到server部分中。
server {
client_body_buffer_size 8k;
client_max_body_size 2m;
client_body_in_single_buffer on;
client_body_temp_pathtemp_files 1 2;
client_header_buffer_size 1m;
large_client_header_buffers 4 8k;
}
了解这些缓冲区行的作用非常重要。
client_body_buffer_size:
此指令设置请求体的缓冲区大小。如果您计划在64位系统上运行 Web 服务器,需要将该值设置为16k。如果您想在32位系统上运行 Web 服务器,请将该值设置为8k。
client_max_body_size:
如果您打算处理大型文件上传,则需要将此指令设置为至少2m
或更大。默认情况下,它设置为1m
。
client_body_in_file_only:
如果您使用井号符号#
禁用了指令client_body_buffer_size
,并且设置了此指令client_body_in_file_only
,那么Nginx将把请求缓冲区保存到临时文件中。这在生产环境中不推荐使用。
client_body_in_single_buffer:
有时并不是所有的请求体都存储在一个缓冲区中。其余部分将保存或写入临时文件。然而,如果您打算将完整的请求缓冲区保存或存储在一个缓冲区中,您需要启用此指令。
client_header_buffer_size:
您可以使用此指令为请求头设置或分配缓冲区。您可以将此值设置为1m
。
large_client_header_buffers:
此指令用于设置读取大型请求头的最大数量和大小。您可以将最大数量和缓冲区大小精确设置为4
和8k
。
压缩
压缩在网络传输的数据量是确保您的 Web 服务器性能更佳的另一种方式。在本节中,我们将使用gzip
、gzip_comp_level
和gzip_min_length
等指令来压缩数据。
将以下代码粘贴到http部分
中,如下所示:
http {
gzip on;
gzip_comp_level 2;
gzip_min_length 1000;
gzip_types text/xml text/css;
gzip_http_version 1.1;
gzip_vary on;
gzip_disable "MSIE [4-6] .";
}
gzip:
如果要启用压缩,请将此指令的值设置为on
。默认情况下,它被禁用。
gzip_comp_level:
您可以使用此指令设置压缩级别。为了不浪费 CPU 资源,您不需要将压缩级别设置得太高。在1
和9
之间,您可以将压缩级别设置为2
或3
。
gzip_min_length:
通过content-length response header field
设置压缩的最小响应长度。您可以将其设置为大于20个字节。
gzip_types:
此指令允许您选择要压缩的响应类型。默认情况下,始终压缩响应类型为text/html
。您可以像上面的代码中所示添加其他响应类型,例如text/css
。
gzip_http_version:
此指令允许您选择请求的最低 HTTP 版本以获取压缩响应。您可以使用默认值1.1
。
gzip_vary:
当启用gzip
指令时,此指令会向响应中添加Vary:Accept Encoding
标头字段。
gzip_disabled:
某些浏览器,如Internet Explorer 6
,不支持gzip 压缩
。此指令使用User-Agent
请求头字段来禁用某些浏览器的压缩。
缓存
通过使用缓存功能,减少加载相同数据的次数。Nginx通过open_file_cache
指令提供了缓存静态内容元数据的功能。
您可以将此指令放置在server
、location
和http
节中。
http {
open_file_cache max=1,000 inactive=30s;
open_file_cache_valid 30s;
open_file_cache_min_uses 4;
open_file_cache_errors on;
}
open_file_cache:
默认情况下,此指令是禁用的。如果要在Nginx中实现缓存,则启用该指令。该指令存储用户常常请求的文件和目录的元数据。
open_file_cache_valid:
此指令包含在open_file_cache
指令中的备份信息。您可以使用该指令设置一个有效期(以秒为单位),在该有效期之后,与文件和目录相关的信息将被重新验证。
open_file_cache_min_uses:
通常根据open_file_cache_min_uses
来清除open_file_cache
指令中的信息,该指令设置一个最小访问次数,以确定哪些文件和目录是活跃访问的。
open_file_cache_errors:
您可以使用此指令允许Nginx缓存错误,例如“权限被拒绝”或“无法访问此文件”等。因此,每当用户访问一个没有权限访问的资源时,Nginx都会显示相同的错误报告“权限被拒绝”。
超时时间
使用keepalive_timeout
和keepalive_requests
等指令配置超时时间,以防止长时间等待的连接浪费资源。
在HTTP节中,复制并粘贴以下代码:
http {
keepalive_timeout 30s;
keepalive_requests 30;
send_timeout 30s;
}
keepalive_timeout
:保持连接活动约30秒。默认值为75秒。
keepalive_requests
:配置在特定时间段内保持活动的请求数。您可以将请求数设置为20或30。
keepalive_disable
:如果要禁用特定浏览器组的保持活动连接,请使用此指令。
send_timeout
:为向客户端传输数据设置超时时间。
Nginx的安全配置
以下内容仅关注如何安全地配置Nginx,而不是关注Web应用程序。因此,我们不会讨论诸如SQL注入等基于Web的攻击。
在本节中,我们将讨论以下配置内容:
- 限制对文件和目录的访问
- 配置日志以监视恶意活动
- 防止DDoS攻击
- 禁止目录列表
限制对文件和目录的访问
让我们看看如何通过以下方法限制对敏感文件和目录的访问。
使用HTTP身份验证
我们可以通过提示用户或管理员进行身份验证来限制对敏感文件或不适合公开查看的区域的访问。如果您尚未安装密码文件创建工具,请运行以下命令安装它。
apt-get install -y apache-utils
接下来,使用以下命令使用htpasswd
工具创建密码文件和用户。 htpasswd
工具由apache2-utils
实用程序提供。
sudo htpasswd -c /etc/apache2/ .htpasswd mike
您可以通过以下命令确认是否成功创建:
cat etc/apache2/ .htpasswd
在位置部分内,您可以粘贴以下代码以使用auth_basic
指令提示用户进行身份验证。
location /admin {
basic_auth "管理员区域";
auth_basic_user_file /etc/apache2/ .htpasswd;
}
通过使用Allow指令
除了basic_auth
指令外,我们还可以使用allow
指令来限制访问。
在位置部分内,您可以使用以下代码允许指定的IP地址访问敏感区域。
location /admin {
allow 192.168.34.12;
allow 192.168.12.34;
}
配置日志以监控恶意活动
在本部分中,我们将配置error
和access
日志以专门监控有效和无效的请求。您可以检查这些日志以了解在特定时间登录的人员,或者哪个用户访问了特定文件等。
error_log:
允许您设置日志记录到特定文件,例如syslog
或stderr
。您还可以指定要记录的错误消息级别。
access_log:
允许将用户请求写入文件access.log
在HTTP部分内,您可以使用以下内容。
http {
access_log logs/access.log combined;
error_log logs/warn.log warn;
}
防止DDOS攻击
您可以通过以下方法保护Nginx免受DDOS攻击:
限制用户请求
您可以使用limit_req_zone
和limit_req
指令限制用户在一定时间内发送请求的速率。
将以下代码添加到嵌套在服务器部分中的location
部分中。
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;
server {
location /admin.html {
limit_req zone=one;
}
}
限制连接数
您可以使用limit_conn
和limit_conn_zone
指令限制对特定位置或区域的连接。例如,下面的代码在特定时间段内接收来自客户端的15个连接。
以下代码将位于location
部分中。
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
location /products/ {
limit_conn addr 10;
}
}
终止慢速连接
您可以使用超时指令,例如client_body_timeout
和client_header_timeout
,来控制Nginx等待从client body
和client header
写入的时间。
将以下内容添加到server
部分内。
server {
client_body_timeout 5s;
client_header_timeout 5s;
}
此外,利用基于云的解决方案可在边缘阻止DDoS攻击也是一个不错的主意。
禁用目录列表
您可以使用auto_index
指令来阻止目录列表,如下所示。您需要将其设置为off
以禁用目录列表。
location / {
auto_index off;
}
结论
我们已经配置了Nginx Web服务器以在生产环境中高效运行并保护免受滥用。如果您将Nginx用于面向互联网的Web应用程序,那么您还应考虑使用CDN和cloud-based security以获得更好的性能和安全性。