5.我在B站学运维之Nginx服务器性能优化与安全配置实践指南
全栈工程师修炼指南
2022年04月15日 17:26
收录于文集
共63篇

帅哥(靓仔)、美女,点个关注后续不迷路!

本章目录


  • 1.引言

    • 1.1 目的

    • 1.2 目标范围

    • 1.3 读者对象

  • 2.参考说明

    • 2.1 帮助参考

    • 2.2 参数说明

    • 3.3 模块说明

  • 3.服务优化

    • 3.1 系统内核

    • 3.2 编译优化

    • 3.3 性能优化

    • 3.4 运营优化

    • 3.5 配置优化

  • 4.安全配置

    • 0.隐藏nginx服务及其版本

    • 1.低权限用户运行服务

    • 2.配置SSL及其会话复用

    • 3.限制SSL协议与加密套件

    • 4.拦截垃圾信息

    • 5.恶意扫描拦截

    • 6.禁用WebDAV

    • 7.禁用Nginx状态模块

    • 8.关闭默认错误页上的Nginx版本号

    • 9.设置client_body_timeout超时

    • 10.设置client_header_timeout

    • 11.设置keepalive_timeout超时

    • 12.设置send_timeout超时

    • 13.Nginx可用的方法应限制为GET, HEAD, POST

    • 14.控制并发连接limit_zone slimits

    • 15.控制并发连接limit_conn slimits

    • 16.主机防webshell跨目录浏览以及列目录

    • 17.文件名解析漏洞php_info,加入fcgi.conf即可

    • 18.访问权限控制nginx

    • 19.异常状态返回200隐藏URL

    • 20.安全模块的选择

    • 21.记录访问者真实IP

    • 22.地区访问响应措施

    • 23.资源防盗链设置

    • 24.常规安全响应头配置

    • 25.防止非所属域名解析到服务器

    • 25.限制指定客户端地址访问

  • 5.配置说明

  • 6.补充知识


前置基础知识学习

  • 1.Nginx基础介绍与安装配置实践指南 https://blog.weiyigeek.top/2019/9-1-121.html

  • 2.Nginx进阶学习之最佳配置实践指南 https://blog.weiyigeek.top/2019/9-1-124.html

  • 3.Nginx模块学习使用实践指南 https://blog.weiyigeek.top/2021/3-1-633.html

  • 4.Nginx安全加固与性能调优最佳指南 https://blog.weiyigeek.top/2019/9-2-122.html

  • 5.Nginx常遇问题入坑出坑整理 https://blog.weiyigeek.top/2020/9-2-622.html


修订控制页


1.引言

1.1 目的

为了更好的指导部署与测试艺术升系统nginx网站服务器高性能同时下安全稳定运行,需要对nginx服务进行调优与加固;

本次进行Nginx服务调优加固主要从以下几个部分:

  • 模块性能优化

  • 系统内核优化

  • 编译安装优化

  • 性能参数优化

  • 安全加固配置

1.2 目标范围

本文档仅供内部使用,禁止外传,帮助研发人员,运维人员对系统长期稳定的运行提供技术文档参考。

1.3 读者对象

  1. 项目经理

  2. 开发人员

  3. 测试人员

  4. 运维人员

  5. 相关领导

2.参考说明

2.1 帮助参考

Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx作为负载均衡服务器, Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务,也可以支持作为 HTTP代理服务器对外进行服务。

Nginx版本选择:

  • Mainline version 最新版本,推荐测试的业务项目的时候使用

  • Stable version 稳定版本,推荐项目上线实际使用

  • Legacy versions 历史版本,不推荐选择可能存在脆弱性漏洞

项目结构:

代码块
Shell
自动换行
复制代码
#编译后的nginx项目结结构
/etc/nginx/
├── client_body_temp  #客户端上面的临时文件存放目录
├── conf              #nginx的配置文件存放目录
├── fastcgi_temp      #fastcgi的临时文件存放目录
├── html              #存放静态资源或者脚本文件的地方
├── logs              #nginx日志文件
├── proxy_temp        #nginx正向/反向代理缓存文件存放目录
├── sbin              #nginx可执行文件
├── scgi_temp         #scgi临时文件目录
└── uwsgi_temp        #uwsgi临时文件存放目录
复制成功

