nginx深度优化

隐藏nginx软件名和版本号

1、调整参数隐藏Nginx版本号信息
 一般来说,软件的漏洞都和版本有关,因此我们应尽量隐藏或清除Web服务队访问的用户显示各类敏感信息(例如:Web软件名称及版本号等信息),这样恶意的用户就很难猜到他攻击的服务器所用的是否是特定漏洞的软件,或者是否有对应的漏洞存在。

vim /application/nginx/conf/nginx.conf
http{
    server_tokens off;
}
#我们在http标签端开启即可

 server_tokens 可以放在http、server、location的标签中

2、更改Nginx源码修改软件名

 隐藏了Nginx版本号后,更进一步,可以通过一些手段把web服务软件的名称也给因此,或者更改为其他Web服务软件名迷惑黑客。Nginx模块不支持更改软件名,所以我们需要更改Nginx源代码重新编译nginx才能解决。需要修改三个源码文件,如下:

 修改的第一个文件为nginx-1.6.3/src/core/nginx.h

cd /home/goser/tools/nginx-1.6.3/src/core/
vim nginx.h 
#define NGINX_VERSION      "1.2.1"
#修改为想要的版本号
#define NGINX_VER          "GOSER/" NGINX_VERSION
#将nginx修改想要修改的软件名称
#define NGINX_VAR          "GOSER"
#将nginx修改为想要修改的软件名称。

 修改第二个文件nginx-1.6.3/src/http/ngx_http_header_filter_module.c的第49行

vim src/http/ngx_http_header_filter_module.c 
staticchar ngx_http_server_string[]="Server: GOSER"    CRLF;
#修改本行,此处的文件是我们Curl 出来显示的名称

 修改第三个文件nginx-1.6.3/src/http/ngx_http_special_response.c,对外页面报错时,它会控制是否展示敏感信息。修改28~30行

 vim src/http/ngx_http_special_response.c 
 21static u_char ngx_http_error_full_tail[]=
 22"<hr><center>"GOSER"</center>" CRLF
 23"</body>" CRLF
 24"</html>" CRLF
 25;
 26 
 27 
 28static u_char ngx_http_error_tail[]=
 29"<hr><center>GOSER</center>" CRLF

 修改完成之后需要重新编译nginx

/application/nginx/sbin/nginx -V
nginx version: nginx/1.6.3
built by gcc 4.4.720120313(RedHat4.4.7-16)(GCC) 
TLS SNI support enabled
configure arguments:--prefix=/application/nginx-1.6.3/ --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
重新编译./configure --prefix=/application/nginx-1.6.3/ --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module
提示:需要停止原来的nginx,从新进行编译。如果不想在覆盖原来的编译参数可以选择指定新的目录。

 最后对修改好的软件名和版本号做测试,可以对server_tokens开启或关闭做测试看看设置是否生效

 温馨提示:

1.提示网站安全,要从最简单、最短板、最低点入手解决问题,门大开着,窗户安装再结实的护栏也没有意义。
2.向有经验的人及优秀的网站公司学习。
3.学习看官方文档,根据一手资料去分析
4.命令输出结果中含有需要过滤或者要保留的内容时,命令自身可能有参数直接实现。

 

 

 

 

更改Nginx服务的默认用户

 为了Web服务更安全,我们要尽可能地改掉软件默认的所有配置,包括端口、用户等。
查看nginx服务对应的默认用户,查看默认配置文件
grep "#user"/application/nginx/conf/nginx.conf.default 
#user  nobody;

 更改nginx的默认用户可以直接在编译前在配置文件中指定用户名,或者在编译的时候直接指定一个用户名来作为nginx的默认用户,我们常用的是在编译的时候指定用户名。

 第一种 如果是在编译前对配置文件做修改,来指定用户名方式为:

 创建一个nginx用户,同时直接更改配置文件参数,将默认的#user nobody修改直接更改配置文件参数,将默认的#user nobody修改如下内容为user nginx  nginx

 第二种 为直接在编译nginx软件时指定编译的用户和组

./configure --prefix=/application/nginx-1.6.3/ --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_modul

优化Nginx服务的worker进程个数

 在高并发、访问量大的Web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求.

 查看Linux服务一个CPU总核数的方法

grep "processor"/proc/cpuinfo |wc -l

#或者使用下面命令查看
grep -c processor /proc/cpuinfo 

 查看cpu总数是多少

grep "pysical id"/proc/cpuinfo |sort|uniq|wc -l

 对查看CPU的总数还可以通过top命令并按1显示

 有关worker_process参数的官方说明如下:

