nginx基本安全优化
1. 调整参数隐藏nginx软件版本号信息
软件的漏洞和版本有关,我们应尽量隐藏或消除web服务对访问用户显示各类敏感信息(例如web软件名称及版本号等信息),这样恶意的用户就很难猜到他攻击的服务器所用的是否有特定漏洞的软件,或者是否有对应漏洞的某一特定版本,从而加强web服务的安全性。
要了解服务器使用的软件版本号,对于linux客户端
[root@Poppy conf]# curl -i bbs.joker.com HTTP/1.1 200 OK Server: nginx/1.6.3 Date: Fri, 15 Jun 2018 02:18:23 GMT Content-Type: text/html Content-Length: 4 Last-Modified: Thu, 07 Jun 2018 10:06:23 GMT Connection: keep-alive ETag: "5b19039f-4" Accept-Ranges: bytes bbs 浏览器上访问如果出现404的时候,会显示软件和版本号。
我们来访问下百度看看是否可以隐藏版本
[root@Poppy conf]# curl -i baidu.com HTTP/1.1 200 OK Date: Fri, 15 Jun 2018 02:23:35 GMT Server: Apache 软件更改成了apache,还隐藏了版本号 Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT ETag: "51-47cf7e6ee8400" Accept-Ranges: bytes Content-Length: 81 Cache-Control: max-age=86400 Expires: Sat, 16 Jun 2018 02:23:35 GMT Connection: Keep-Alive Content-Type: text/html <html> <meta http-equiv="refresh" content="0;url=http://www.baidu.com/"> </html>
通过修改配置文件nginx.conf中的http标签段内加入“server_tokens off”;参数
[root@Poppy conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 访问日志,main就是读http里面的main日志变量 access_log logs/www_access.log main; server_tokens off; include extra/bbs.conf; }
再来访问看看
[root@Poppy conf]# curl -i bbs.joker.com HTTP/1.1 200 OK Server: nginx Date: Fri, 15 Jun 2018 02:27:21 GMT Content-Type: text/html Content-Length: 4 Last-Modified: Thu, 07 Jun 2018 10:06:23 GMT Connection: keep-alive ETag: "5b19039f-4" Accept-Ranges: bytes bbs
语法格式为
server_tokens off; off 为关闭 on为开启 (默认开启安)
存放的位置可以是http,server,location
2. 更改源码隐藏nginx软件名称及版本号
隐藏了nginx版本号后,更近一步,我们可以通过一些手段把web服务软件的名称也隐藏起来,或者更改为其他web服务软件名以迷惑黑客。由于商业及品牌的展示原因等,软件提供商不希望使用者把软件名字隐藏起来。因此,如果要修改软件名称就只能更改nginx源代码
我们不做修改
3. 更改nginx服务默认用户
为了让web服务更安全,要尽可能的改掉软件默认的所有配置,包括端口,用户等
nginx服务的默认用户是nobody,即使是注释或者不配置默认用户都是nobody
[root@Poppy conf]# grep "#user" nginx.conf.default #user nobody;
#1 为nginx服务建立新用户的操作过程如下
useradd www -s /sbin/nologin -M
不需要有系统登录权限,应当禁止其登录行为
#2 配置nginx服务,让其使用刚建立的nginx用户
第一种方法是直接修改配置文件,将默认的#user nobody改为 user nginx; 第二种方法是直接在编译nginx软件时指定编译的用户和组 ./configure --user=nginx --group=nginx 检查更改用户的效果 [root@Poppy conf]# ps -ef|grep nginx root 9032 1 0 Jun14 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx www 10609 9032 0 10:27 ? 00:00:00 nginx: worker process 可以看到worker process进程对应的用户都变成了nginx。上述2种方法都可以设置nginx的worker进程运行的用户,当然,nginx的主进程还是以root身份运行的。
根据参数优化nginx服务器性能
优化nginx服务的worker进程个数
在高并发,高访问量的web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求
这类似于开饭店,在营业前,需要事先招聘一定数量的服务员准备接待顾客,但这里就有个问题,如果饭店对客流没有正确评估,就会导致一些问题发生,例如;服务员人数招聘多了,但是客流很少,那么服务员就可能很闲,没事干,饭店的成本也就高了;如果客流很大,而服务员人数少了,可能就接待不过来顾客,导致顾客吃饭体验差。因此,饭店要根据客户的流量及并发量来调整接待的服务人员数量,然后根据监测顾客量变化及时调整到最佳的配置。
nginx服务就相当于饭店,网站用户就相当于顾客,nginx的进程就相当于服务员
1. 优化nginx进程对应的配置
优化nginx的进程反应nginx服务的配置参数如下
worker_processes 1;指定了nginx要开启的进程数,结尾的数字就是进程个数
调整的是nginx服务的worker进程数,nginx有master进程和worker进程之分,master是管理进程,worker是工作处理进程
2. 优化nginx进程个数的策略
如何设置worker_processes树木,官方建议我们起始为cpu的核数,这样起始提供服务时就不会出现因为访问量快速增加而临时启动新进程提供服务的问题,缩短了系统的瞬间开销和提供服务的时间,提升了服务用户的速度。高流量高并发场合也可以考虑将进程数提高至cpu核数具体情况根据实际业务来选择,因为这个参数除了要和cpu核数匹配外,也和硬盘存储的数据及系统的负载有关。
3. 查看web服务器cpu硬件资源信息
[root@Poppy conf]# grep -c processor /proc/cpuinfo 1 一颗cpu一核 [root@Poppy conf]# grep 'physical id' /proc/cpuinfo|sort|uniq|wc -l 1 一颗cpu
4. 实践修改nginx配置
服务器cpu颗数为1颗,核数为4核,则初始的配置可通过查看默认的nginx.conf里的work_process了解,命令如下
[root@Poppy conf]# grep worker_processes nginx.conf worker_processes 1;
我们修改将其修改为4,然后重启nginx
[root@Poppy conf]# grep worker_processes nginx.conf worker_processes 4;
我们通过ps -ef,来查看下nginx进程
[root@Poppy conf]# ps -ef|grep nginx root 9032 1 0 Jun14 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx www 10862 9032 0 14:02 ? 00:00:00 nginx: worker process www 10863 9032 0 14:02 ? 00:00:00 nginx: worker process www 10864 9032 0 14:02 ? 00:00:00 nginx: worker process www 10865 9032 0 14:02 ? 00:00:00 nginx: worker process
可知,worker的进程数为4个,ngxin master主进程不包含在这个参数内,nginx master的主进程为管理进程,负责调度和管理worker进程。
优化绑定不同的nginx进程到不同的cpu上
默认情况下,nginx的多个进程有可能跑在某一个cpu或cpu的某一核上,导致nginx进程使用硬件的资源不均,如何尽可能地分配不同的nginx进程给不同的cou处理,达到充分有效利用硬件的多cpu多核资源的目的
四核cpu服务器参数配置参考
worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000; worker_cpu_affinity就是配置nginx进程与cpu亲和力的参数,即把不同的进程分给不同的cpu处理,这里0001 0010 0100 1000是掩码,分别代表第1,2,3,4核cpu,由于worker_processes进程数位4,因此,上述配置会把每个进程分配一核cpu处理,默认情况下进程不会绑定人和cpu,参数位置为main段
八核cpu服务器参数配置参考
worker_cpu_affinity 0001 0010 0100 1000 0001 0010 0100 1000
worker_cpu_affinity 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008
其语法就是
worker_cpu_affinity cpumask; cpumask是掩吗
worker_cpu_affinity的作用是绑定不同的worker进程数到一组cpu上
压力测试 。webbench -c 2000 -t 180 http://www.joker.com/
nginx事件处理模式优化
nginx的链接处理机制在不同的操作系统会采用不同的i/o模型,在linux下,nginx使用epoll的i/o多路复用模型,具体配置如下
events{
events 指令是设定nginx的工作模式及连接数上限
user epoll;
use是一个事件模块指令,用来指定nginx的工作模式。
}
nginx的工作模式
nginx的工作模式有select,poll,kqueue,epoll,rtsig和/dev/poll。其中select,poll都是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用来linux平台上,而kqueue用来bsd系统中。对于linux系统linux 2.6+的内核,推荐选择epoll工作模式,这是高性能高并发的设置。
nginx官方文档建议,我们可以不指定事件处理模型,nginx会自动选择最佳的事件处理模型服务
调整nginx单个进程允许的客户端最大连接数
调整nginx单个进程允许的客户端最大连接数,这个控制连接数的参数为worker_connections
worker_connections的值要根据具体服务器性能和程序的内存使用量来执行(一个进程启动使用的内存根据程序确定),如下
events{ events指令是设定nginx的工作模式及连接数上限 worker_connections 20480; worker_connections也是个事件模块指令,用于定义nginx每个进程的最大连接数,默认是1024。最大客户端连接数由worker_processes和worker_connections决定,即max_client=worker_processes*worker_connections。进程的最大连接数接受linux系统接受linux系统进程的最大打开文件数限制,在执行操作系统命令“ulimit -Hsn 65535”或配置相应文件后,worker_connections的设置才能生效 } worker_connections用来设置一个worker process支持的最大并发连接数
配置nginx worker进程最大打开文件数
调整配置nginx worker进程最大打开文件数,这个控制连接数的参数为worker_rlimit_nofile。
worker_rlimit_nofile 65535;
最大打开文件数,可设置为系统优化后的ulimit -HSn的结果
优化服务器域名的散列表大小
先要将确切名字和通配符名字存储在散列表中,散列表和监听端口关联,每个端口最多关联到三张表;确切名字的散列表,以星号起始的通配符名字的散列表和以星号结束的通配符名字的散列表。散列表的尺寸在配置阶段进行了优化,可以以最小的cpu缓存命中失败来找名字。nginx首先会搜索确切名字的散列表,如果没有找到,则搜索以星号起始的通配符名字的散列表,如果还是没有找到,继续搜索以星号结束的通配符名字的散列表。
[root@Poppy extra]# cat bbs.conf server { listen 80; server_name bbs.joker.com *.joker.com; 很明显*.joker.com效率低 location / { root html/bbs; index index.html; } }
如果你要想定义大量的名字,或者定义非常长的名字,就需要在http配置块中调整server_names_hash_max_size和server_names_hash_bucket_size的值。server_names_hash_max_size的默认值可能是32或64,也可能是其他值,这取决于cpu的缓存行的长度。那么定义“wwwwwwwwwwwwwwwwwwwwww.joker.com”作为虚拟主机名就会失败,此时会显示下面的错误信息;
could not build the server_name_hash; you should increase server_names_hash_bucket_size:32
出了这种情况,就需要将server_names_hash_max_size扩大一倍。
http{ server_names_hash_max_size 64 ....... }
如果定义了大量名字,会得到如下另外一个错误消息;
could not build the server_name_hash; you should increase server_names_hash_max_size:512 # 默认512kb,一般查看系统给出确切的值,cpu l1的4倍到5倍 or server_names_hash_bucket_size; 32
我们应该修改server_names_hash_max_size的值,此值差不多等于名字列表的名字总量。
注意:后面不能带单位
开启高效文件传输模式
1. 设置参数sendfile on;
sendfile参数用于开启文件的高效传输模式,同时将tcp_nopush和tcp_nodelay俩个指令设置为on,可防止网络及磁盘i/o阻塞,提升nginx工作效率
在http ,server,location,if in location字段标签里面可以设置
http {
sendfile on; 默认是off
}
激活sendfile功能,sendfile()是作用于俩个文件描述符之间的数据拷贝函数,这个拷贝操作是在内核之中的,被称为“零拷贝”,sendfile()比read和write函数要高效很多,因为,read和write函数要把数据拷贝到应用层在进行操作。
2. 设置参数tcp_nopush
在http,server,location字段标签里面可以设置
http {
sendfile on;
tcp_nopush on; 默认是off
}
激活linux上传递tcp_cork socket选项,此选项仅仅当开启sendfile时才生效,激活这个,tcp_nopush参数可以允许把http response header和文件的开始部分放在一个文件里发布,其积极的作用是减少网络报文段的数量。