Nginx文档帮助: http://nginx.org/en/docs/ Nginx首页地址目录: /usr/share/nginx/html Nginx配置文件:

  • /etc/nginx/nginx.conf

  • /usr/local/nginx/conf/nginx.conf

  • /usr/local/etc/nginx/nginx.conf

2.2 参数说明

localtion 请求匹配的url实是一个正则表达式:

代码块
Shell
自动换行
复制代码
# 语法规则: 
location [=|~|~*|^~] /uri/ { ... }

# 参数解析: 
= 表示精确匹配,这个优先级也是最高的
/ 通用匹配,任何请求都会匹配到,默认匹配.
~ 表示区分大小写的正则匹配
~* 表示不区分大小写的正则匹配(和上面的唯一区别就是大小写) !~和!~*分别为区分大小写不匹配及不区分大小写不匹配的正则
!~,!~* : 分别标识为区分大小写不匹配及不区分大小写不匹配的正则
^~ 表示 uri 以某个常规字符串开头,理解为匹配 url 路径即可。nginx 不对 url 做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa 匹配到(注意是空格)
复制成功

Nginx 匹配判断表达式:

代码块
Shell
自动换行
复制代码
-f 和 !-f: 用来判断是否存在文件
-d 和 !-d: 用来判断是否存在目录
-e 和 !-e: 用来判断是否存在文件或目录
-x 和 !-x: 用来判断文件是否可执行
复制成功

例如,匹配末尾为如下后缀的静态并判断是否存在该文件, 如不存在则404。

代码块
Shell
自动换行
复制代码
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
  if (-f $request_filename) { 
    return 403;
    break;
  }
}
复制成功

3.3 模块说明

查看可用模块编译参数:http://nginx.org/en/docs/configure.html

代码块
Shell
自动换行
复制代码
#可以通过运行 "./configure --help" 查看编译帮助,决定是否需要安装哪些模块,比如下面的ssi模块能够实现访问shtml页面
./configure -help
复制成功

http_gzip模块 开启gzip压缩输出(常常是大于1kb的静态文件),减少网络传输;

代码块
Shell
自动换行
复制代码
gzip_min_length 1k #设置允许压缩的页面最小字节数页面字节数从content-length中进行获取,默认值是20
gzip_buffers 4 16k #设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,安装原始数据大小以16k为单位的4倍申请内存。
gzip_comp_level 2 #gzip压缩比,其值从1到9数字越大压缩率越高,越消耗CPU负载也越高
gzip_types #匹配mime类型进行压缩,无论是否指定”text/html”类型总是会被压缩的,推荐配置:`gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript。`
gzip_http_version 1.0 #用于识别 http 协议的版本早期的浏览器不支持 Gzip 压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项;如果你用了 Nginx 的反向代理并期望也启用 Gzip 压缩的话,由于末端通信是 http/1.0,故请设置为 1.0。
gzip_proxied any #Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
gzip_vary on #和http头有关系会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如用Squid缓存经过Nginx压缩的数据。
复制成功

http_fastcgi_module模块 nginx可以用来请求路由到FastCGI服务器运行应用程序由各种框架和PHP编程语言等。可以开启FastCGI的缓存功能以及将静态资源进行剥离,从而提高性能。

代码块
Shell
自动换行
复制代码
指令:fastcgi_temp_path  #定义FastCGI缓存文件保存临时路径。
指令:fastcgi_cache_path  #定义FastCGI缓存文件保存路径和缓存的其它参数。缓存数据以二进制数据文件形式存储,缓存文件名和key都是通过对访问URL使用MD5计算获得的结果。缓存文件先保存至fastcgi_temp_path指定的临时目录下,然后通过重命名操作移至fastcgi_cache_path指定的缓存目录。建议fastcgi_temp_path和fastcgi_cache_path设为同一分区,同分区移动操作效率更高。示例:
fastcgi_temp_path /tmp/fastcgi_temp;
fastcgi_cache_path /tmp/fastcgi_cache levels=1:2 keys_zone=cache_fastcgi:16m inactive=30m max_size=1g;
# levels指定了目录结构,子目录数以16为基数;
# keys_zone指定了共享内存区名和大小,用于保存缓存key和数据信息;
# inactive指定了缓存数据保存的时间,当这段时间内未被访问将被移出;
# max_size指定了缓存使用的最大磁盘空间,超过容量时将最近最少使用数据删除。
#示例中使用/tmp/fastcgi_temp作为FastCGI缓存的临时目录;/tmp/fastcgi_cache作为FastCGI缓存保存的最终目录;一级子目录为16的一次方16个,二级子目录为16的2次方256个;共享内存区名为cache_fastcgi,占用内存128MB;缓存过期时间为30分钟;缓存数据保存于磁盘的最大空间大小为1GB。

