当前位置: 首页 > news >正文

ps网站首页怎么做网站建设服务商排名

ps网站首页怎么做,网站建设服务商排名,有没有哪种网站推荐一下,海贼王网页设计素材NGINX以高性能的负载均衡器#xff0c;缓存#xff0c;和web服务器闻名#xff0c;驱动了全球超过 40% 最繁忙的网站。在大多数场景下#xff0c;默认的 NGINX 和 Linux 设置可以很好的工作#xff0c;但要达到最佳性能#xff0c;有些时候必须做些调整。首先我们先了解其…      NGINX以高性能的负载均衡器缓存和web服务器闻名驱动了全球超过 40% 最繁忙的网站。在大多数场景下默认的 NGINX 和 Linux 设置可以很好的工作但要达到最佳性能有些时候必须做些调整。首先我们先了解其工作原理。 一.  Nginx的模块与工作原理 Nginx由内核和模块组成其中内核的设计非常微小和简洁完成的工作也非常简单仅仅通过查找配置文件将客户端请求映射到一个location blocklocation是Nginx配置中的一个指令用于URL匹配而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。 Nginx的模块从结构上分为核心模块、基础模块和第三方模块 核心模块HTTP模块、EVENT模块和MAIL模块 基础模块HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块 第三方模块HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块。 用户根据自己的需要开发的模块都属于第三方模块。正是有了这么多模块的支撑Nginx的功能才会如此强大。 Nginx的模块从功能上分为如下三类。 Handlers处理器模块。此类模块直接处理请求并进行输出内容和修改headers信息等操作。Handlers处理器模块一般只能有一个。 Filters 过滤器模块。此类模块主要对其他处理器模块输出的内容进行修改操作最后由Nginx输出。 Proxies 代理类模块。此类模块是Nginx的HTTP Upstream之类的模块这些模块主要与后端一些服务比如FastCGI等进行交互实现服务代理和负载均衡等功能。 图1-1展示了Nginx模块常规的HTTP请求和响应的过程。 Nginx本身做的工作实际很少当它接到一个HTTP请求时它仅仅是通过查找配置文件将此次请求映射到一个location block而此location中所配置的各个指令则会启动不同的模块去完成工作因此模块可以看做Nginx真正的劳动工作者。通常一个location中的指令会涉及一个handler模块和多个filter模块当然多个location可以复用同一个模块。handler模块负责处理请求完成响应内容的生成而filter模块对响应内容进行处理。 Nginx的模块直接被编译进Nginx因此属于静态编译方式。启动Nginx后Nginx的模块被自动加载不像Apache首先将模块编译为一个so文件然后在配置文件中指定是否进行加载。在解析配置文件时Nginx的每个模块都有可能去处理某个请求但是同一个处理请求只能由一个模块来完成。  二.  Nginx的进程模型 在工作方式上Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下除主进程外还有一个工作进程工作进程是单线程的在多工作进程模式下每个工作进程包含多个线程。Nginx默认为单工作进程模式。 Nginx在启动后会有一个master进程和多个worker进程。 1、master进程管理进程 master进程主要用来管理worker进程具体包括如下4个主要功能         1接收来自外界的信号。         2向各worker进程发送信号。         3监控woker进程的运行状态。         4当woker进程退出后异常情况下会自动重新启动新的woker进程。 用户交互接口master进程充当整个进程组与用户的交互接口同时对进程进行监护。它不需要处理网络事件不负责业务的执行只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。 重启work进程我们要控制nginx只需要通过kill向master进程发送信号就行了。比如kill -HUP pid则是告诉nginx从容地重启nginx我们一般用这个信号来重启nginx或重新加载配置因为是从容地重启因此服务是不中断的。 master进程在接收到HUP信号后是怎么做的呢 1、首先master进程在接到信号后会先重新加载配置文件然后再启动新的worker进程并向所有老的worker进程发送信号告诉他们可以光荣退休了。 2、新的worker在启动后就开始接收新的请求而老的worker在收到来自master的信号后就不再接收新的请求并且在当前进程中的所有未处理完的请求处理完成后再退出。 直接给master进程发送信号这是比较传统的操作方式nginx在0.8版本之后引入了一系列命令行参数来方便我们管理。比如./nginx -s reload就是来重启nginx./nginx -s stop就是来停止nginx的运行。如何做到的呢我们还是拿reload来说我们看到执行命令时我们是启动一个新的nginx进程而新的nginx进程在解析到reload参数后就知道我们的目的是控制nginx来重新加载配置文件了它会向master进程发送信号然后接下来的动作就和我们直接向master进程发送信号一样了。 2、worker进程处理请求 而基本的网络事件则是放在worker进程中来处理了。多个worker进程之间是对等的他们同等竞争来自客户端的请求各进程互相之间是独立的。一个请求只可能在一个worker进程中处理一个worker进程不可能处理其它进程的请求。worker进程的个数是可以设置的一般我们会设置与机器cpu核数一致这里面的原因与nginx的进程模型以及事件处理模型是分不开的。 worker进程之间是平等的每个进程处理请求的机会也是一样的。当我们提供80端口的http服务时一个连接请求过来每个进程都有可能处理这个连接怎么做到的呢 Nginx采用异步非阻塞的方式来处理网络事件类似于Libevent具体过程如下 1接收请求首先每个worker进程都是从master进程fork过来在master进程建立好需要listen的socketlistenfd之后然后再fork出多个worker进程。所有worker进程的listenfd会在新连接到来时变得可读每个work进程都可以去accept这个socketlistenfd。当一个client连接到来时所有accept的work进程都会受到通知但只有一个进程可以accept成功其它的则会accept失败。为保证只有一个进程处理该连接Nginx提供了一把共享锁accept_mutex来保证同一时刻只有一个work进程在accept连接。所有worker进程在注册listenfd读事件前抢accept_mutex抢到互斥锁的那个进程注册listenfd读事件在读事件里调用accept接受该连接。 2处理请求当一个worker进程在accept这个连接之后就开始读取请求解析请求处理请求产生数据后再返回给客户端最后才断开连接这样一个完整的请求就是这样的了。 我们可以看到一个请求完全由worker进程来处理而且只在一个worker进程中处理。worker进程之间是平等的每个进程处理请求的机会也是一样的。 nginx的进程模型可以由下图来表示 三.   Nginx为啥性能高主从多进程/事件驱动/非阻塞IO模型 参考http://mp.weixin.qq.com/s?__bizMjM5NTg2NTU0Ngmid407889757idx3sncfa8a70a5fd2a674a91076f67808273cscene23srcid0401aeJQEraSG6uvLj69Hfve#rd 1、nginx采用多进程模型好处 首先对于每个worker进程来说独立的进程不需要加锁所以省掉了锁带来的开销同时在编程以及问题查找时也会方便很多。 其次采用独立的进程可以让互相之间不会影响一个进程退出后其它进程还在工作服务不会中断master进程则很快启动新的worker进程。当然worker进程的异常退出肯定是程序有bug了异常退出会导致当前worker上的所有请求失败不过不会影响到所有请求所以降低了风险。 2、nginx多进程事件驱动模型和异步非阻塞IO 虽然nginx采用多worker的方式来处理请求每个worker里面只有一个主线程那能够处理的并发数很有限啊多少个worker就能处理多少个并发何来高并发呢非也这就是nginx的高明之处nginx采用了事件驱动和异步非阻塞I/O的方式来处理请求 事件驱动模型Nginx 采用了事件驱动的模型来处理请求。在这种模型中主循环负责监听是否有新的事件如新的连接或者已有连接上的新数据一旦有事件发生就进行相应的处理。这种设计使得 Nginx 可以同时处理多个事件而不是在处理一个事件的时候阻塞其他事件。 非阻塞 I/ONginx 使用了非阻塞的 I/O 操作。传统的阻塞 I/O 操作在读写数据的时候会阻塞当前的线程直到数据准备好才继续。而非阻塞 I/O 操作则会立即返回即使数据还没有准备好然后在后台继续等待数据。这样Nginx 可以在等待数据的同时处理其他的事件。 因此nginx是可以同时处理成千上万个请求的。在处理一个连接的时候Nginx 不会被阻塞而是可以继续处理其他的连接。一个worker进程可以同时处理的请求数只受限于内存大小而且在架构设计上不同的worker进程之间处理并发请求时几乎没有同步锁的限制worker进程通常不会进入睡眠状态因此当Nginx上的进程数与CPU核心数相等时最好每一个worker进程都绑定特定的CPU核心进程间切换的代价是最小的。 而apache的常用工作方式apache也有异步非阻塞版本但因其与自带某些模块冲突所以不常用每个进程在一个时刻只处理一个请求因此当并发数上到几千时就同时有几千的进程在处理请求了。这对操作系统来说是个不小的挑战进程带来的内存占用非常大进程的上下文切换带来的cpu开销很大自然性能就上不去了而这些开销完全是没有意义的。 为什么nginx可以采用异步非阻塞的方式来处理呢或者异步非阻塞到底是怎么回事呢具体请看使用 libevent 和 libev 提高网络应用性能——I/O模型演进变化史 3、Reactor主从NIO线程模型 mainReactor负责监听server socketaccept新连接并将建立的socket分派给subReactor。   subReactor负责多路分离已连接的socket读写网络数据对业务处理功能其扔给worker线程池完成。通常subReactor个数上可与CPU个数等同。 利用主从NIO线程模型可以解决一个服务端监听线程无法有效处理所有客户端连接的性能不足问题 我们先回到原点看看一个请求的完整过程:首先请求过来要建立连接然后再接收数据接收数据后再发送数据。 具体到系统底层就是读写事件而当读写事件没有准备好时必然不可操作如果不用非阻塞的方式来调用那就得阻塞调用了事件没有准备好那就只能等了等事件准备好了你再继续吧。阻塞调用会进入内核等待cpu就会让出去给别人用了对单线程的worker来说显然不合适当网络事件越多时大家都在等待呢cpu空闲下来没人用cpu利用率自然上不去了更别谈高并发了。好吧你说加进程数这跟apache的线程模型有什么区别注意别增加无谓的上下文切换。所以在nginx里面最忌讳阻塞的系统调用了。不要阻塞那就非阻塞喽。非阻塞就是事件没有准备好马上返回EAGAIN告诉你事件还没准备好呢你慌什么过会再来吧。好吧你过一会再来检查一下事件直到事件准备好了为止在这期间你就可以先去做其它事情然后再来看看事件好了没。虽然不阻塞了但你得不时地过来检查一下事件的状态你可以做更多的事情了但带来的开销也是不小的。 关于IO模型socket/io(3)、socket阻塞与非阻塞同步与异步、I/O模型_socket异步-CSDN博客 4、nginx支持的I/O复用模型如下nginx的wiki: Nginx支持如下处理连接的方法I/O复用方法这些方法可以通过use指令指定。 select– 标准方法。 如果当前平台没有更有效的方法它是编译时默认的方法。你可以使用配置参数 –with-select_module 和 –without-select_module 来启用或禁用这个模块。poll– 标准方法。 如果当前平台没有更有效的方法它是编译时默认的方法。你可以使用配置参数 –with-poll_module 和 –without-poll_module 来启用或禁用这个模块。kqueue– 高效的方法使用于 FreeBSD 4.1, OpenBSD 2.9, NetBSD 2.0 和 MacOS X. 使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。epoll – 高效的方法使用于Linux内核2.6版本及以后的系统。在某些发行版本中如SuSE 8.2, 有让2.4版本的内核支持epoll的补丁。rtsig – 可执行的实时信号使用于Linux内核版本2.2.19以后的系统。默认情况下整个系统中不能出现大于1024个POSIX实时(排队)信号。这种情况 对于高负载的服务器来说是低效的所以有必要通过调节内核参数 /proc/sys/kernel/rtsig-max 来增加队列的大小。可是从Linux内核版本2.6.6-mm2开始 这个参数就不再使用了并且对于每个进程有一个独立的信号队列这个队列的大小可以用 RLIMIT_SIGPENDING 参数调节。当这个队列过于拥塞nginx就放弃它并且开始使用 poll 方法来处理连接直到恢复正常。/dev/poll – 高效的方法使用于 Solaris 7 11/99, HP/UX 11.22 (eventport), IRIX 6.5.15 和 Tru64 UNIX 5.1A.eventport – 高效的方法使用于 Solaris 10. 为了防止出现内核崩溃的问题 有必要安装这个 安全补丁。 5、epoll的优点nginx如何支持百万连接数 在linux下面只有epoll是高效的方法 下面再来看看epoll到底是如何高效的        Epoll是Linux内核为处理大批量句柄而作了改进的poll。 要使用epoll只需要这三个系统调用epoll_create(2) epoll_ctl(2) epoll_wait(2)。 工作进程与最大连接数worker_processes*work_connections nginx支持的并发连接数越大理论上能支持的并发用户数就越多所以从性能角度来说期望这个越大越好。而这个值等于worker_processes与work_connections的乘积。 worker_processes要看cpu的核数如果设置固定数值就要小于等于CPU核数如果设置为auto启动nginx时会根据CPU的繁忙情况自动参数worker数量。 work_connections是单个worker的最大连接数这个值受系统ulimit的限制ulimit -n可以看到系统一个进程允许打开的最大文件数量同时系统还有/proc/sys/fs/file-max限制整个系统允许打开的最大文件数即worker_processes与work_connections的乘积最大不能超过file-max的限制所以还要适当调整系统参数限制。 epoll支持一个进程打开大数目的socket描述符(FD) select 最不能忍受的是一个进程所打开的FD是有一定限制的由FD_SETSIZE设置默认值是1024/2048。对于那些需要支持的上万连接数目的web服务器来说显 然太少了。这时候你一是可以选择修改这个宏然后重新编译内核不过资料也同时指出这样会带来网络效率的下降二是可以选择多进程的解决方案(传统的 Apache方案)不过虽然linux上面创建进程的代价比较小但仍旧是不可忽视的加上进程间数据同步远比不上线程间同步的高效所以也不是一种完 美的方案。不过 epoll则没有这个限制它所支持的FD上限是最大可以打开文件的数目这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左 右具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。 IO效率不随FD数目增加而线性下降 传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合不过由于网络延时任一时间只有部分的socket是”活跃”的但 是select/poll每次调用都会线性扫描全部的集合导致效率呈现线性下降。但是epoll不存在这个问题它只会对”活跃”的socket进行操 作—这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么只有”活跃”的socket才会主动的去调用 callback函数其他idle状态socket则不会在这点上epoll实现了一个”伪”AIO因为这时候推动力在os内核。在一些 benchmark中如果所有的socket基本上都是活跃的—比如一个高速LAN环境epoll并不比select/poll有什么效率相 反如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。 使用mmap加速内核与用户空间的消息传递。 这 点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间如何避免不必要的内存拷贝就很 重要在这点上epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注epoll的话一定不会忘记手工 mmap这一步的。 内核微调 这一点其实不算epoll的优点了而是整个linux平台的优点。也许你可以怀疑linux平台但是你无法回避linux平台赋予你微调内核的能力。比如内核TCP/IP协 议栈使用内存池管理sk_buff结构那么可以在运行时期动态调整这个内存pool(skb_head_pool)的大小— 通过echo XXXX/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参数(TCP完成3次握手 的数据包队列长度)也可以根据你平台内存大小动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网卡驱动架构。 (epoll内容参考epoll_互动百科) 推荐设置worker的个数为cpu的核数在这里就很容易理解了更多的worker数只会导致进程来竞争cpu资源了从而带来不必要的上下文切换。而且nginx为了更好的利用多核特性提供了cpu亲缘性的绑定选项我们可以将某一个进程绑定在某一个核上这样就不会因为进程的切换带来cache的失效。像这种小的优化在nginx中非常常见同时也说明了nginx作者的苦心孤诣。比如nginx在做4个字节的字符串比较时会将4个字符转换成一个int型再作比较以减少cpu的指令数等等。 6、代码来总结一下nginx的事件处理模型 while (true) {for t in run_tasks:t.handler();update_time(now);timeout ETERNITY;for t in wait_tasks: /* sorted already */if (t.time now) {t.timeout_handler();} else {timeout t.time - now;break;}nevents poll_function(events, timeout);for i in nevents:task t;if (events[i].type READ) {t.handler read_handler;} else { /* events[i].type WRITE */t.handler write_handler;}run_tasks_add(t); } 四.  NginxFastCGI运行原理 1、什么是 FastCGI FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI包括Apache、Nginx和lighttpd等。同时FastCGI也被许多脚本语言支持其中就有PHP。 FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析然后将结果返回给HTTP服务器。这在处理高并发访问时几乎是不可用的。另外传统的CGI接口方式安全性也很差现在已经很少使用了。 FastCGI接口方式采用C/S结构可以将HTTP服务器和脚本解析服务器分开同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时可以将其直接交付给FastCGI进程来执行然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端这在很大程度上提高了整个应用系统的性能。 2、NginxFastCGI运行原理 Nginx不支持对外部程序的直接调用或者解析所有的外部程序包括PHP必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket这个socket可以是文件socket也可以是ip socket。 wrapper为了调用CGI程序还需要一个FastCGI的wrapperwrapper可以理解为用于启动另一个程序的程序这个wrapper绑定在某个固定socket上如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候通过FastCGI接口wrapper接收到请求然后Fork(派生出一个新的线程这个线程调用解释器或者外部程序处理脚本并读取返回数据接着wrapper再将返回的数据通过FastCGI接口沿着固定的socket传递给Nginx最后Nginx将返回的数据html页面或者图片发送给客户端。这就是NginxFastCGI的整个运作过程如图1-3所示。 所以我们首先需要一个wrapper这个wrapper需要完成的工作 通过调用fastcgi库的函数通过socket和ningx通信读写socket是fastcgi内部实现的功能对wrapper是非透明的调度thread进行fork和kill和applicationphp进行通信 3、spawn-fcgi与PHP-FPM FastCGI接口方式在脚本解析服务器上启动一个或者多个守护进程对动态脚本进行解析这些进程就是FastCGI进程管理器或者称为FastCGI引擎。 spawn-fcgi与PHP-FPM就是支持PHP的两个FastCGI进程管理器。因此HTTPServer完全解放出来可以更好地进行响应和并发处理。 spawn-fcgi与PHP-FPM的异同        1spawn-fcgi是HTTP服务器lighttpd的一部分目前已经独立成为一个项目一般与lighttpd配合使用来支持PHP。但是ligttpd的spwan-fcgi在高并发访问的时候会出现内存泄漏甚至自动重启FastCGI的问题。即PHP脚本处理器当机这个时候如果用户访问的话可能就会出现白页(即PHP不能被解析或者出错)。 2Nginx是个轻量级的HTTP server必须借助第三方的FastCGI处理器才可以对PHP进行解析因此其实这样看来nginx是非常灵活的它可以和任何第三方提供解析的处理器实现连接从而实现对PHP的解析(在nginx.conf中很容易设置)。nginx也可以使用spwan-fcgi(需要一同安装lighttpd但是需要为nginx避开端口一些较早的blog有这方面安装的教程)但是由于spawn-fcgi具有上面所述的用户逐渐发现的缺陷现在慢慢减少用nginxspawn-fcgi组合了。 由于spawn-fcgi的缺陷现在出现了第三方(目前已经加入到PHP core中)的PHP的FastCGI处理器PHP-FPM它和spawn-fcgi比较起来有如下优点 由于它是作为PHP的patch补丁来开发的安装的时候需要和php源码一起编译也就是说编译到php core中了因此在性能方面要优秀一些 同时它在处理高并发方面也优于spawn-fcgi至少不会自动重启fastcgi处理器。因此推荐使用NginxPHP/PHP-FPM这个组合对PHP进行解析。 相对Spawn-FCGIPHP-FPM在CPU和内存方面的控制都更胜一筹而且前者很容易崩溃必须用crontab进行监控而PHP-FPM则没有这种烦恼。        FastCGI 的主要优点是把动态语言和HTTP Server分离开来所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上以分担前端Nginx服务器的压力使Nginx专一处理静态请求和转发动态请求而PHP/PHP-FPM服务器专一解析PHP动态请求。 4、NginxPHP-FPM PHP-FPM是管理FastCGI的一个管理器它作为PHP的插件存在在安装PHP要想使用PHP-FPM时在老php的老版本php5.3.3之前就需要把PHP-FPM以补丁的形式安装到PHP中而且PHP要与PHP-FPM版本一致这是必须的 PHP-FPM其实是PHP源代码的一个补丁旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的PHP源代码中在编译安装PHP后才可以使用。    PHP5.3.3已经集成php-fpm了不再是第三方的包了。PHP-FPM提供了更好的PHP进程管理方式可以有效控制内存和进程、可以平滑重载PHP配置比spawn-fcgi具有更多优点所以被PHP官方收录了。在./configure的时候带 –enable-fpm参数即可开启PHP-FPM。 fastcgi已经在php5.3.5的core中了不必在configure时添加 --enable-fastcgi了。老版本如php5.2的需要加此项。 当我们安装Nginx和PHP-FPM完后配置信息 PHP-FPM的默认配置php-fpm.conf listen_address  127.0.0.1:9000 #这个表示php的fastcgi进程监听的ip地址以及端口 start_servers min_spare_servers max_spare_servers Nginx配置运行php 编辑nginx.conf加入如下语句 location ~ \.php$ {             root html;                fastcgi_pass 127.0.0.1:9000; 指定了fastcgi进程侦听的端口,nginx就是通过这里与php交互的             fastcgi_index index.php;             include fastcgi_params;              fastcgi_param SCRIPT_FILENAME   /usr/local/nginx/html$fastcgi_script_name;     } Nginx通过location指令将所有以php为后缀的文件都交给127.0.0.1:9000来处理而这里的IP地址和端口就是FastCGI进程监听的IP地址和端口。 其整体工作流程 1)、FastCGI进程管理器php-fpm自身初始化启动主进程php-fpm和启动start_servers个CGI 子进程。 主进程php-fpm主要是管理fastcgi子进程监听9000端口。 fastcgi子进程等待来自Web Server的连接。 2)、当客户端请求到达Web Server Nginx是时Nginx通过location指令将所有以php为后缀的文件都交给127.0.0.1:9000来处理即Nginx通过location指令将所有以php为后缀的文件都交给127.0.0.1:9000来处理。 3FastCGI进程管理器PHP-FPM选择并连接到一个子进程CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程。 4)、FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时请求便告处理完成。 5)、FastCGI子进程接着等待并处理来自FastCGI进程管理器运行在 WebServer中的下一个连接。 五.   NginxPHP正确配置 一般web都做统一入口把PHP请求都发送到同一个文件上然后在此文件里通过解析「REQUEST_URI」实现路由。 Nginx配置文件分为好多块常见的从外到内依次是「http」、「server」、「location」等等缺省的继承关系是从外到内也就是说内层块会自动获取外层块的值作为缺省值。 例如 server {listen 80;server_name foo.com;root /path;location / {index index.html index.htm index.php;if (!-e $request_filename) {rewrite . /index.php last;}}location ~ \.php$ {include fastcgi_params;fastcgi_param SCRIPT_FILENAME /path$fastcgi_script_name;fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;} } 1)  不应该在location 模块定义index 一旦未来需要加入新的「location」必然会出现重复定义的「index」指令这是因为多个「location」是平级的关系不存在继承此时应该在「server」里定义「index」借助继承关系「index」指令在所有的「location」中都能生效。 2)     使用try_files 接下来看看「if」指令说它是大家误解最深的Nginx指令毫不为过 if (!-e $request_filename) {     rewrite . /index.php last; } 很多人喜欢用「if」指令做一系列的检查不过这实际上是「try_files」指令的职责 try_files $uri $uri/ /index.php; 除此以外初学者往往会认为「if」指令是内核级的指令但是实际上它是rewrite模块的一部分加上Nginx配置实际上是声明式的而非过程式的所以当其和非rewrite模块的指令混用时结果可能会非你所愿。 3fastcgi_params」配置文件 include fastcgi_params; Nginx有两份fastcgi配置文件分别是「fastcgi_params」和「fastcgi.conf」它们没有太大的差异唯一的区别是后者比前者多了一行「SCRIPT_FILENAME」的定义 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 注意$document_root 和 $fastcgi_script_name 之间没有 /。 原本Nginx只有「fastcgi_params」后来发现很多人在定义「SCRIPT_FILENAME」时使用了硬编码的方式于是为了规范用法便引入了「fastcgi.conf」。 不过这样的话就产生一个疑问为什么一定要引入一个新的配置文件而不是修改旧的配置文件这是因为「fastcgi_param」指令是数组型的和普通指令相同的是内层替换外层和普通指令不同的是当在同级多次使用的时候是新增而不是替换。换句话说如果在同级定义两次「SCRIPT_FILENAME」那么它们都会被发送到后端这可能会导致一些潜在的问题为了避免此类情况便引入了一个新的配置文件。 此外我们还需要考虑一个安全问题在PHP开启「cgi.fix_pathinfo」的情况下PHP可能会把错误的文件类型当作PHP文件来解析。如果Nginx和PHP安装在同一台服务器上的话那么最简单的解决方法是用「try_files」指令做一次过滤 try_files $uri 404; 依照前面的分析给出一份改良后的版本是不是比开始的版本清爽了很多 server {listen 80;server_name foo.com;root /path;index index.html index.htm index.php;location / {try_files $uri $uri/ /index.php;}location ~ \.php$ {try_files $uri 404;include fastcgi.conf;fastcgi_pass 127.0.0.1:9000;} } 六.   Nginx优化 1. 编译安装过程优化 1.减小Nginx编译后的文件大小 在编译Nginx时默认以debug模式进行而在debug模式下会插入很多跟踪和ASSERT之类的信息编译完成后一个Nginx要有好几兆字节。而在编译前取消Nginx的debug模式编译完成后Nginx只有几百千字节。因此可以在编译之前修改相关源码取消debug模式。具体方法如下 在Nginx源码文件被解压后找到源码目录下的auto/cc/gcc文件在其中找到如下几行 # debug CFLAGS”$CFLAGS -g” 注释掉或删掉这两行即可取消debug模式。 2.为特定的CPU指定CPU类型编译优化 在编译Nginx时默认的GCC编译参数是“-O”要优化GCC编译可以使用以下两个参数 --with-cc-opt-O3 --with-cpu-optCPU  #为特定的 CPU 编译有效的值包括 pentium, pentiumpro, pentium3, # pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64  要确定CPU类型可以通过如下命令 #cat /proc/cpuinfo | grep model name  2. 利用TCMalloc优化Nginx的性能 TCMalloc的全称为Thread-Caching Malloc是谷歌开发的开源工具google-perftools中的一个成员。与标准的glibc库的Malloc相比TCMalloc库在内存分配效率和速度上要高很多这在很大程度上提高了服务器在高并发情况下的性能从而降低了系统的负载。下面简单介绍如何为Nginx添加TCMalloc库支持。 要安装TCMalloc库需要安装libunwind32位操作系统不需要安装和google-perftools两个软件包libunwind库为基于64位CPU和操作系统的程序提供了基本函数调用链和函数调用寄存器功能。下面介绍利用TCMalloc优化Nginx的具体操作过程。 1).安装libunwind库 可以从Index of /nongnu/libunwind/下载相应的libunwind版本这里下载的是libunwind-0.99-alpha.tar.gz。安装过程如下 #tar zxvf libunwind-0.99-alpha.tar.gz   # cd libunwind-0.99-alpha/   #CFLAGS-fPIC ./configure   #make CFLAGS-fPIC   #make CFLAGS-fPIC install 2).安装google-perftools 可以从http://google-perftools.googlecode.com下载相应的google-perftools版本这里下载的是google-perftools-1.8.tar.gz。安装过程如下 [rootlocalhost home]#tar zxvf google-perftools-1.8.tar.gz   [rootlocalhost home]#cd google-perftools-1.8/   [rootlocalhost google-perftools-1.8]# ./configure   [rootlocalhost google-perftools-1.8]#make make install   [rootlocalhost google-perftools-1.8]#echo /usr/ local/lib /etc/ld.so.conf.d/usr_local_lib.conf   [rootlocalhost google-perftools-1.8]# ldconfig 至此google-perftools安装完成。 3).重新编译Nginx 为了使Nginx支持google-perftools需要在安装过程中添加“–with-google_perftools_module”选项重新编译Nginx。安装代码如下 [rootlocalhostnginx-0.7.65]#./configure \   --with-google_perftools_module --with-http_stub_status_module  --prefix/opt/nginx   [rootlocalhost nginx-0.7.65]#make   [rootlocalhost nginx-0.7.65]#make install 到这里Nginx安装完成。 4).为google-perftools添加线程目录 创建一个线程目录这里将文件放在/tmp/tcmalloc下。操作如下 [rootlocalhost home]#mkdir /tmp/tcmalloc   [rootlocalhost home]#chmod 0777 /tmp/tcmalloc 5).修改Nginx主配置文件 修改nginx.conf文件在pid这行的下面添加如下代码 #pid        logs/nginx.pid;   google_perftools_profiles /tmp/tcmalloc; 接着重启Nginx即可完成google-perftools的加载。 6).验证运行状态 为了验证google-perftools已经正常加载可通过如下命令查看 [root localhost home]# lsof -n | grep tcmalloc   nginx      2395 nobody   9w  REG    8,8       0    1599440 /tmp/tcmalloc.2395   nginx      2396 nobody   11w REG   8,8       0    1599443 /tmp/tcmalloc.2396   nginx      2397 nobody   13w REG  8,8        0    1599441  /tmp/tcmalloc.2397   nginx     2398 nobody    15w REG  8,8     0    1599442 /tmp/tcmalloc.2398 由于在Nginx配置文件中设置worker_processes的值为4因此开启了4个Nginx线程每个线程会有一行记录。每个线程文件后面的数字值就是启动的Nginx的pid值。 至此利用TCMalloc优化Nginx的操作完成。 3.Nginx内核参数优化 内核参数的优化主要是在Linux系统中针对Nginx应用而进行的系统内核参数优化。 下面给出一个优化实例以供参考。 net.ipv4.tcp_max_tw_buckets 6000 net.ipv4.ip_local_port_range 1024 65000   net.ipv4.tcp_tw_recycle 1 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_syncookies 1 net.core.somaxconn 262144 net.core.netdev_max_backlog 262144 net.ipv4.tcp_max_orphans 262144 net.ipv4.tcp_max_syn_backlog 262144 net.ipv4.tcp_synack_retries 1 net.ipv4.tcp_syn_retries 1 net.ipv4.tcp_fin_timeout 1 net.ipv4.tcp_keepalive_time 30 将上面的内核参数值加入/etc/sysctl.conf文件中然后执行如下命令使之生效 [root localhost home]#/sbin/sysctl -p  下面对实例中选项的含义进行介绍 TCP参数设置 net.ipv4.tcp_max_tw_buckets 选项用来设定timewait的数量默认是180 000这里设为6000。 net.ipv4.ip_local_port_range:选项用来设定允许系统打开的端口范围。在高并发情况否则端口号会不够用。当NGINX充当代理时每个到上游服务器的连接都使用一个短暂或临时端口。 net.ipv4.tcp_tw_recycle:选项用于设置启用timewait快速回收. net.ipv4.tcp_tw_reuse:选项用于设置开启重用允许将TIME-WAIT sockets重新用于新的TCP连接。 net.ipv4.tcp_syncookies:选项用于设置开启SYN Cookies当出现SYN等待队列溢出时启用cookies进行处理。 net.ipv4.tcp_max_orphans:选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字孤立连接将立即被复位并打印出警告信息。这个限制只是为了防止简单的DoS攻击。不能过分依靠这个限制甚至人为减小这个值更多的情况下应该增加这个值。 net.ipv4.tcp_max_syn_backlog:选项用于记录那些尚未收到客户端确认信息的连接请求的最大值。对于有128MB内存的系统而言此参数的默认值是1024对小内存的系统则是128。 net.ipv4.tcp_synack_retries参数的值决定了内核放弃连接之前发送SYNACK包的数量。 net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。 net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。默认值是60秒。正确设置这个值非常重要有时即使一个负载很小的Web服务器也会出现大量的死套接字而产生内存溢出的风险。 net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。 如果发送端要求关闭套接字net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。接收端可以出错并永远不关闭连接甚至意外宕机。 net.ipv4.tcp_fin_timeout的默认值是60秒。需要注意的是即使一个负载很小的Web服务器也会出现因为大量的死套接字而产生内存溢出的风险。FIN-WAIT-2的危险性比FIN-WAIT-1要小因为它最多只能消耗1.5KB的内存但是其生存期长些。 net.ipv4.tcp_keepalive_time选项表示当keepalive启用的时候TCP发送keepalive消息的频度。默认值是2单位是小时。 缓冲区队列: net.core.somaxconn:选项的默认值是128 这个参数用于调节系统同时发起的tcp连接数在高并发的请求中默认的值可能会导致链接超时或者重传因此需要结合并发请求数来调节此值。 由NGINX可接受的数目决定。默认值通常很低但可以接受因为NGINX 接收连接非常快但如果网站流量大时就应该增加这个值。内核日志中的错误消息会提醒这个值太小了把值改大直到错误提示消失。 注意 如果设置这个值大于512相应地也要改变NGINX listen指令的backlog参数。 net.core.netdev_max_backlog:选项表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时允许发送到队列的数据包的最大数目。 4、关于TIME_WAIT快速回收的优化GPT4的回答 4.PHP-FPM的优化 如果您高负载网站使用PHP-FPM管理FastCGI这些技巧也许对您有用: 1增加FastCGI进程数 把PHP FastCGI子进程数调到100或以上在4G内存的服务器上200就可以建议通过压力测试获取最佳值。 2增加 PHP-FPM打开文件描述符的限制 标签rlimit_files用于设置PHP-FPM对打开文件描述符的限制默认值为1024。这个标签的值必须和Linux内核打开文件数关联起来例如要将此值设置为65 535就必须在Linux命令行执行“ulimit -HSn 65536”。 然后 增加 PHP-FPM打开文件描述符的限制:      # vi /path/to/php-fpm.conf     找到“valuenamerlimit_files1024/value” 把1024更改为 4096或者更高. 重启 PHP-FPM. ulimit -n 要调整为65536甚至更大。如何调这个参数可以参考网上的一些文章。命令行下执行 ulimit -n 65536即可修改。如果不能修改需要设置  /etc/security/limits.conf加入 * hard nofile65536 * soft nofile 65536 3适当增加max_requests 标签max_requests指明了每个children最多处理多少个请求后便会被关闭默认的设置是500。 value namemax_requests 500 /value 5.nginx.conf的参数优化 nginx要开启的进程数 一般等于cpu的总核数 其实一般情况下开4个或8个就可以。 每个nginx进程消耗的内存10兆的模样 worker_cpu_affinity     仅适用于linux使用该选项可以绑定worker进程和CPU2.4内核的机器用不了 假如是8 cpu 分配如下     worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 nginx可以使用多个worker进程原因如下 to use SMP  to decrease latency when workers blockend on disk I/O  to limit number of connections per process when select()/poll() is used The worker_processes and worker_connections from the event sections allows you to calculate maxclients value: k max_clients worker_processes * worker_connections worker_rlimit_nofile 102400; 每个nginx进程打开文件描述符最大数目 配置要和系统的单进程打开文件数一致,linux 2.6内核下开启文件打开数为65535worker_rlimit_nofile就相应应该填写65535 nginx调度时分配请求到进程并不是那么的均衡假如超过会返回502错误。我这里写的大一点 use epoll Nginx使用了最新的epollLinux 2.6内核和kqueuefreebsd网络I/O模型而Apache则使用的是传统的select模型。 处理大量的连接的读写Apache所采用的select网络I/O模型非常低效。在高并发服务器中轮询I/O是最耗时间的操作 目前Linux下能够承受高并发 访问的Squid、Memcached都采用的是epoll网络I/O模型。 worker_processes  NGINX工作进程数默认值是1。在大多数情况下一个CPU内核运行一个工作进程最好建议将这个指令设置成自动就可以。有时可能想增大这个值比如当工作进程需要做大量的磁盘I/O。 worker_connections 65535;    每个工作进程允许最大的同时连接数 Maxclient work_processes * worker_connections keepalive_timeout 75 keepalive超时时间 这里需要注意官方的一句话 The parameters can differ from each other. Line Keep-Alive: timeouttime understands Mozilla and Konqueror. MSIE itself shuts keep-alive connection approximately after 60 seconds. client_header_buffer_size 16k large_client_header_buffers 4 32k客户请求头缓冲大小  nginx默认会用client_header_buffer_size这个buffer来读取header值如果header过大它会使用large_client_header_buffers来读取 如果设置过小HTTP头/Cookie过大 会报400 错误 nginx 400 bad request 求行如果超过buffer就会报HTTP 414错误(URI Too Long) nginx接受最长的HTTP头部大小必须比其中一个buffer大否则就会报400的HTTP错误(Bad Request)。 open_file_cache max 102400 使用字段:http, server, location 这个指令指定缓存是否启用,如果启用,将记录文件以下信息: ·打开的文件描述符,大小信息和修改时间. ·存在的目录信息. ·在搜索文件过程中的错误信息 -- 没有这个文件,无法正确读取,参考open_file_cache_errors 指令选项: ·max - 指定缓存的最大数目,如果缓存溢出,最长使用过的文件(LRU)将被移除 例: open_file_cache max1000 inactive20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; open_file_cache_errors 语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误. open_file_cache_min_uses 语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location 这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如 果使用更大的值,文件描述符在cache中总是打开状态. open_file_cache_valid 语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息. 开启gzip gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; 缓存静态文件 location ~* ^.\.(swf|gif|png|jpg|js|css)$ {     root /usr/local/ku6/ktv/show.ku6.com/;     expires 1m; } 响应缓冲区 比如我们NginxTomcat 代理访问JS无法完全加载这几个参数影响 proxy_buffer_size 128k; proxy_buffers   32 128k; proxy_busy_buffers_size 128k; Nginx在代理了相应服务后或根据我们配置的UpStream和location来获取相应的文件首先文件会被解析到nginx的内存或者临时文件目录中然后由nginx再来响应。那么当proxy_buffers和proxy_buffer_size以及proxy_busy_buffers_size 都太小时会将内容根据nginx的配置生成到临时文件中但是临时文件的大小也有默认值。所以当这四个值都过小时就会导致部分文件只加载一部分。所以要根据我们的服务器情况适当的调整proxy_buffers和proxy_buffer_size以及proxy_busy_buffers_size、proxy_temp_file_write_size。具体几个参数的详细如下 proxy_buffers   32 128k;  设置了32个缓存区每个的大小是128k proxy_buffer_size 128k; 每个缓存区的大小是128k当两个值不一致时没有找到具体哪个有效建议和上面的设置一致。 proxy_busy_buffers_size 128k;设置使用中的缓存区的大小控制传输至客户端的缓存的最大 proxy_temp_file_write_size 缓存文件的大小 6.优化访问日志 记录每个请求会消耗CPU和I/O周期一种降低这种影响的方式是缓冲访问日志。使用缓冲而不是每条日志记录都单独执行写操作NGINX会缓冲一连串的日志记录使用单个操作把它们一起写到文件中。    要启用访问日志的缓存就涉及到在access_log指令中buffersize这个参数。当缓冲区达到size值时NGINX会把缓冲区的内容写到日志中。让NGINX在指定的一段时间后写缓存就包含flushtime参数。当两个参数都设置了当下个日志条目超出缓冲区值或者缓冲区中日志条目存留时间超过设定的时间值NGINX都会将条目写入日志文件。当工作进程重新打开它的日志文件或退出时也会记录下来。要完全禁用访问日志记录的功能将access_log 指令设置成off参数。 7.限流 你可以设置多个限制防止用户消耗太多的资源避免影响系统性能和用户体验及安全。 以下是相关的指令limit_conn and limit_conn_zoneNGINX接受客户连接的数量限制例如单个IP地址的连接。设置这些指令可以防止单个用户打开太多的连接消耗超出自己的资源。limit_rate传输到客户端响应速度的限制每个打开多个连接的客户消耗更多的带宽。设置这个限制防止系统过载确保所有客户端更均匀的服务质量。limit_req and limit_req_zoneNGINX处理请求的速度限制与limit_rate有相同的功能。可以提高安全性尤其是对登录页面通过对用户限制请求速率设置一个合理的值避免太慢的程序覆盖你的应用请求比如DDoS攻击)。max_conns上游配置块中服务器指令参数。在上游服务器组中单个服务器可接受最大并发数量。使用这个限制防止上游服务器过载。设置值为0默认值表示没有限制。queue (NGINX Plus) 创建一个队列用来存放在上游服务器中超出他们最大max_cons限制数量的请求。这个指令可以设置队列请求的最大值还可以选择设置在错误返回之前最大等待时间默认值是60秒。如果忽略这个指令请求不会放入队列。 七.   错误排查 所有错误的都在错误文件error.log里面 1、400 bad request错误的原因和解决办法 配置nginx.conf相关设置如下. client_header_buffer_size 16k;      large_client_header_buffers 4 64k; 根据具体情况调整一般适当调整值就可以。 2、Nginx出现的413 Request Entity Too Large错误 这个错误一般在上传文件的时候会出现 client intended to send too large body: 23937077 bytes, client: 10.45.142.41, server: localhost, request 服务器拒绝处理当前请求因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围。此种情况下服务器可以关闭连接以免客户端继续发送此请求。   如果这个状况是临时的服务器应当返回一个 Retry-After 的响应头以告知客户端可以在多少时间以后重新尝试。 编辑Nginx主配置文件Nginx.conf找到http{}段添加 client_max_body_size 10m; //设置多大根据自己的需求作调整. 如果运行php的话这个大小client_max_body_size要和php.ini中的如下值的最大值一致或者稍大这样就不会因为提交数据大         小不一致出现的错误。 post_max_size 10M         upload_max_filesize 2M 3、Nginx 502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时从上游服务器接收到无效的响应。 常见原因 1、后端服务挂了的情况,直接502 nginx error日志connect() failed (111: Connection refused)  2、后端服务在重启 实例将后端服务关掉然后向nginx发送请求后端接口nginx日志可以看到502错误。 如果nginxphp出现502, 错误分析 php-cgi进程数不够用、php执行时间长mysql慢、或者是php-cgi进程死掉都会出现502错误 一般来说Nginx 502 Bad Gateway和php-fpm.conf的设置有关而Nginx 504 Gateway Time-out则是与nginx.conf的设置有关 1、查看当前的PHP FastCGI进程数是否够用 netstat -anpo | grep php-cgi | wc -l 如果实际使用的“FastCGI进程数”接近预设的“FastCGI进程数”那么说明“FastCGI进程数”不够用需要增大。 2、部分PHP程序的执行时间超过了Nginx的等待时间可以适当增加 nginx.conf配置文件中FastCGI的timeout时间例如 http {     ......     fastcgi_connect_timeout 300;     fastcgi_send_timeout 300;     fastcgi_read_timeout 300;     ...... } 4、504 Gateway Timeout : nginx作为网关或者代理工作的服务器尝试执行请求时未能及时从上游服务器URI标识出的服务器例如HTTP、FTP、LDAP收到响应。 常见原因 该接口太耗时后端服务接收到请求开始执行未能在设定时间返回数据给nginx 后端服务器整体负载太高接受到请求之后由于线程繁忙未能安排给请求的接口导致未能在设定时间返回数据给nginx 5、413 Request Entity Too Large    解决增大client_max_body_size client_max_body_size:指令指定允许客户端连接的最大请求实体大小,它出现在请求头部的Content-Length字段. 如果请求大于指定的值,客户端将收到一个Request Entity Too Large (413)错误. 记住,浏览器并不知道怎样显示这个错误. php.ini中增大 post_max_size 和upload_max_filesize 6、 Ngnix error.log出现upstream sent too big header while reading response header from upstream错误 1)如果是nginx反向代理    proxy是nginx作为client转发时使用的如果header过大超出了默认的1k就会引发上述的upstream sent too big header 说白了就是nginx把外部请求给后端server后端server返回的header  太大nginx处理不过来就导致了。 server {         listen       80;         server_name  *.xywy.com ; large_client_header_buffers 4 16k; location / { #添加这3行            proxy_buffer_size 64k;            proxy_buffers   32 32k;            proxy_busy_buffers_size 128k; proxy_set_header Host $host;            proxy_set_header X-Real-IP       $remote_addr;            proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for; } }         2) 如果是 nginxPHPcgi  错误带有 upstream: fastcgi://127.0.0.1:9000。就该  多加 fastcgi_buffer_size 128k;  fastcgi_buffers 4 128k; server {         listen       80;         server_name  ddd.com;         index index.html index.htm index.php;            client_header_buffer_size 128k;         large_client_header_buffers 4 128k;         proxy_buffer_size 64k;         proxy_buffers 8 64k;         fastcgi_buffer_size 128k;         fastcgi_buffers 4 128k; location / { ...... } }          7、Nginx Error 99: Cannot ssign requested address 解决增加端口范围大小 echo 10240 65535 /proc/sys/net/ipv4/ip_local_port_range 根据实际情况优化参数 net.ipv4.tcp_tw_recycle 1 net.ipv4.tcp_tw_reuse 1 八  、 Nginx的php漏洞 漏洞介绍nginx是一款高性能的web服务器使用非常广泛其不仅经常被用作反向代理也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析这将导致严重的安全问题使得恶意的攻击者可能攻陷支持php的nginx服务器。 漏洞分析nginx默认以cgi的方式支持php的运行譬如在配置文件当中可以以location ~ .php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; } 的方式支持对php的解析location对请求进行选择的时候会使用URI环境变量进行选择其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的这里就是产生问题的点。而为了较好的支持PATH_INFO的提取在PHP的配置选项里存在cgi.fix_pathinfo选项其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。 那么假设存在一个http://www.80sec.com/80sec.jpg我们以如下的方式去访问 http://www.80sec.com/80sec.jpg/80sec.php 将会得到一个URI/80sec.jpg/80sec.php 经过location指令该请求将会交给后端的fastcgi处理nginx为其设置环境变量SCRIPT_FILENAME内容为/scripts/80sec.jpg/80sec.php 而在其他的webserver如lighttpd当中我们发现其中的SCRIPT_FILENAME被正确的设置为/scripts/80sec.jpg 所以不存在此问题。 后端的fastcgi在接受到该选项时会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字查找的方式也是查看文件是否存在这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为/scripts/80sec.jpg和80sec.php 最后以/scripts/80sec.jpg作为此次请求需要执行的脚本攻击者就可以实现让nginx以php来解析任何类型的文件了。 POC 访问一个nginx来支持php的站点在一个任何资源的文件如robots.txt后面加上/80sec.php这个时候你可以看到如下的区别 访问http://www.80sec.com/robots.txtHTTP/1.1 200 OK Server: nginx/0.6.32 Date: Thu, 20 May 2010 10:05:30 GMT Content-Type: text/plain Content-Length: 18 Last-Modified: Thu, 20 May 2010 06:26:34 GMT Connection: keep-alive Keep-Alive: timeout20 Accept-Ranges: bytes 访问访问http://www.80sec.com/robots.txt/80sec.phpHTTP/1.1 200 OK Server: nginx/0.6.32 Date: Thu, 20 May 2010 10:06:49 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive Keep-Alive: timeout20 X-Powered-By: PHP/5.2.6 其中的Content-Type的变化说明了后端负责解析的变化该站点就可能存在漏洞。 漏洞厂商http://www.nginx.org 解决方案 我们已经尝试联系官方但是此前你可以通过以下的方式来减少损失关闭cgi.fix_pathinfo为0 或者if ( $fastcgi_script_name ~ ..*/.*php ) { return 403; } PS: 鸣谢laruence大牛在分析过程中给的帮助
http://www.w-s-a.com/news/841462/