syntax:    worker_processes number:#此行为参数语法,number为数量
default:    worker_processes 1    #此行意思是不配置该参数,软件默认情况为1
context:    main               #此行为worker_processes参数可以放置的位置
worker_processes为定义worker进程数的数量,建议设置为CPU的核数或者cpu核数*2的进程数,具体情况要根据实际业务来进行选择。除了要和CPU核数的匹配外,和硬盘存储的数据以及系统的负载也会有关,设置为CPU的个数或核数是一个好的起始配置

 

优化绑定不同的Nginx进程到不同CPU上

  绑定不同的NGINX进程到不同CPU上,也就是做CPU的亲和力,即对worker_cpu_affinity的配置

  默认情况Nginx的多个进程有可能跑在某一个或某一核的CPU上,导致Nginx进程使用硬件的资源不均。可以分配不同的Nginx进程给不同的CPU处理,达到充分有效利用硬件的多CPU多核资源的目的。

worker_processes  4;
worker_cpu_affinity 0001001001001000;
#worker_cpu_affinity就是配置nginx进程CPU亲和力的参数,即把不同的进程分给不同的CPU处理。这里0001 0010 0100 1000是掩码,分别代表1、2、3、4核cpu核心,由于worker_processes进程数为4,因此上述配置会把每个进程分配一核CPU处理,默认情况下进程不会绑定任何CPU,参数位置为main段

 

 通过观察,我们发现配置后不同CPU的使用率相对平均,和测试前变化不大。可能是Nginx软件本身在逐渐变化,使其使用多核CPU时更为均衡。另外(taskset – retrieve or set a process’s CPU affinity)命令本身也有分配CPU的功能,(例如:taskset -c 1,2,3 /etc/init.d/mysqld start)。

 Nginx事件处理模型优化

  Nginx的连接处理机制在于不同的操作系统会采用不同的I/O模型,在Linux下,Nginx使用epoll的I/O多路复用模型,在Freebsd中使用kqueue的I/O多路复用模型,在Solaris中使用/dev/poll方式的I/O多路复用模型,在Windows使用的是icop,等待。
    要根据系统类型选择不同的事件处理模型,可供使用的选择的有“use [kqueue|rtsig|epoll|/dev/poll|select|pokk]”。
events {
#events指令是设定Nginx的工作模式及连接数上限
use epoll
}
#use是个事件模块指定,用来指定Nginx的工作模式,Nginx支持的工作模式有select、poll、kqueue、epoll、rtsig和/dev/poll。其中select和poll都是标准的工作迷失,kqueue和epoll是高效工作模式,不同的是epoll用在Linux平台,而kqueue用在BSD系统中。对于Linux 2.6内核推荐使用epoll工作模式

 根据Nginx的官方文档建议,也可以不指定事件处理模型,Nginx会自动选择最佳的事件处理模型服务。

调整Nginx单个进程允许的客户端最大连接数

 worker_connections的值要根据具体服务器性能和程序的内存使用量来指定(一个进程启动使用的内存根据程序确定)

events {
    worker_connections  20480;
}
#worker_connections 也是个事件模块指令,用于定义Nginx每个进程的最大连接数,默认是1024.最大客户端连接数由worker_processes和worker_connections决定.
 并发=worker_process * worker_connections 

 参考资料:http:nginx.org/en/docs/ngx_core_module.html

配置Nginx worker进程最大打开文件数

 例如设置worker_rlimit_nofile大小为65535

worker_rlimit_nofile   65535
 worker_rlimit_nofile number的官方说明如下:
 参数语法:worker_rlimit_nofile number;
 默认配置:无
 放置位置:主标签段
 说明:此参数的作用是改变worker processes能打开的最大文件数。

开启高效文件传输模式

 sendfile参数用于开启文件的高效传输模式,同时将tcp_nopush和tcp_nodelay两个指定设为on,可防止网络及磁盘I/O阻塞,提升Nginx工作效率

 sendfile官方说明:

syntax:    sendfile on|off  #参数语法
default:    sendfile off    #参数默认大小
context:    http,server,location,ifin location #可放置的标签段
 参数作用:激活或者禁用sendfile()功能。sendfile()是作用于两个文件描述符之间的数据拷贝函数,这个拷贝操作是在内核之中,被称为“零拷贝”,sendfile()和read和write函数要高效很多,因为read和wrtie函数要把数据拷贝到应用层再进行操作。相关控制参数还有sendfile_max_chunk。
 http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile
 
 关于参数:tcp_nopush on