指令:fastcgi_cache_key        # 定义FastCGI缓存关键字。启用FastCGI缓存必须加上这个配置,不然访问所有PHP的请求都为访问第一个PHP文件URL的结果。
指令:fastcgi_cache_valid      # 为指定的Http状态码指定缓存时间。
指令:fastcgi_cache_min_uses   # 指定经过多少次请求相同的URL将被缓存。
指令:fastcgi_cache_use_stale  # 指定当连接FastCGI服务器发生错误时,哪些情况使用过期数据回应。
指令:fastcgi_cache            # 缓存使用哪个共享内存区
复制成功

keepalive模块 长连接对性能有很大的影响,通过减少CPU和网络开销需要开启或关闭连接;

  • keepalive_timeout 闲长连接保持打开状态的时间;

  • keepalive_requests 单个客户端长连接可以请求的数量;

  • keepalive 上游服务器长连接的相关指令,每个工作进程中空闲长连接到上游服务器保持开启的连接数量(没有默认值)。 要使用连接到上游服务器的长连接,必须要配置文件中下面的指令:

代码块
Shell
自动换行
复制代码
proxy_http_version 1.1;
proxy_set_header Connection "";
复制成功

http_ssl_module模块 Nginx开启支持Https协议的SSL模块

代码块
Shell
自动换行
复制代码
#Nginx SSL性能调优
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#注意这里的加密方式
ssl_ciphers ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!AESGCM;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
复制成功

3.服务优化

3.1 系统内核

Linux内核参数部分默认值不适合高并发,Linux内核调优,主要涉及到网络和文件系统、内存等的优化,

  • 临时方法可以通过调整/Proc文件系统,需要注意调整/Proc文件系统系统重启后还原至默认值(不推荐)。

  • 永久修改/etc/sysctl.conf配置文件永久保存

下面是我常用的内核调优配置:

代码块
Shell
自动换行
复制代码
grep -q "net.ipv4.tcp_max_tw_buckets" /etc/sysctl.conf || cat >> /etc/sysctl.conf << EOF
########################################
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216

#缓冲区队列设置与连接及其如何排队相关#
#调节系统同时发起的tcp连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此需要结合并发请求数来调节此值。
#net.core.somaxconn = 262144
#在提交到CPU前网卡中数据包缓冲的速率,高带宽下提高这个值可提高性能;检查内核日志文件中有关这个设置的错误,根据网卡文档中的建议修改这个值。
net.core.netdev_max_backlog = 262144
#设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上
net.ipv4.tcp_max_orphans = 262144
#用于记录那些尚未收到客户端确认信息的连接请求的最大值(根据类才更改)
net.ipv4.tcp_max_syn_backlog = 1024

#设定timewait的数量默认是180000设为10000。
net.ipv4.tcp_max_tw_buckets = 10000

#在高并发情况端口值的起止范围一般端口号设置是1024到65000,用来设定允许系统打开的端口范围;
net.ipv4.ip_local_port_range = 1024 65500

#用于设置启用timewait快速回收
net.ipv4.tcp_tw_recycle = 1

#用于设置开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接。
net.ipv4.tcp_tw_reuse = 1

#用于设置开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies进行处理。
net.ipv4.tcp_syncookies = 1

#决定了内核放弃连接之前发送SYN+ACK包的数量。
net.ipv4.tcp_synack_retries = 1
#表示在内核放弃建立连接之前发送SYN包的数量。
net.ipv4.tcp_syn_retries = 1
#决定了套接字保持在FIN-WAIT-2状态的时间。默认值是60秒。
#正确设置这个值非常重要,有时即使一个负载很小的Web服务器,也会出现大量的死套接字而产生内存溢出的风险。
net.ipv4.tcp_fin_timeout = 30
#选项表示当keepalive启用的时候,TCP发送keepalive消息的频度。默认值是2(单位是小时)。
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_mem = 786432 1048576 1572864