相关文章:

  • 新乡网站建设新乡长沙本地论坛有哪些
  • 潍坊中企动力做的网站怎么样wordpress接入微博
  • 网站开发者所有权归属网站项目建设的必要性
  • 菜鸟网站编程广州网站设计权威乐云践新
  • 网站做接口到app 价格大地资源免费视频观看
  • 怎么给钓鱼网站做防红网站建设相关的
  • 教育培训的网站建设湖南网站建设小公司
  • 福建南平网站建设创意交易平台网
  • 做直播网站要哪些技术内容营销理论
  • 价格划算的网站开发怎么找有赞做网站
  • 做网站店铺图片用什么软件网络营销方案格式
  • 做外贸要自己建网站吗有效的网络营销方式
  • 精通网站开发书籍做网站获取手机号码
  • 论坛做视频网站有哪些济南新站seo外包
  • 哪类型网站容易做冷水滩做微网站
  • 搭建企业网站流程保定徐水网站建设
  • 建设单位到江川区住房和城乡建设局网站伦敦 wordpress 设计
  • 响应式网站的服务麦德龙网站建设目标
  • 做国外单的网站叫什么海南省海口市网站建设
  • 杭州响应式网站案例wordpress5.2.2
  • 网站建设运营维护合同wordpress资源搜索插件
  • 国外网站流量查询东莞网站建设教程
  • 餐饮类网站建设达到的作用东莞工程建设交易中心网
  • 网站设计 知识产权湖北网站建设xiduyun
  • 猫咪网站模版下载中国风 古典 红色 网站源代码
  • 个人网站备案模板制作网站首页
  • 潍坊正规建设网站网站建设设计作业
  • 推荐一下网站谢谢辽宁住房城乡建设部官方网站
  • 网站文件大小英选 网站开发
  • 济南建网站哪家好wordpress编辑器排行