Syntax: tcp_nopush on | off;  #参数语法
Default: tcp_nopush off;      #参数默认大小
Context: http, server, location  #可以放置标签段
 参数作用:激活或禁用Linux上的TCP_CORK socker选项,此选项仅仅开启sendfile时才生效,激活这个tcp_nopush参数可以运行把http response header和文件的开始放在一个文件里发布,减少网络报文段的数量。
 
 关于参数:tcp_nodelay on
 用于激活tcp_nodelay功能,提高I/O性能
Syntax: tcp_nodelay on | off;
Default: tcp_nodelay on;
Context: http, server, location
 参数作用:默认情况下数据发送时,内核并不会马上发送,可能会等待更多的字节组成一个数据包,这样可以提高I/O性能,但是,在每次只发送很少字节的业务场景,使用tcp_nodelay功能,等待时间会比较长。
   参数生产条件:激活或禁用tcp_nodelay选项,当一个连接进入到keep-alive状态时生效

优化Nginx连接参数调整连接超时时间

1、什么是连接超时?
    这里的服务员相当于Nginx服务建立的连接,当服务器建立的连接没有接收到处理请求时,可在指定的事件内就让它超时自动退出。还有当Nginx和fastcgi服务建立连接请求PHP时,如果因为一些原因(负载高、停止响应)fastcgi服务无法给Nginx返回数据,此时可以通过配置Nginx服务参数使其不会四等。例如:可设置如果Fastcgi 10秒内不能返回数据,那么Nginx就终端本次请求。
 
2、连接超时的作用
1)设置将无用的连接尽快超时,可以保护服务器的系统资源(CPU、内存、磁盘)
2)当连接很多时,及时断掉那些已经建立好的但又长时间不做事的连接,以减少其占用的服务器资源,因为服务器维护连接也是消耗资源的。
3)有时黑客或而恶意用户攻击网站,就会不断和服务器建立多个连接,消耗连接数,但是什么也不操作。只是持续建立连接,这就会大量的消耗服务器的资源,此时就应该及时断掉这些恶意占用资源的连接。
4)LNMP环境中,如果用户请求了动态服务,则Nginx就会建立连接请求fastcgi服务以及MySQL服务,此时这个Nginx连接就要设定一个超时时间,在用户容忍的时间内返回数据,或者再多等一会后端服务返回数据,具体策略要看业务。
 
3.连接超时带来的问题以及不同程序连接设定知识
    服务器建立新连接也是要消耗资源的,因此,超时设置的太短而并发很大,就会导致服务器瞬间无法响应用户的请求,导致体验下降。
    企业生产有些PHP程序站点就会系统设置短连接,因为PHP程序建立连接消耗的资源和时间相对要少些。而对于java程序站点一般建议设置长连接,因为java程序建立消耗的资源和时间更多。
 
4.Nginx连接超时的参数设置
 设置参数:keeplived_timeout 60;
 用于设置客户端连接保持会话的超时时间为60秒。超过这个时间,服务器会关闭该连接,此数值为参考值。
Syntax: keepalive_timeout timeout [header_timeout];#参数语法
Default: keepalive_timeout 75s;#参数默认大小
Context: http, server, location #可以放置的标签段

 参数作用:keep-alive可以使客户端到服务端已经建立的连接一直工作不退出,当服务器有持续请求时,keep-alive会使用正在建立的连接提供服务,从而避免服务器重新建立新连接处理请求。

 

 设置参数:client_header_timeout 15

 用于设置读取客户端请求头数据的超时时间,此处的数值15单位是秒。

Syntax: client_header_timeout time;
Default: client_header_timeout 60s;
Context: http, server

 参数作用:设置读取客户端请求头数据的超时时间。如果超过这个时间,客户端还没有发送完整的header数据,服务端将数据返回“Request time out (408)”错误

 

 设置参数:client_body_timeout 15

用于设置读取客户端请求主体的超时时间,默认值是60
Syntax: client_body_timeout time;
Default: client_body_timeout 60s;
Context: http, server, location
 参数作用:设置读取客户端请求主体的超时时间。这个超时仅仅为两次成功的读取操作之间的一个超时,非请求整个主体数据的超时时间,如果在这个超时时间内,客户端没有发送任何数据,Nginx将返回“Request time out(408)”错误,默认值是60.
 
 设置参数:send_timeout 25
 用户指定响应客户端的超时时间。这个超时时间仅限于两个链接活动之间的事件,如果超过这个时间,客户端没有任何活动,Nginx将会关闭连接,默认值为60s,可以改为参考值25s