#文件描述符系统级别的限制#
kernel.sem = 250 32000 100 128
fs.file-max = 6815744
vm.swappiness = 10
fs.aio-max-nr = 1048576
EOF
sysctl -p
复制成功

文件描述符 文件描述符是操作系统资源,用于表示连接、打开的文件,以及其他信息。NGINX 每个连接可以使用两个文件描述符。 例如如果NGINX充当代理时,通常一个文件描述符表示客户端连接,另一个连接到代理服务器,如果开启了HTTP 保持连接,这个比例会更低(译注:为什么更低呢)。

对于有大量连接服务的系统,下面的设置可能需要调整一下:

代码块
Shell
自动换行
复制代码
#修改文件描述符方式
vim /etc/security/limits.conf
* - nofile 65536  #用户级别文件描述符限制

#然后进行启动文件修改
echo "ulimit -Hsn 65536" >> /etc/profile
复制成功

3.2 编译优化

精简模块:Nginx由于不断添加新的功能,附带的模块也越来越多,建议一般常用的服务器软件;

(1) 减小Nginx编译后的文件大小

  • 编译Nginx时默认以debug模式进行,而在debug模式下会插入很多跟踪和ASSERT之类的信息,编译完成后一个Nginx要有好几兆字节;因此可以在编译之前,修改相关源码,取消debug模式;

代码块
Shell
自动换行
复制代码
# 找到源码目录下 auto/cc/gcc  文件 debug
CFLAGS="$CFLAGS -g" #注释掉或删掉这两行,即可取消debug模式。

ls -alh /usr/local/nginx/sbin/nginx
-rwxr-xr-x. 1 root root 915K Aug 17 09:49 /usr/local/nginx/sbin/nginx  #可以看到体积大大减少
复制成功

(2) 指定GCC编译参数 修改GCC编译参数提高编译优化级别稳妥起见采用  这也是大多数软件编译推荐的优化级别。

  • Nginx源码文件 auto/cc/gcc 搜索 NGX_GCC_OPT默认GCC编译参数为-O,可以直接修改内容为 NGX_GCC_OPT="-O2&#​34; 或者在 ./configure配置时添加--with-cc-opt='-O2&#​39;选项

代码块
Shell
自动换行
复制代码
--with-cc-opt='-O3'  #编译级别
--with-cpu-opt=CPU   #为特定的 CPU 编译,有效的值包括:pentium, pentiumpro, pentium3, # pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64
复制成功

GCC编译参数优化 [可选项] 总共提供了5级编译优化级别:

  • -O0:无优化。

  • -O和-O1:使用能减少目标代码尺寸以及执行时间并且不会使编译时间明显增加的优化,在编译大型程序的时候会显著增加编译时内存的使用。

  • -O2:包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化。编译器不执行循环展开以及函数内联。此选项将增加编译时间和目标文件的执行性能。

  • -Os:可以看成 -O2.5,专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项,并且执行专门减小目标文件大小的优化选项。适用于磁盘空间紧张时使用。但有可能有未知的问题发生,况且目前硬盘容量很大,常用程序无必要使用。

  • -O3:打开所有 -O2 的优化选项外增加 -finline-functions、-funswitch-loops、-fgcse-after-reload 优化选项。相对于 -O2 性能并未有较多提高,编译时间也最长,生成的目标文件也更大更占内存,有时性能不增反而降低,甚至产生不可预知的问题(包括错误),所以并不被大多数软件安装推荐,除非有绝对把握方可使用此优化级别。

常用编译参数:

