1、Nginx基本安全优化
a、更改配置文件参数隐藏版本
编辑nginx.conf配置文件增加参数,实现隐藏Nginx版本号的方式如下。在nginx配置文件nginx.conf中的http标签段内加入 “server_tokens off;”参数,如下:
http{ …… server_tokens off; …… }
此参数放置在http标签内,作用是控制http response header内的web服务版本信息的显示,以及错误信息中web服务版本信息的显示。
server_tokens参数的官方说明如下:
syntax: server_tokens on | off ; #此行为参数语法,on为开启状态,off为关闭状态 default: server_tokens on; #此行意思是不配置该参数,软件默认情况的结果 context: http,server, location #此行为server_tokens参数可以放置的位置 参数作用:激活或禁止nginx的版本信息显示在报错信息和servser的响应首部位置中Enables or disables emitting of nginx version in error messages and in the "server" response header field
官方资料地址:http://nginx.org/en/docs/http/ngx_http_core_moudule.html
b、更改源码隐藏nginx软件名及版本号
第一里程碑:依次修改3个nginx源码文件
修改第一个文件为nginx-1.10.2/src/core/nginx.h,如下:
[[email protected] nginx-1.10.2]# sed -n ‘13,27p‘ src/core/nginx.h
#define NGINX_VERSION "1.10.2" #修改为想要显示的版本号,如1.6.2
#define NGINX_VER "nginx/" NGINX_VERSION #将nginx修改为想要修改的软件名称,如Apache
#ifdef NGX_BUILD
#define NGINX_VER_BUILD NGINX_VER " (" NGX_BUILD ")"
#else
#define NGINX_VER_BUILD NGINX_VER
#endif
#define NGINX_VAR "NGINX" #将nginx修改为想要修改的软件名称,如Apache
#define NGX_OLDPID_EXT ".oldbin"
#endif /* _NGINX_H_INCLUDED_ */
修改第二个文件是nginx-1.10.2/src/http/ngx_http_header_filter_module.c 的49行,需要修改的字符串如下:
[[email protected] nginx-1.10.2]# grep -n ‘Server: nginx‘ src/http/ngx_http_header_filter_module.c 49:static char ngx_http_server_string[] = "Server: nginx" CRLF; #把“Server: nginx”替换为“Server: Apache” 提示:sed替换命令sed "49 s#Server: nginx#Server: Apache#" src/http/ngx_http_header_filter_module.csed -i "49 s#nginx#Apache#" src/http/ngx_http_header_filter_module.c
修改第三个文件是 nginx-1.10.2/src/http/ngx_http_special_response.c,对外页面报错时,它会控制是否展示敏感信息。
[[email protected] nginx-1.10.2]# sed -n ‘21,30p‘ src/http/ngx_http_special_response.c static u_char ngx_http_error_full_tail[] = "<hr><center>" NGINX_VER "</center>" CRLF #此行需要修改,修改为"<hr><center>" NGINX_VER "(http://www.xxx.com)</center>" CRLF
"</body>" CRLF "</html>" CRLF ; static u_char ngx_http_error_tail[] = "<hr><center>nginx</center>" CRLF #此行需要修改,将对外展示的nginx改为Apache"</body>" CRLF
注:修改后编译安装软件,启动服务使其生效。
C、更改nginx服务的默认用户
为了让web服务更安全,要尽可能地改掉软件默认的所有配置,包括端口、用户等,通用其他软件服务。
nginx服务启动后,默认用户是nobody(编译安装时可以指定创建用户),查看默认配置文件,如下:
[[email protected] nginx-1.10.2]# grep "#user" conf/nginx.conf.default #user nobody;
为了防止黑客使用默认用户进行攻击,用户需要更改成特殊的用户,例如www或nginx等等,但用户必须存在,下面以www用户为例进行说明。
第一里程碑:创建用户
useradd -s /sbin/nologin -m www #无需有登录权限,只需在系统内容执行任务 id www #检查创建的用户
第二里程碑:配置nginx服务,让其使用创建的用户www用户(编译安装时已指定用户,无需做此操作)
将默认的#user nobody;改为以下内容: user www www注:如果注释或不设置上述参数,默认用户为nobody用户,不推荐使用nobody用户名。编译安装nginx软件时指定编译的用户和组,编译命令如:./configure --prefix=/usr/local/nginx-1.10.2 --user=www --group=www --with-http_stub_status_module --with-http_ssl_module
第三里程碑:检查更改用户的效果
重新加载配置后,检查nginx服务进行的对应用户,如下:
[[email protected] nginx-1.10.2]# ps -ef | grep nginx | grep -v grep
2、根据nginx.conf配置文件参数优化nginx服务性能
在高并发、高访问量的web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求。
a、优化nginx服务的worker进程个数
01、优化nginx进程对应nginx服务的配置参数如下:
#配置文件信息 [[email protected] nginx-1.10.2]# cat conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; …… } #需要修改的参数: worker_processes 1; #指定了nginx要开启的进程数,结尾的数字就是进程的个数 注:worker_processes参数调整的是nginx服务的worker进程数,nginx有master进程和worker进程之分,Master为管理员进程,真正接待“顾客”的是worker进程。
02、优化nginx进程个数的策略
work_processes参数大小的设置最好和网站的用户数量相关联。
搭建服务器时,worker进程数最开始的设置可以等于CPU的核数,且worker进程数要多一些,这样起始提供服务时就不会出现因为访问量快速增加而临时启动新进程提供服务的问题,缩短了系统的瞬时开销和提供服务的时间,提升了服务用户的速度。高流量高并发场合也可以考虑将进程数提高至CPU核数*2,具体情况要根据实际的业务来选择,因为这个参数除了要和CPU核数匹配外,也和硬盘存储的数据及系统的负载有关,设置为CPU的核数是一个好的起始配置。
03、查看web服务器CPU硬件资源信息
下面介绍查看linux服务器CPU总核数的方法。
通过/proc/cpuinfo可查看CPU个数及总核数。查看CPU总核数的示例如下:
[[email protected] ~]# grep processor /proc/cpuinfo |wc -l 8 #表示为1颗CPU八核
[[email protected] ~]# grep processor /proc/cpuinfo
查看CPU总颗数的示例如下:
[[email protected] ~]# grep ‘physical id‘ /proc/cpuinfo |sort|uniq |wc -l 1 #对physical id去重计数,表示1颗CPU
通过执行top命令,然后按数字1,即可显示所有CPU核数,如下:
[[email protected] ~]# top #按1显示多核CPUtop - 09:20:02 up 7:04, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 82 total, 1 running, 81 sleeping, 0 stopped, 0 zombie Cpu0 : 0.3%us, 1.0%sy, 0.0%ni, 98.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu1 : 0.1%us, 1.0%sy, 0.0%ni, 98.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu2 : 0.3%us, 1.0%sy, 0.0%ni, 98.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu3 : 0.2%us, 1.0%sy, 0.0%ni, 98.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu4 : 0.1%us, 1.0%sy, 0.0%ni, 98.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu5 : 0.1%us, 1.0%sy, 0.0%ni, 98.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu6 : 0.3%us, 1.0%sy, 0.0%ni, 98.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu7 : 0.2%us, 1.0%sy, 0.0%ni, 98.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 2493928k total, 485836k used, 2008092k free, 79828k buffers Swap: 1048572k total, 0k used, 1048572k free, 187784k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 7 root 20 0 0 0 0 S 0.3 0.0 0:26.20 events/0 1 root 20 0 19356 1528 1228 S 0.0 0.3 0:02.06 init 注:这是单CPU 八核的信息例如:CPU核数为8,就配置worker_processes 8
04、实操==》修改nginx配置
第一里程碑:检查nginx.conf配置文件里的worker_processes数来了解,命令如下:
[[email protected] conf]# grep worker_processes nginx.conf worker_processes 1;
第二里程碑:修改配置文件中参数
[[email protected] conf]# sed -i ‘s#worker_processes 1#worker_processes 8#g‘ nginx.conf [[email protected] conf]# grep worker_processes nginx.conf worker_processes 8;
第三里程碑:平滑启动nginx,使修改生效,如下:
[[email protected] conf]# /usr/local/nginx/sbin/nginx -t #检查配置文件是否有错,养成修改配置文件后检查的好习惯(修改配置文件需要先备份) nginx: the configuration file /usr/local/nginx-1.10.2//conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx-1.10.2//conf/nginx.conf test is successful [[email protected] conf]# /application/nginx/sbin/nginx -s reload #平滑重启
第四里程碑:检查修改后worker进程数量,命令如下:
[[email protected] conf]# ps -ef | grep nginx | grep -v grep
参考链接:http://nginx.org/en/docs/ngx_core_module.html
b、优化绑定不同的nginx进程到不同的CPU上
优化不同的nginx进程对应不同的CPU配置时,八核CPU服务器的参数配置参考如下:
[[email protected] conf]# cat nginx.conf worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 #此行为cpu亲和力参数,cpumask为cpu掩码 events { worker_connections 1024; } ……
worker_cpu_affinity的作用是绑定不同的worker进程数到一组CPU上。通过设置bitmask控制进行允许使用的CPU,默认worker进程不会绑定到任何CPU。
示例配置:
worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000 #绑定每个工作进程到一个单独的CPU,而 worker_processes 2; worker_cpu_affinity 0101 1010; #绑定第一个工作进程到CPU0/CPU2,第二个工作进程绑定到CPU1/CPU3。第二个例子适用于超线程。 #特殊值auto允许将工作进程自动绑定到可用的CPU: # worker_processes auto; # worker_cpu_affinity auto; 参考链接:http://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity
C、nginx事件处理模型优化
nginx的联机处理机制在不同的操作系统会采用不同的I/O模型,在linux下,nginx使用epoll的I/O多路复用模型,在freebsd中使用kequeue的I/O多路复用模型,在Solaris中使用/dev/poll方式的I/O多路复用模型,在windows中使用的是icop等等。
要根据系统类型选择不同的时间处理模型,可供使用的选择有“use[kqueue|rtsig|epoll|/dev/poll|select|poll];”,其中select和poll都是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在linux平台上,而kqueue用在BSD系统中。对于linux系统linux 2.6.x的内核,推荐选择epoll工作模式,这是高性能高并发的设置。
本环境使用centos 6.9,因此将nginx的事件模型调整为epoll模型。
具体配置参数如下:
events #events指令是设定nginx的工作模式及连接数上限 { use epoll; #use是一个事件模块指令,用来指定nginx的工作模式。 }
d、调整nginx单个进程允许的客户端最大连接数
控制连接数的参数为worker_connections,此值要根据具体服务器性能和程序的内存使用量来指定,配置如下:
events #events指令是设定nginx的工作模式及连接数上限 { worker_connections 2048; #最大客户端连接数由worker_processes和worker_connections决定,即Max_client=worker_processes*worker_connections。进程的最大连接数受linux系统进程的最大打开文件数限制,在执行操作系统命令 “ulimit -Hsh 65535”或配置相应文件后,worker_connections的设置才能生效 } 参考链接:http://nginx.org/en/docs/ngx_core_module.html
e、配置nginx worker进程最大打开文件数
参数配置如下:
worker_rlimit_nofile 65535;#最大打开文件数限制,执行操作系统命令 “ulimit -HSh ”的结果
f、优化服务器域名的散列表大小
在HTTP配置块中调整server_names_hash_max_size和server_names_hash_bucket_size的值。
server_names_hash_bucket_size的默认值可能是32或64,也可能是其他值,这取决于CPU的缓存行的长度。
g、开启高效文件传输模式
1、设置参数:sendfile on; 2、设置参数:tcp_nopush on; 参考链接:http://nginx.org/en/docs/http/ngx_core_module.html#sendfile http://nginx.org/en/docs/http/ngx_core_module.html
h、优化nginx连接参数,调整连接超时时间
nginx连接超时的参数设置: 1、设置参数:keepalive_timeout 60; 2、设置参数tcp_nodelay on; 3、设置参数:client_header_timeout 15; #用于设置读取客户端请求头数据的超时时间。此处的数值为15,其单位是秒,为经验参考值。 4、设置参数:client_body_timeout 15 #用于设置读取客户端请求主题的超时时间,默认值时60. 5、设置参数:send_timeout 25; #用于指定响应客户端的超时时间。这个超时仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx将会关闭连接。
i、上传文件大小的限制(动态应用)
在主配置文件里加入如下参数:
client_max_body_size 8m; #具体大小根据业务做调整
j、FastCGI相关参数调优(配合PHP引擎动态服务)
FastCGI Cache资料链接:http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache
worker_processes 4; pid conf/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main ‘$remote_addr - $remote_user [$time_local] "$request" ‘ ‘$status $body_bytes_sent "$http_referer" ‘ ‘"$http_user_agent" "$http_x_forwarded_for"‘; access_log logs/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; client_header_timeout 15; client_body_timeout 15; send_timeout 15; gzip on; server_tokens off; fastcgi_connect_timeout 240; fastcgi_send_timeout 240; fastcgi_read_timeout 240; fastcgi_buffer_size 64k; fastcgi_buffer 4 64k; fastcgi_temp_file_write_size 128k; fastcgi_temp_path /data/ngx_fcgi_tmp; fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_size=40g; server { listen 80; server_name localhost; access_log logs/host.access.log main; location / { root html; index index.php index.html index.htm; } } location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_conf; fastcgi_cache ngx_fcgi_cache; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_cache_key http://$host$request_uri; } ……
k、配置nginx gzip压缩实现性能优化
目的:节省带宽、提高访问速度。
参数介绍及配置:
gzip on #开启压缩功能 gzip_min_length 1k; #设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取。默认值是0,表示不管页面多大都进行压缩,建议设置成大于1k. gzip_buggers 4 16k; #压缩缓冲区大小。表示申请4个单位为16k的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。 gzip_http_version 1.1; #压缩版本(默认1.1,前端为squid2.5时使用1.0),用于设置识别HTTP协议版本,使用默认即可。 gzip_comp_level 2; #压缩比率。用来指定gzip压缩比,1压缩比最小,处理速度最快;9压缩比最大,传输速度快,单处理最慢,也比较消耗CPU资源。 gzip_types text/plain application/x-javascript text/css application/xml; #用来指定压缩的类型,“text/html”类型总是会被压缩,这个就是HTTP原理部分将的媒体类型。 gzip_vary on; #vary header支持。该选项可以让前端的缓存服务器缓存经过gzip压缩的页面。例如用squid缓存经过nginx压缩的数据。 #完整配置如下: gzip on; gzip_min_length 1k; gzip_buffers 4 32k; gzip_http_version 1.1; gzip_comp_level 9; gzip_types text/css text/xml /app/javascripts; gzip-vary on; 注:不同版本的nginx,gzip_types的配置可能会有不同。
L、配置nginx expires 缓存实现性能优化
目的:降低网站的带宽、节约成本、加快访问速度、减轻服务器压力。
a、根据扩展名进行判断
nginx expires配置详解(配置在nginx.conf中的server模块中): …… server{ …… location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 365d; 当用户访问网站URL结尾的文件扩展名为上述指定类型的图片时,设置缓存365天。 } location ~ .*\.(js | css)?$ { expires 30d; #当用户访问网站URL结尾的文件扩展名为js、css类型的元素时,设置缓存30天。 } ……
b、根据URI中的路径(目录)进行判断,添加expires功能范例
location ~ ^/ (images|javascript|js|css|flash|media|static)/ { expires 360d; }
c、单个文件添加expires功能范例
location ~(robots.txt){ expires 7d; #给robots.txt机器人文件设置过去时间,在设置的期间内不记录404错误日志。
break; }
Nginx expires功能缺点及解决方法
当网站被缓存的界面或数据更新了,此时用户端看到还是旧的已经缓存的内容,这样就会影响到用户体验,解决方法如下:
- 对于经常需要变动的图片等文件,可以缩短对象缓存时间。例:谷歌的首页图片经常根据不同的日期换成一些节日图,所以可以将这个图片设置为缓存期1天。
- 当网站改版或更新时,可以在服务器将缓存的对象改名(网站代码程序)
- 对于网站的图片、附件,一般不会被用户直接修改,用户层面上的修改图片,实际上个是重新传到服务器,虽然内容一样,但是会产生一个新的图片名称。
- 网站改版升级会修改js、css等样式文件,若改版时对这些样式文件中的元素改了名,会使得前端的CDN及用户端需要重新缓存内容。
企业网站缓存日期曾经的案例参考:
若企业的业务和网站访问量不同,那么网站的缓存时间设置也是不同,如下企业所用的缓存日期:
- 51CTO:1周
- 新浪:15天
- 京东:25年
- 淘宝:10年