Syntax: send_timeout time;
Default: send_timeout 60s;
Context: http, server, location 
 参数作用:设置服务器端传送http响应信息到客户端的超时时间,这个超时时间仅仅为两次成功握手后的一个超时,非请求整个响应数据的超时时间,如在这个超时时间内,客户端没有收到任何数据,连接将被关闭。
 
 最后将上面的超时配置如下:
一般放在http标签即可
http {
sendfile        on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
server_names_hash_bucket_size 128;
server_names_hash_max_size 512;
keepalive_timeout  65;
client_header_timeout 15s;
client_body_timeout 15s;
send_timeout 60s;
}

优化服务器域名的bash表大小

 哈希表和监听端口关联,每个端口都是最多关联到三张表:确切名字的哈希表,以星号起始的通配符名字的哈希表和以星号结束的统配符名字的哈希表。哈希表的尺寸在配置阶段进行了优化,可以以最小的CPU缓存命中率失败来找到名字。Nginx首先会搜索确切名字的哈希表,如果没有找到,则搜索以星号起始的通配符名称的哈希表,如果还是没有找到,继续搜索以星号结束的通配符名字的哈希表。
   注意.nginx.org存储在通配符名字的哈希表中,而不在明确名字的哈希表中,由于正则表达式是一个个串行测试的,因此该方式也是最慢的,并且不可扩展。

   举个例子,如果Nginx.org和www.nginx.org来访问服务器最频繁,那么明确的定义出来更为有效

 server {
        listen       80;
        server_name  nginx.org  www.nginx.org *.nginx.org
        location /{
            root   html/www;
            index  index.php index.html index.htm;
        }

 server_names_hash_bucket_size size的值,具体信息如下

server_names_hash_bucket_size size 512;

 #默认是512KB 一般要看系统给出确切的值。这里一般是cpu L1的4-5倍

 官方说明:

Syntax: server_names_hash_bucket_size size;
Default: server_names_hash_bucket_size 32|64|128;
Context: http

 参数作用:设置存放域名(server names)的最大哈希表大小。

上传文件大小(http Request body size)的限制(动态应用)

 设置上传文件大小需要在nginx的主配置文件加入如下参数 

client_max_body_size 8m;

 具体大小根据公司的业务调整,如果不清楚设置为8m即可

Syntax: client_max_body_size size;
Default: client_max_body_size 1m;  #默认值是1m
Context: http, server, location

 参数作用:设置最大的允许客户端请求主体大小,在请求头域有“Content-Length”,如果超过了此配置值,客户端会收到413错误,意思是请求的条目过大,有可能浏览器不能正确的显示这个错误,设置为0表示禁止检查客户端请求主体大小,此参数对服务端的安全有一定的作用。

 http://nginx.org/en/docs/http/ngx_http_core_module.html

fastcgi相关参数调优(配合PHP引擎动态服务)

 PHP 优化设置:
 在http{}里面
fastcgi_connect_timeout 240;
fastcgi_send_timeout 240;
fastcgi_read_timeout 240;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
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;

 PHP缓存 可以配置在server标签和http标签

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;

 

 nginx做反向代理优化

 nginx作为反向代理的话,有些参数是需要优化的,优化配置如下:

server
     {
            listen             80;
            server_name    bbs.linuxtone.conf;
            index index.html index.htm;
            root    /date/www;

         location / {
             root    /date/wwwroot/linuxtone/;
             proxy_redirect off ;
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header REMOTE-HOST $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             client_max_body_size 50m;
             client_body_buffer_size 256k;
             proxy_connect_timeout 30;
             proxy_send_timeout 30;
             proxy_read_timeout 60;
             proxy_buffer_size 256k;
             proxy_buffers 4 256k;
             proxy_busy_buffers_size 256k;
             proxy_temp_file_write_size 256k;
             proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
             proxy_max_temp_file_size 128m;
             proxy_pass    http://bbs.linuxtone.com;
            }
}

配置Nginx gzip 压缩实现性能优化

1.Nginx gzip压缩功能介绍   

    Nginx gzuo压缩模块提供了压缩文件内容的功能,用户请求的内容在发送出用客户端之前,Nginx服务器会根据一些具体的策略实施压缩,以节约网站出口带宽,同时加快了数据传输效率,提升了用户访问体验。

2.Nginx gzip 压缩的优点

1.提升网站用户体验:由于发给用户的内容小了,所以用户访问单位大小的页面就快了,用户体验提升了,网站口碑就好了。
2.节约网站带宽成本,由于数据是压缩传输的,因此,此举节省了网站的带宽流量成本,不过压缩会稍微消耗一些CPU资源,这个一般可以忽略。此功能既能让用户体验增强,公司也少花钱。对于几乎所有的Web服务来说,这是一个非常重要的功能,Apache服务也由此功能。

3.需要和不需要压缩的对象

1、纯文本内容压缩比很高,因此纯文本内容是最好压缩,例如:html、js、css、xml、shtml等格式的文件
2、被压缩的纯文本文件必须要大于1KB,由于压缩算法的特殊原因,极小的文件压缩可能反而变大。
3、图片、视频(流媒体)等文件尽量不要压缩,因为这些文件大多数都是经历压缩的,如果再压缩很坑不会减小或减少很少,或者可能增加。而在压缩时还会消耗大量的CPU、内存资源
4、参数介绍及配置说明
    此压缩功能很类似早起的Apache服务的mod_defalate压缩功能,Nginx的gzip压缩功能依赖于ngx_http_gzip_module模块,默认已安装。
 
在nginx的配置文件中的http标签下添加:
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 application/javascript;
gzip_vary on;

设置完成之后重启Nginx服务器,在火狐浏览器中安装插件Firebug和YSlow 进行查看页面压缩率 

 

配置Nginx expires 缓存实现性能优化

1.Nginx expires 功能介绍
    简单地说,Nginx expires的功能就是为用户访问的网站内容设定一个国企时间,当用户第一次访问到这些内容时,会把这样内容存储在用户浏览器本地,这样用户第二次及此后继续访问网站,浏览器会检查加载缓存在用户浏览器本地的内容,就不会去服务器下载了。直到缓存的内容过期或被清除为止。
    深入理解,expires的功能就是允许通过Nginx 配置文件控制HTTP的“Expires”和“Cache-Contorl”响应头部内容,告诉客户端刘琦是否缓存和缓存多久以内访问的内容。这个expires模块控制Nginx 服务器应答时Expires头内容和Cache-Control头的max-age指定。
    这些HTTP头向客户端表名了内容的有效性和持久性。如果客户端本地有内容缓存,则内容就可以从缓存(除非已经过期)而不是从服务器读取,然后客户端会检查缓存中的副本。
 
2.Nginx expires作用介绍
    在网站的开发和运营中,对于图片、视频、css、js等网站元素的更改机会较少,特别是图片,这时可以将图片设置在客户端浏览器本地缓存365天或3650天,而降css、js、html等代码缓存10~30天,这样用户第一次打开页面后,会在本地的浏览器按照过期日期缓存响应的内容,下次用户再打开类似页面,重复的元素就无需下载了,从而加快了用户访问速度,由于用户的访问请求和数据减少了,因此节省了服务器端大量的带宽。此功能和apache的expire相似。
 
3.Nginx expires 功能优点
1.Expires可以降低网站的带宽,节约成本。
2.加快用户访问网站的速度,提升了用户访问体验。
3.服务器访问量降低了,服务器压力就减轻了,服务器成本也会降低,甚至可以解决人力成本。
    对于几乎所有Web来说,这是非常重要的功能之一,Apache服务也由此功能。
4.配置expires参数示例
 根据文件扩展名进行判断,添加expires功能
location ~ .*\.(gif|jpg|png|bmp|swf)$
{
expires	3650d;
}
location ~ .*\.(js|css)$
{
expires	30d;
}

 该示例表示当前用户访问网站URL结尾的文件扩展名为上述指定的各种类型的图片时,设置缓存3650天,访问的是js、css代码时本地缓存1一个月

 配置可以放在server标签,也可以放在http标签下配置

 
 也可以根据URI中的路径(目录)进行判断,添加expires功能
location ~^/(images|javascript|js|css|flash|media|static)/{
  expires 360d;
}

 意思是当用户访问URI中包含上述路径(例:images、js、css,这些在服务端是程序目录)时,把访问的内容设置缓存360天,即1年。如果要想缓存30天,设置30d即可

5.Nginx expires功能缺点及解决方法

    当网站被缓存的页面或数据更新了,此时用户看到的可能还是旧的已经缓存的内容,这样会影响用户体验。
    对经常需要变动的图片等文件,可以缩短对象缓存时间,例如:谷歌和百度的首页图片经常根据不同的日期换成一些节日的图,所以这里可以将图片设置为缓存期为1天。
    当网站改版或更新内容时,可以在服务器将缓存的对象改名(网站代码程序)。
1. 对于网站的图片、软件,一般不会被用户直接修改,用户层面上的修改图片,实际上是重新传到服务器,虽然内容一样但是是一个新的图片名了
2.网站改版升级会修改JS、CSS元素,若改版的时候对这些元素该了名,会使得前端的CDN以及用户需要重新缓存内容。

6.企业网站缓存日期曾经的案例参考

    若企业的业务和访问量不同,那么网站的缓存期时间设置也是不同的,比如:
  a、51CTO:1周
  b、sina:15天
  c、京东:25年
  d、淘宝:10年

7.企业网站有可能不希望被缓存的内容

1.广告图片,用于广告服务,都缓存了就不好控制展示了。
2.网站流量统计工具(js代码)都缓存了流量统计就不准了
3.更新很频繁的文件(google的logo),如果按天,缓存效果还是显著的。

Nginx日志相关优化

 1、Nginx目前没有类似Apache的通过cronlog或者rotatelog对日志分割处理的能力,但是,运维人员可以通过利用脚本开发、Nginx的信号控制功能或reload重新加载,来实现日志自动切割,轮询。然后在定时任务中将这个切割nginx的日志脚本添加进去。

 2、不记录不需要的访问日志,比如访问图片、JS、CSS文件的记录就不需要记录到日志了,因为 对于负载均衡器健康检查节点或某些特定文件(比如图片、js、css)的日志,一般不需要记录下来,因为在统计PV时是按照页面计算的。而且日志写入频繁会大量消耗磁盘I/O,降低服务的性能。

location ~.*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)?$ {
        access_log off; 
}

 3、访问日志的权限设置

  不需要在日志目录上给nginx用户读或写的许可,因为让nginx的用户查看日志存在很大隐患。加入日志目录为/app/logs,则授权方法为:

chown -R root.root /app/logs/
chmod -R 700/app/logs

Nginx站点目录及文件URL访问控制

 Web2.0时代,绝大多数网站都是以用户为中心,例如:BBS、blog、sns产品,这几个产品共同特点就是不但允许用户发布内容到服务器,还允许用户发图片甚至附件到服务器,由于为用户打开了上传的功能,因为给服务器带来了很大的安全风险。
 下面将利用Nginx配置禁止访问上传资源目录下的PHP、shell、perl、Python程序文件,这样用户即使上传了木马文件也没法去执行,从而加强了网站的安全。 

 配置nginx限制指定目录下的指定程序被解析,放在fast_pass的location前面,这样可有效的限制指定的php等动态程序的解析。

location ~ ^/images/.*\.(php|php5|.sh|.pl|.py)$
{

deny all;
}
location ~ ^/static/.*\.(php|php5|.sh|.pl|.py)$
{

deny all;
}
location ~ ^/data/(attachment|avatar)/.*\.(php|php5)$
{

deny all;
}

 

 对于限制目录或URL访问,有的资源只能对内部人员开放,对外部人员禁止、

 案例环境:phpmyadmin 数据库的Web客户端,内部开发人员使用
 禁止某目录让外界访问,但允许某IP访问该目录,且支持PHP解析