代码块
Shell
自动换行
复制代码
#编译0:常规编译参数
configure arguments: 
#安装的目录或者路径#
--prefix=/etc/nginx 
--sbin-path=/usr/sbin/nginx 
--modules-path=/usr/lib64/nginx/modules 
--conf-path=/etc/nginx/nginx.conf 
--error-log-path=/var/log/nginx/error.log 
--http-log-path=/var/log/nginx/access.log 
--pid-path=/var/run/nginx.pid 
--lock-path=/var/run/nginx.lock
#执行对应模块nginx所保留的临时文件#
--http-client-body-temp-path=/var/cache/nginx/client_temp 
--http-proxy-temp-path=/var/cache/nginx/proxy_temp 
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 
--http-scgi-temp-path=/var/cache/nginx/scgi_temp 
#启动的用户和组用户#
--user=nginx 
--group=nginx 
#模块参数#
--with-compat 
--with-file-aio 
--with-threads 
--with-http_addition_module 
--with-http_auth_request_module 
--with-http_dav_module 
--with-http_flv_module 
--with-http_gunzip_module 
--with-http_gzip_static_module 
--with-http_mp4_module 
--with-http_random_index_module 
--with-http_realip_module 
--with-http_secure_link_module 
--with-http_slice_module 
--with-http_ssl_module 
--with-http_stub_status_module 
--with-http_sub_module 
--with-http_v2_module 
--with-mail 
--with-mail_ssl_module 
--with-stream 
--with-stream_realip_module 
--with-stream_ssl_module 
--with-stream_ssl_preread_module
#设置额外的参数将被添加到CFLAGS#
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' 
#设置附件参数,链接系统库#
-with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'


#编译1:除多余模块
./configure \
"--prefix=/App/nginx" \ 
"--user=nginx" \ 
"--group=nginx" \
"--with-http_stub_status_module" \
"--without-http_auth_basic_module" \
"--without-http_autoindex_module" \
"--without-http_browser_module" \
"--without-http_empty_gif_module" \
"--without-http_geo_module" \
"--without-http_limit_conn_module" \
"--without-http_limit_req_module" \
"--without-http_map_module" \
"--without-http_memcached_module" \
"--without-http_proxy_module" \
"--without-http_referer_module" \
"--without-http_scgi_module" \
"--without-http_split_clients_module" \
"--without-http_ssi_module" \
"--without-http_upstream_ip_hash_module" \
"--without-http_upstream_keepalive_module" \
"--without-http_upstream_least_conn_module" \
"--without-http_userid_module" \
"--without-http_uwsgi_module" \
"--without-mail_imap_module" \
"--without-mail_pop3_module" \
"--without-mail_smtp_module" \
"--without-poll_module" \
"--without-select_module" \
"--with-cc-opt='-O2'"
复制成功

3.3 性能优化

缓存和压缩与限制可以提高性能 NGINX的一些额外功能可用于提高Web应用的性能,调优的时候web应用不需要关掉但值得一提,因为它们的影响可能很重要。

  • 1)缓存 一个启用NGINX缓存的情景,一组web或者应用服务器负载均衡,可以显著缩短对客户端的响应时间,同时大幅度降低后端服务器的负载。缓存本身就可以作个专题来讲,这里我们就不试图讲它了。

代码块
Shell
自动换行
复制代码
# 网页资源缓存
location ~* \.(xml|html|htm)$ {
  # 资源决绝对目录设置
  root /var/www/html;
  # 日志文件的相对路径或完整路径
  access_log /path/to/file.log;
  # 开启日志记录
  access_log on;
  # 设置过期时间
  expires 24h;
}

# 样式、JS、图片资源缓存
location ~* \.(css|js|ico|gif|jpg|jpeg|png)$ {
  root /var/www/html/res;
  # 禁用404错误日志
  log_not_found off;
  # 关闭日志
  access_log off;
  # 缓存时间7天
  expires 7d;
}

# 字体资源缓存
location ~* \.(eot|ttf|otf|woff|woff2|svg)$ {
  root /var/www/html/static;
  log_not_found off;
  access_log off;
  expires max;
}
复制成功

  • 2)压缩 所以使用更小的网络带宽。然而尽管压缩数据会消耗CPU资源,但当需要减少网络带宽使用时这样做非常有效。需要注意的是,不能对已压缩的文件再压缩例如JPEG 文件。

    • 3)限制 防止用户消耗太多的资源,避免影响系统性能和用户体验及安全性,以下是相关的指令:

  • 4)减少磁盘IO 减少磁盘IO次数可以帮助我们更好的提升服务器性能,增强服务器的负载能力。

  • Concat源代码网址:https://github.com/alibaba/nginx-http-concat/

  • PageSpeed源代码网址:https://github.com/pagespeed/ngx_pagespeed。

  • 1.增加FastCGI进程数:把PHP FastCGI子进程数调到100或以上,在4G内存的服务器上200就可以建议通过压力测试获取最佳值。

  • 2.增加 PHP-FPM打开文件描述符的限制

  • 3.适当增加max_requests: 标签max_requests指明了每个children最多处理多少个请求后便会被关闭默认的设置是500。