[TOC]
修订控制页 |版本 |修订日期 |修订人 |修订摘要| |—|—|—|—| |1.0| 2019年9月8日 09点18分 |WeiyiGeek |初稿| |2.0| 2022年1月8日 18点18分 |WeiyiGeek |扩充|
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 历史版本,不推荐选择可能存在脆弱性漏洞
项目结构:
[TOC]
修订控制页 |版本 |修订日期 |修订人 |修订摘要| |—|—|—|—| |1.0| 2019年9月8日 09点18分 |WeiyiGeek |初稿| |2.0| 2022年1月8日 18点18分 |WeiyiGeek |扩充|
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 历史版本,不推荐选择可能存在脆弱性漏洞
项目结构:1 2 3 4 5 6 7 8 9 10 11 /etc/nginx/ ├── client_body_temp ├── conf ├── fastcgi_temp ├── html ├── logs ├── proxy_temp ├── sbin ├── scgi_temp └── uwsgi_temp
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实是一个正则表达式:1 2 3 4 5 6 7 8 9 10 location [=|~|~*|^~] /uri/ { ... } = 表示精确匹配,这个优先级也是最高的 / 通用匹配,任何请求都会匹配到,默认匹配. ~ 表示区分大小写的正则匹配 ~* 表示不区分大小写的正则匹配(和上面的唯一区别就是大小写) !~和!~*分别为区分大小写不匹配及不区分大小写不匹配的正则 !~,!~* : 分别标识为区分大小写不匹配及不区分大小写不匹配的正则 ^~ 表示 uri 以某个常规字符串开头,理解为匹配 url 路径即可。nginx 不对 url 做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa 匹配到(注意是空格)
Nginx 匹配判断表达式:1 2 3 4 -f 和 !-f: 用来判断是否存在文件 -d 和 !-d: 用来判断是否存在目录 -e 和 !-e: 用来判断是否存在文件或目录 -x 和 !-x: 用来判断文件是否可执行
例如,匹配末尾为如下后缀的静态并判断是否存在该文件, 如不存在则404。1 2 3 4 5 6 location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ { if (-f $request_filename) { return 403; break; } }
3.3 模块说明 查看可用模块编译参数:http://nginx.org/en/docs/configure.html
http_gzip模块 开启gzip压缩输出(常常是大于1kb的静态文件),减少网络传输;1 2 3 4 5 6 7 gzip_min_length 1k gzip_buffers 4 16k gzip_comp_level 2 gzip_types gzip_http_version 1.0 gzip_proxied any gzip_vary on
http_fastcgi_module模块 nginx可以用来请求路由到FastCGI服务器运行应用程序由各种框架和PHP编程语言等。可以开启FastCGI的缓存功能以及将静态资源进行剥离,从而提高性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 指令: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; 指令:fastcgi_cache_key 指令:fastcgi_cache_valid 指令:fastcgi_cache_min_uses 指令:fastcgi_cache_use_stale 指令:fastcgi_cache
keepalive模块 长连接对性能有很大的影响,通过减少CPU和网络开销需要开启或关闭连接;
keepalive_timeout 闲长连接保持打开状态的时间;
keepalive_requests 单个客户端长连接可以请求的数量;
keepalive 上游服务器长连接的相关指令,每个工作进程中空闲长连接到上游服务器保持开启的连接数量(没有默认值)。 要使用连接到上游服务器的长连接,必须要配置文件中下面的指令:1 2 proxy_http_version 1.1; proxy_set_header Connection "" ;
http_ssl_module模块 Nginx开启支持Https协议的SSL模块1 2 3 4 5 6 7 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配置文件永久保存
下面是我常用的内核调优配置:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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 net.core.netdev_max_backlog = 262144 net.ipv4.tcp_max_orphans = 262144 net.ipv4.tcp_max_syn_backlog = 1024 net.ipv4.tcp_max_tw_buckets = 10000 net.ipv4.ip_local_port_range = 1024 65500 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_fin_timeout = 30 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 保持连接,这个比例会更低(译注:为什么更低呢)。
对于有大量连接服务的系统,下面的设置可能需要调整一下:1 2 3 4 5 6 vim /etc/security/limits.conf * - nofile 65536 echo "ulimit -Hsn 65536" >> /etc/profile
3.2 编译优化 精简模块:Nginx由于不断添加新的功能,附带的模块也越来越多,建议一般常用的服务器软件使用源码编译安装管理
;
(1) 减小Nginx编译后的文件大小
编译Nginx时默认以debug模式进行,而在debug模式下会插入很多跟踪和ASSERT之类的信息,编译完成后一个Nginx要有好几兆字节;因此可以在编译之前,修改相关源码,取消debug模式;1 2 3 4 5 CFLAGS="$CFLAGS -g" 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编译参数提高编译优化级别稳妥起见采用 -O2
这也是大多数软件编译推荐的优化级别。
Nginx源码文件 auto/cc/gcc 搜索 NGX_GCC_OPT默认GCC编译参数为-O,可以直接修改内容为 NGX_GCC_OPT="-O2" 或者在 ./configure配置时添加--with-cc-opt='-O2'选项
。
1 2 --with-cc-opt='-O3' --with-cpu-opt=CPU
weiyigeek.top-
GCC编译参数优化 [可选项] 总共提供了5级编译优化级别:
-O0:无优化。
-O和-O1:使用能减少目标代码尺寸以及执行时间并且不会使编译时间明显增加的优化,在编译大型程序的时候会显著增加编译时内存的使用。
-O2:包含-O1的优化并增加了不需要在目标文件大小和执行速度上进行折衷的优化。编译器不执行循环展开以及函数内联。此选项将增加编译时间和目标文件的执行性能。
-Os:可以看成 -O2.5,专门优化目标文件大小,执行所有的不增加目标文件大小的-O2优化选项,并且执行专门减小目标文件大小的优化选项。适用于磁盘空间紧张时使用。但有可能有未知的问题发生,况且目前硬盘容量很大,常用程序无必要使用。
-O3:打开所有 -O2 的优化选项外增加 -finline-functions、-funswitch-loops、-fgcse-after-reload 优化选项。相对于 -O2 性能并未有较多提高,编译时间也最长,生成的目标文件也更大更占内存,有时性能不增反而降低,甚至产生不可预知的问题(包括错误),所以并不被大多数软件安装推荐,除非有绝对把握方可使用此优化级别。
常用编译参数:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 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 --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 --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' ./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或者应用服务器负载均衡,可以显著缩短对客户端的响应时间,同时大幅度降低后端服务器的负载。缓存本身就可以作个专题来讲,这里我们就不试图讲它了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 location ~* \.(xml|html|htm)$ { root /var/www/html; access_log /path/to/file.log; access_log on; expires 24h; } location ~* \.(css|js|ico|gif|jpg|jpeg|png)$ { root /var/www/html/res; log_not_found off; access_log off; 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 文件。
1 2 3 4 5 6 7 8 9 10 gzip on; gzip_min_length 2k; gzip_comp_level 2; gzip_types text/html text/plain text/css text/javascript application/javascript application/x-javascript application/xml application/x-httpd-php image/x-icon image/jpeg image/gif image/png image/svg+xml image/avif image/webp font/ttf font/opentype; gzip_vary on;
3)限制 防止用户消耗太多的资源,避免影响系统性能和用户体验及安全性,以下是相关的指令:
1 2 3 4 5 limit_conn and limit_conn_zone limit_req and limit_req_zon limit_rate max_conns queue (NGINX Plus - 商业版本提供)
简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 http { limit_conn_zone $binary_remote_addr zone=www_weiyigeek_top:10m; limit_req_zone $binary_remote_addr zone=blog_weiyigeek_top:10m rate=1r/s; server { allow 内部IP或负载均衡IP; deny 恶意IP; location ^~ /download/ { limit_conn www_weiyigeek_top 2; limit_req zone=blog_weiyigeek_top burst=5 nodelay; alias /data/weiyigeek.top/download/; } } }
4)减少磁盘IO 减少磁盘IO次数可以帮助我们更好的提升服务器性能,增强服务器的负载能力。
1 2 3 4 5 6 access_log off; error_log /dev/null access_log /var/log /nginx/access.log main buffer=128k gzip flush=1m;
3.4 运营优化 1) 永久重定向
如果你的站点需要让http URL跳转到https,则非建议设置永久重定向,而非临时重定向,这可以帮助你站点更好的被收录(SEO)。
例如,配置 http 向 https 跳转 (永久)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server { listen 80; server_name weiyigeek.top www.weiyigeek.top; return 301 https://$host $request_uri ; } server { listen 80; server_name weiyigeek.top www.weiyigeek.top; if ($http_host !~ "^www\.weiyigeek\.top$" { rewrite ^(.*) https://www.weiyigeek.top$1 permanent; } }
3.5 配置优化 nginx配置文件指令优化一览表
位置
指令
说明
优化
main
worker_processes
工作进程数的选择包括(但不限于)CPU核心的数量、存储数据的硬盘数量及负载模式
设置 auto 或者 `cat /proc/cpuinfo
grep processor
wc -l` 服务器逻辑核心总数
main
worker_cpu_affinity
Nginx默认未开启CPU绑定,绑定工作进程到对应CPU核心
多核CPU建议设置CPU绑定,绑定样例: worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
main
worker_rlimit_nofile
打开文件数限制(默认值1024),受限于系统的用户进程打开文件数限制,未设置则使用系统默认值
修改用户打开文件数限制: echo "* - nofile 65536" >> /etc/security/limits.conf
修改所有Shell和通过Shell启动的进程打开文件数限制: echo "ulimit -n 65536" >> /etc/profile
临时生效(重启后生效): ulimit -n 65536
main
worker_connections
Nginx一个工作进程的最大同时连接数,不仅限于客户端连接,包括了和后端被代理服务器等其他的连接
建议设置成与 worker_rlimit_nofile
值相等
mian
sendfile
在http或server或location环境中包含sendfile指令。 NGINX可以不需要切换到用户态,就把缓存或磁盘上的内容写入套接字而且写的速度非常快,消耗更少的CPU周期。 注意尽管使用sendfile()数据拷贝可以绕过用户态但不适用于常规的NGINX处理改变内容的链和过滤器比如gzip
建议设置成 on
main-events
accept_mutex
惊群问题: 如果指令值为 on 启用,那么将轮流唤醒一个工作进程接收处理新的连接,其余工作进程继续保持睡眠 如果指令值为 off 关闭,那么将唤醒所有工作进程,由系统通过use指令指定的网络IO模型调度决定由哪个工作进程处理,未接收到连接请求的工作进程继续保持睡眠
on开启状态为了稳定参数值; off关闭状态提高性能和吞吐量但是会带来上下文切换增多或者负载升高等等其它资源更多消耗的后果(推荐)
main-events
use
定义了Nginx设置用于复用客户端线程的轮询方法(也可称多路复用网络IO模型),自然是选择效率更高的优先(默认即可)
use epoll
main
open_file_cache
开启关闭打开文件缓存默认值 off 关闭,强烈建议开启可以避免重新打开同一文件带来的系统开销节省响应时间
max=数字设置缓存元素的最大数量 inactive=时间设置超时 当缓存溢出时使用LRU(最近最少使用)算法删除缓存中的元素;在这段时间内缓存元素如果没有被访问将从缓存中删除; open_file_cache max=65536 inactive=60s
main
open_file_cache_valid
设置检查open_file_cache缓存的元素的时间间隔
80s
main
open_file_cache_min_uses
设置在由open_file_cache指令的inactive参数配置的超时时间内文件应该被访问的最小次数。 如果访问次数大于等于此值,文件描述符会保留在缓存中,否则从缓存中删除。
1
main
error_log
错误的访问请求日志记录,当并发很大时Nginx的访问日志和错误日志的保存肯定会造成对磁盘的大量读写也将影响Nginx的性能
注释即可 或者 错误日志设置为 error 或者 crit
main-http
access_log
成功的访问请求日志记录, 如必须保存日志,可以按每日或者每时或者其它时间段对日志做切割,这也可以减小IO,虽然可能效果不是特别大,不过因为日志文件尺寸变小了很多,也方便查阅或归档分析日志
建议开启日志记录级别 main
main-http
gzip
默认开启了gzip压缩功能:增加CPU的处理时间和负载(默认即可) 关闭gzip压缩功能:虽然减少了CPU计算节省了服务器的响应时间,但网站页面总体响应时间反而加长了静态文件数据传输时间增加;
设置 gzip on 即可;(该模块中有附带参数)
main-http
keepalive_timeout
空闲长连接保持打开状态的时间;复用之前已建立的TCP连接接收请求、发送回应,减少重新建立TCP连接的资源时间开销
正数为开启持久连接(常规设置120)而0关闭。 当网站页面内容以静态为主时,开启持久连接; 动态网页且不能被转化为静态页面,则关闭持久连接;
main-http
keepalive_requests
单个客户端长连接可以请求的数量但是当使用压力测试工具从一个客户端发送多个请求测试时,这个值设更高些特别有用
默认值是100
main-http-server-location
expires
浏览器缓存设置HTTP应答中的“Expires”和“Cache-Control”头标。”Expires”一般结合”Last-Modified”使用比较缓存时间,避免了从服务器再次传送文件内容减小了服务器压力,节省了带宽同时也提高了用户访问速度
-1 表示永远过期不缓存,推荐静态文件如js/css等等访问设置 expires 30d
a;
4.安全配置 描述:Nginx因为安全配置不合适导致的安全问题,Nginx的默认配置中存在一些安全问题,例如版本号信息泄露、未配置使用SSL协议等。 对Nginx进行安全配置可以有效的防范一些常见安全问题,按照基线标准做好安全配置能够减少安全事件的发生,保证采用Nginx服务器系统应用安全运行;
Nginx安全配置项:
0.隐藏nginx服务及其版本 温馨提示: 在修改相应的源代码文件后需重新编译。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static char ngx_http_server_string[] = "Server: LTWS" ; static u_char ngx_http_error_full_tail[] = "<center> NGINX_VER </center>" "<hr><center> http://www.weiyigeek.com</center>" "</body>" "</html>" ; static u_char ngx_http_error_tail[] = "<hr><center>LTWS</center>" "</body>" "</html>" ;
weiyigeek.top-修改服务名及其版本对应文件
设置成功后验证:
weiyigeek.top-验证服务名及其版本修改
1.低权限用户运行服务 应配置非root低权限用户来运行nginx服务,设置如下建立Nginx用户组和用户,采用user指令指运行用户
加固方法:1 2 3 4 5 6 groupadd nginxweb; useradd -M -g nginxweb -s /sbin/nologin nginxweb user nginxweb
2.配置SSL及其会话复用 我们应该为提供的站点配置Secure Sockets Layer Protocol (SSL协议),配置其是为了数据传输的安全,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 server { listen 443 ssl http2; listen [::]:443 ssl http2; ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/weiyigeek.top.key; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ...... }
3.限制SSL协议与加密套件 不应使用不安全SSLv2、SSLv3协议即以下和存在脆弱性的加密套件(ciphers), 我们应该使用较新的TLS协议也应该优于旧的,并使用安全的加密套件。1 2 3 4 5 6 ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4; ssl_prefer_server_ciphers on;
4.拦截垃圾信息 HTTP Referrer Spam是垃圾信息发送者用来提高他们正在尝试推广的网站的互联网搜索引擎排名一种技术,如果他们的垃圾信息链接显示在访问日志中,并且这些日志被搜索引擎扫描,则会对网站排名产生不利影响 加固方法:1 2 3 if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ){ return 403; }
5.恶意扫描拦截 当恶意攻击者采用扫描器进行扫描时候利用use-agent判断是否是常用的工具扫描以及特定的版本,是则返回错误或者重定向;1 2 3 4 5 6 7 8 9 10 11 12 13 14 if ($http_user_agent ~* "java|python|perl|ruby|curl|bash|echo|uname|base64|decode|md5sum|select|concat|httprequest|httpclient|nmap|scan|nessus|wvs" ) { return 403; } if ($http_user_agent ~* "" ) { return 403; } location ~* \.(bak|swp|save|sh|sql|mdb|svn|git|old)$ { rewrite ^/(.*)$ $host permanent; } location /(admin|phpadmin|status) { deny all; }
weiyigeek.top-恶意扫描拦截
6.禁用WebDAV Nginx支持webdav,虽然默认情况下不会编译。如果使用webdav,则应该在Nginx策略中禁用此规则。 加固方法: dav_methods 应设置为off
7.禁用Nginx状态模块 当访问一个特制的URL时,如”../nginx.status”,stub_status模块提供一个简短的Nginx服务器状态摘要,大多数情况下不应启用此模块。 加固方法:nginx.conf文件中stub_status不应设置为:on
8.关闭默认错误页上的Nginx版本号 如果在浏览器中出现Nginx自动生成的错误消息,默认情况下会包含Nginx的版本号,这些信息可以被攻击者用来帮助他们发现服务器的潜在漏洞 加固方法: 关闭”Server”响应头中输出的Nginx版本号将server_tokens应设置为:off
9.设置client_body_timeout超时 client_body_timeout设置请求体(request body)的读超时时间。仅当在一次readstep中,没有得到请求体,就会设为超时。超时后Nginx返回HTTP状态码408(Request timed out)。 加固方法:nginx.conf文件中client_body_timeout应设置为:10
client_header_timeout设置等待client发送一个请求头的超时时间(例如:GET / HTTP/1.1)。仅当在一次read中没有收到请求头,才会设为超时。超时后Nginx返回HTTP状态码408(Request timed out)。
加固方法:nginx.conf文件中client_header_timeout应设置为:10
11.设置keepalive_timeout超时 keepalive_timeout设置与client的keep-alive连接超时时间。服务器将会在这个时间后关闭连接。
加固方法:nginx.conf文件中keepalive_timeout应设置为:55
12.设置send_timeout超时 send_timeout设置客户端的响应超时时间。这个设置不会用于整个转发器,而是在两次客户端读取操作之间。如果在这段时间内,客户端没有读取任何数据,Nginx就会关闭连接。
加固方法:nginx.conf文件中send_timeout应设置为:10
13.Nginx可用的方法应限制为GET, HEAD, POST GET和POST是Internet上最常用的方法。Web服务器方法在RFC 2616中定义禁用不需要实现的可用方法。
加固方法:1 2 if ($request_method !~ ^(GET|HEAD|POST)$ )
14.控制并发连接limit_zone slimits limit_zone 配置项限制来自客户端的同时连接数。通过此模块可以从一个地址限制分配会话的同时连接数量或特殊情况。
加固方法:nginx.conf文件中limit_zone应设置为:slimits $binary_remote_addr 5m
1 2 limit_conn_zone $binary_remote_addr zone=ops:10m;
15.控制并发连接limit_conn slimits 该配置项控制一个会话同时连接的最大数量,即限制来自单个IP地址的连接数量。
加固方法:nginx.conf 文件中 limit_conn 应设置为: slimits 5
16.主机防webshell跨目录浏览以及列目录 加固方法:1 2 3 4 5 6 7 a.在nginx.conf里把每个虚拟主机站点请求端口给区别开 b.为每个站点建一个conf,并进行配置 c.修改php-fpm启动脚本 d.启动服务 autoindex off
17.文件名解析漏洞php_info,加入fcgi.conf即可 1 2 3 4 5 6 7 if ($request_filename ~* (.*)\.php) { set $php_url $1 ; } if (!-e $php_url .php) { return 403; }
18.访问权限控制nginx 加固方法:1 2 3 4 5 6 7 8 9 10 11 12 13 location ~ ^/script/ { auth_basic "welcome to weiyigeek.github.io" ; auth_basic_user_file /var/www/test /script/.htpasswd; } mkdir /var/www/test /script perl -e "print crypt('baidu.eud'," n");" nnUygd3RSf3u6 echo 'nginx:nnUygd3RSf3u6' > /var/www/test /script/.htpasswd/usr/local /nginx/sbin/nginx -s reload
weiyigeek.top-
19.异常状态返回200隐藏URL 解决办法:1 2 3 4 5 6 7 server{ listen 80; server_name weiyigeek.top; index index.html index.htm index.php; root /data/web; error_page 404 =200 /404.jpg; }
20.安全模块的选择 1 2 3 4 5 http_sub_module http_stub_status_module xss-nginx-module with-http_ssl_module
21.记录访问者真实IP 描述后端获取Proxy后的真实Client的IP获取需要安装--with-http_realip_module
,然后后端程序采用JAVA(request.getAttribute("X-Real-IP")
)进行获取;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 set_real_ip_from 100.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on; location / { proxy_pass http://weiyigeek.top } proxy_set_header Host $host ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; set $Real $http_x_forwarded_for ;if ( $Real ~ (\d+)\.(\d+)\.(\d+)\.(\d+),(.*) ){ set $Real $1 .$2 .$3 .$4 ; } proxy_set_header X-Real-IP $remote_addr ; $proxy_add_x_forwarded_for $http_x_forwarded_for $http_x_real_ip |$remote_addr
22.地区访问响应措施 描述: 如果要使用geoip地区选择,我们需要再nginx编译时加入 --with-http_geoip_module
编译参数。1 2 3 4 # 例如,访问者IP地址不为中国或者美国的都返回403。 if ( $geoip_country_code !~ ^(CN|US)$ ) { return 403; }
23.资源防盗链设置 描述: 为了防止外部站点引用我们的静态资源,我们需要设置那些域名可以访问我们的静态资源。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked weiyigeek.top server_names ~\.google\. ~\.baidu\.; if ($invalid_referer ) { return 403; add_header Content-Type 'application/json; charset=utf-8' ; return 200 "{'msg':'valid'}" ; rewrite ^/.*.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last; rewrite ^/ https://www.weiyigeek.top/picture/images/details-image-1.jpg; } }
24.常规安全响应头配置 描述: 下面收集了Web服务中常规的安全响应头, 它可以保证不受到某些攻击,建议在指定的 server{}
代码块进行配置。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 add_header Strict-Transport-Security "max-age=31536000;includeSubDomains;preload" always; add_header X-XSS-Protection "1; mode=block" ; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options ALLOW-FROM music.163.com; add_header X-Robots-Tag none; add_header Access-Control-Allow-Origin '*.weiyigeek.top' ; add_header Access-Control-Allow-Methods 'GET' ; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' ; Content-Security-Policy: default-src 'none' ; script-src 'self' https://code.jquery.com https://www.google-analytics.com; img-src 'self' https://www.google-analytics.com; connect-src 'self' ; font-src 'self' ; style-src 'self' ;
25.防止非所属域名解析到服务器 描述: 为了防止某些未备案的域名或者恶意镜像站域名绑定到我们服务器上, 导致服务器被警告关停,将会对业务或者SEO排名以及企业形象造成影响,我们可以通过如下方式进行防范。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 server { listen 80 default_server; server_name 82.156.18.253; add_header X-Robots-Tag 'noindex,noarchive,nosnippet' ; location ^~ / { if ( $host = 82.156.18.253 ){ return 301 https://www.weiyigeek.top/index.html; } if ( $host !~* weiyigeek\.top ) { add_header Content-Type 'application/json; charset=utf-8' ; return 200 '{"status":"error","Author":"WeiyiGeek","Site":"https://www.weiyigeek.top","Chinese":"大佬, 请不要把你的域名解析到我的服务器上","English":"Friend, Please do not resolve your domain name to my server"}' ; } } ... }
执行结果: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ curl -I 82.156.18.253 HTTP/1.1 301 Moved Permanently Server: nginx Date: Mon, 11 Apr 2022 12:15:02 GMT Content-Type: text/html Content-Length: 162 Connection: keep-alive Location: https://www.weiyigeek.top/index.html X-Robots-Tag: noindex,noarchive,nosnippet $ curl --insecure -I https://82.156.18.253 HTTP/2 301 server: nginx date: Mon, 11 Apr 2022 12:15:24 GMT content-type: text/html content-length: 162 location: https://www.weiyigeek.top/index.html x-robots-tag: noindex,noarchive,nosnippet $ curl weiyigeek.cn {"status" :"error" ,"Author" :"WeiyiGeek" ,"Site" :"https://www.weiyigeek.top" ,"Chinese" :"大佬, 请不要把你的域名解析到我的服务器上" ,"English" :"Friend, Please do not resolve your domain name to my server" }
25.限制指定客户端地址访问 描述: 有时你的网站可能只需要被某一IP或者IP段的地址请求访问,那么非白名单中的地址访问将被阻止访问, 我们可以如下配置;1 2 3 4 5 6 location / { allow 12.97.167.194; allow 12.33.1.2; allow 12.152.49.4; deny all; }
5.配置说明 常用nginx配置文件解释: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 user nginx; worker_processes auto; events { worker_connections 65535; use epoll; accept_mutex off; } worker_cpu_affinity 0001 0010 0100 1000; worker_rlimit_nofile 65535 error_log logs/error.log error; pid /var/run/nginx.pid; include /etc/nginx/conf.d/*.conf; http { include mime.types; default_type text/html; charset UTF-8; server_names_hash_bucket_size 128; client_body_buffer_size 128k client_header_buffer_size 4k; client_max_body_size 50m open_file_cache max=65536 inactive=60s; open_file_cache_valid 80s; open_file_cache_min_uses 1; large_client_header_buffers 4 64k; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' ; log_format custom '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" rt=$request_time urt=$upstream_response_time' ; access_log logs/access.log main buffer=1024 flush=60s; access_log /var/log /nginx/access.log custom buffer=128k flush=5m; server_tokens off; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 120; gzip on; gzip_min_length 1k; gzip_buffers 4 64k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; server { listen 80; server_name localhost; return 301 https://$host $request_uri ; location / { root html; index index.html index.htm; allow 192.168.10.100; allow 172.29.73.0/24; deny all; auth_basic "Nginx Status" auth_basic_user_file /usr/local /nginx/nginx.passwd } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location ~ .+\.(gif|jpg|jpeg|png|bmp|swf|txt|csv|doc|docx|xls|xlsx|ppt|pptx|flv)$ { root e:wwwroot; expires 30d; access_log off; } location ~ .+\.(js|css|html|xml)$ { expires 30d;} location /nginx-status{ stub_status on; allow 192.168.1.0/24; allow 127.0.0.1; deny all; } } upstream monitor_server { ip_hash; server 192.168.0.131:80 weight=9 max_fails=5 fail_timeout=600s; server 192.168.0.132:80 weight=1 max_fails=5 fail_timeout=600s; } server { listen 80; server_name blog.weiyigeek.top; location / { proxy_pass http://monitor_server; proxy_redirect off; proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; proxy_connect_timeout 60s; proxy_read_timeout 60s; proxy_send_timeout 30s; proxy_buffer_size 4k proxy_buffers 4 32k proxy_busy_buffers_size 64k proxy_max_temp_file_size 0 proxy_temp_file_write_size 64k client_max_body_size 100m; } location ~ .(jsp|jspx|do )?$ { proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; proxy_pass http://127.0.0.1:8080; } location ~ \.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ { expires 15d; } location ~ \.(js|css)$ { expires 1h; } } server { listen 80; listen [::]:80; server_name weiyigeek.top; return 301 https://$host $request_uri ; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name weiyigeek.top; add_header Strict-Transport-Security "max-age=31536000;includeSubDomains;preload" always; add_header X-XSS-Protection "1; mode=block" ; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options ALLOW-FROM music.163.com; ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/weiyigeek.top.key; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/ssl/ca.cer; ssl_dhparam /path/to/dhparam; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4; ; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:HIGH:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DES:!MD5:!RC4; ssl_prefer_server_ciphers on; resolver 223.6.6.6 8.8.8.8 192.168.12.254; } }
为了更好的指导部署与测试系统,在保证nginx网站服务器高性能的同时下,为了保证其安全稳定运行,我们需要对nginx服务进行调优与加固; 本次进行Nginx服务调优加固主要从以下几个部分,模块性能优化,系统内核优化,编译安装优化,性能参数优化,安全加固配置, 可以帮助安全开发运维者加速进行Nginx服务器相关优化。