location ~ ^/docker/ { 
allow 202.58.209.56; 
deny all;
}

 企业问题案例:Nginx做反向代理的时候可以限制客户端IP吗?
 解答:可以,具体方法如下。

if ( $remote_addr = 10.0.0.143 ) {
    return 403;
}
if ( $remote_addr = 218.247.17.130 ) {
     set $allow_access_root 'true';
}

配置Nginx禁止非法域名解析访问企业网站

 nginx如何防止用户ip访问网站(恶意域名解析,也相当于是直接ip访问企业网站)

  方法1:让使用ip访问的网站的,或者访问经恶意解析域名,收到501错误

    但是直接报501错误,从用户体验上不是很好

#放在第一个虚拟主机前面
server{
listen 80 default_server;
server_name _;
return 501;
}

  方法2:发现某域名恶意解析到公司的服务器IP,在server标签里添加一下代码即可,若有多个server要多出添加

if ($host !~ ^www/.goser/.com$){
rewrite ^(.*) http://www.goser.com$1 permanent;
}

Nginx图片及目录防盗链解决方案

1.什么是资源盗链

    简单的说,就是某些不发的网站未经许可,通过在其自身网站程序里非法调用其他网站的资源吗,然后在自己的网站上显示。达到补充自身网站的效果,这一举动不但浪费了调用网站的流量,还造成服务器的压力,甚至宕机。

2.常见防盗链 根据http referer 实现防盗链

 在HTTP协议中,有一个表头字段叫referer,使用URL格式来表示哪里的链接用了当前网页的资源。通过referer可以检测目标访问的来源网页,如果是资源文件,可以跟踪到显示它的网页地址,一旦检测出来不是本站,马上进行阻止或返回指定的页面。

 HTTP Referer是header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理,Apache、Nginx、Lighttpd三者都支持根据http referer实现防盗链referer是目前网站图片、附件、html最常用的盗链手段。

3、根据cookie防盗链

    对于一些特殊的业务数据,例如流媒体应用以及通过Active X显示的内容(例如,Flash、Windows Media视频、流媒体的RTSP协议等)因为他们不向服务器提供Referer Header,所以若也采用上述的Referer的防盗链手段就达不到想要的结果。
    对于视频这种占用流量较大的业务根据实现防盗链是比较困难的,此时可以采用Cookie技术,来解决对Flash、Windows Media视频等防盗链问题。
    例如:Active X插件不传递Referer,但会传递Cookie。可以在显示Active X的页面的<head> </head>标签内嵌入一段代码,可以用JavaScript 代码来设置一段“Cookie;Cache=av”;

4.通过加密变换访问路径实现防盗链

    此方法比较适合视频以及下载类业务的网站。例如:Lighttpd 有类似的插件mod_secdownload来实现此功能,现在服务器配置此模块,设置一个固定用于加密的字符串,比如abcdocker,然后设置一个url前缀,比如/abc/,再设置一个过期时间,比如1小时,然后写一段PHP代码,例如加密字符串和系统时间等通过md5算法生产一个加密字符串,最终获取到的文件的URL连接种会带由一个时间戳和一个加密字符的md5数值,在访问时系统会对这两个数据进行验证。如果时间不在预期的时间段内(如1小时)则失效;如果时间戳符合条件,但是加密的字符串不符合条件也失效,从而达到防盗链的效果。

防盗链的优化配置示例如下:

location ~* \.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
valid_referers none blocked *.goser.com goser.com;
if($invalid_referer) {
rewrite ^/ http://www.goser.com/img/nolink.jpg;
}
}
#当然放盗链也可以对某个目录设置

访问nginx web页面不存在时优雅显示 

 在网站的运行过程中,可能由于页面不存在或者系统过载等原因,导致网站无法正常响应用于的请求,此时Web服务默认会返回系统默认的错误码,或者很不友好的页面。影响用户体验

 例如:

server {
        listen       80;
        server_name  www.goser.com;
        location /{
            root   html/www;
            index  index.php index.html index.htm;
            error_page 404           /404.html
        }
}

 当然如果客户端访问的页面不存在 可以直接对访问的错误码 用首页来显示
  比如 error_page 404 http://www.goser.com;
 还可以对多个错误码用一个页面来显示:比如天猫网站设置:

error_page   500 501 502 503 504 http://err.tmall.com/error2.html;
error_page 400 403 404 405 408 410 411 412 413 414 415 http://err.tmall.com/error1.html;

Nginx防爬虫优化

 我们可以根据客户端的user-agents信息,轻松地阻止爬虫取我们的网站防爬虫,例如:

 ## Block download agents ##
     if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
            return 403;}

 添加内容防止N多爬虫代理访问网站示例

if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot") { 
     return 403; 
}

利用Nginx限制HTTP的请求方法

 HTTP最常用的方法为GET/POST,我们可以通过Nginx限制http请求的方法来达到提升服务器安全的目的,例如,让HTTP只能使用GET、HEAD和POST方法配置如下:

#Only allow these request methods
     if ($request_method !~ ^(GET|HEAD|POST)$ ) {
         return 501;
     }

 设置对应的用户相关权限,这样一旦程序有漏洞,木马就有可能被上传到服务器挂载的对应存储服务器的目录里,虽然我们也做了禁止PHP、SH、PL、PY等扩展名的解析限制,但是还是会遗漏一些我们想不到的可执行文件。对于这种情况,该怎么办捏?事实上,还可以通过限制上传服务器的web服务(可以具体到文件)使用GET方法,来达到防治用户通过上传服务器访问存储内容,让访问存储渠道只能从静态或图片服务器入口进入。例如,在上传服务器上限制HTTP的GET方法的配置如下:

 ## Only allow GET request methods ##
     if ($request_method ~* ^(GET)$ ) {
         return 501;
     }

 对于nginx连接php要用到的变量有:

cd  /application/nginx/conf/
cat  fastcgi_params
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

使用普通用户启动Nginx(监牢模式)

1.为什么要让Nginx服务使用普通用户
    默认情况下,Nginx的Master进程使用的是root用户,Worker进程使用的是Nginx指定的普通用户,使用root用户跑Nginx的Master进程由两个最大的问题:
   (1)、管理权限必须是root,这就使得最小化分配权限原则遇到难题
   (2)、使用root跑Nginx服务,一旦网站出现漏洞,用户就很容易获得服务器root权限
2.给Nginx服务降权解决方案
   (1)给Nginx服务降权,用inca用户跑Nginx服务,给开发及运维设置普通账号,只要和inca同组即可管理Nginx,该方案解决了Nginx管理问题,防止root分配权限过大。
   (2)开发人员使用普通账户即可管理Nginx服务以及站点下的程序和日志
   (3)采取项目负责制,即谁负载项目维护处了问题就是谁负责。
3.监控模式配置如下:
useradd inca
su - inca
mkdir conf logs www
cp /application/nginx/conf/mime.types ~/conf/
echo inca >www/index.html

vim conf/nginx.conf 
worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 65535;
error_log  /home/inca/logs/error.log;
user inca inca;
pid        /home/inca/logs/nginx.pid;
events {
    use epoll;
    worker_connections  10240;
}
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"';
    #web.fei fa daolian..............
    server {
        listen       8080;
        server_name  www.goser.com;
        root   /home/inca/www;
        location / {
            index  index.php index.html index.htm;
                }
         access_log  /home/inca/logs/web_blog_access.log  main;
           }
}

 用普通用户inca启动nginx的话,首先要关闭root开启的nginx,步骤如下:

/application/nginx/sbin/nginx -s stop
su - inca
/application/nginx/sbin/nginx -c /home/inca/conf/nginx.conf &>/dev/null

lsof -i:80
[1]+  Exit1                  /application/nginx/sbin/nginx -c /home/inca/conf/nginx.conf &>/dev/null

 这种方式启动nginx类似于mysql多实例的配置

本解决方案的优点如下:
 (1)给Nginx服务降权,让网站更安全
   (2).按用户设置站点权限,使站点更安全(无需虚拟化隔离)
   (3)开发不需要用root即可完整管理服务及站点
   (4)可实现对责任划分,网络问题属于运维的责任,打开不就是开发责任或共同承担

控制Nginx并发连接数

  nginx_http_limit_conn_module这个模块用于限制每个定义的key值的连接数,特别是单IP的连接数。
    不是所有的连接数都会被计数。一个符合要求的连接是整个请求头已经被读取的连接。
 控制Nginx并发连接数量参数的说明如下:
limit_conn_zone参数:
语法:limit_conn_zone key zone=name:size;
上下文:http
用于设置共享内存区域,key可以是字符串,nginx自有变量或前两个组合,如$binary_remote_addr、$server_name。name为内存区域的名称,size为内存区域的大小。
limit_conn参数:
语法:limit_conn zone number;
上下文:http、server、location

 对nginx的配置文件配置如下:

cat /application/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    server {
        listen       80;
        server_name   www.goser.com;
        location / {
            root   html;
            index  index.html index.htm;
            limit_conn addr 1; #<==限制单IP的并发连接为1
        }
    }
}

 还可以设置某个目录单IP并发连接数

         location /download/ {
            limit_conn addr 1;
        }

 在客户端使用Apache的ab测试工具进行测试

 执行ab -c 1 -n 10 http://10.0.0.3进行测试

 注意:-c并发数、-n请求总数,10.0.0.3nginx的IP地址

当然也可以限制虚拟主机的总连接数

不仅可以限制单IP的并发连接数,还可以限制虚拟主机的总连接数,可以同时使用
nginx配置文件nginx.conf的配置如下:

http{
limit_conn_zone $server_name zone=perserver:10m;
server{
limit_conn perserver 2;#设置此虚拟主机的总连接数为2
}

}

控制客户端请求Nginx的速率

 ngx_http_limit_req_module模块用于限制每个IP访问定义key的请求速率。
 limit_req_zone参数说明如下:
 语法:limit_req_zonekey zone=name:size rate=rate;
 用于设置共享内存区域,key可以是字符串、Nginx自有变量或前两个组合,如$binary_remote_addr。name为内存区域的名称,size为内存区域的大小,rate为速率,单位为r/s,每秒一个请求。
 cat /application/nginx/conf/nginx.conf         
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
#<==以请求的客户端IP作为key值,内存区域命名为one,分配10m内存空间,访问速率限制为1秒1次请求(request)
    server {
        listen       80;
        server_name   www.etiantian.org;
        location / {
            root   html;
            index  index.html index.htm;
            limit_req zone=one burst=5; 
#<==使用前面定义的名为one的内存空间,队列值为5,即可以有5个请求排队等待。
        }
    }
}

 

posted @ 2017-10-20 16:56  goser  阅读(482)  评论(0)    收藏  举报