从错误代码基本可以确定跟nginx本身无关,主要是提交给php-fpm的请求未能正确反馈而导致,一般情况下,提交动态请求的时候,nginx会直接把请求转交给php-fpm,而php-fpm再分配php-cgi进程来处理相关的请求,之后再依次返回,最后由nginx把结果反馈给客户端浏览器,但我这个vps目前跑的是个纯php应用内容,实际上用户所有的请求都是php请求,有的耗费时间比较久,php-cgi进程就一直都被用满,而php-fpm本身的配置文件只打开了10组php-cgi进程,这样的话在线用户稍微多的话就会导致请求无法被正常处理而出错。
大概分析出了原因,下面做就比较容易了,首先是更改php-fpm的几处配置:
把max_children由之前的10改为现在的30,这样就可以保证有充足的php-cgi进程可以被使用;
把request_terminate_timeout由之前的0s改为60s,这样php-cgi进程处理脚本的超时时间就是60秒,可以防止进程都被挂起,提高利用效率。
接着再更改nginx的几个配置项,减少FastCGI的请求次数,尽量维持buffers不变:
fastcgi_buffers由 4 64k 改为 2 256k;
fastcgi_buffer_size由 64k 改为 128K;
fastcgi_busy_buffers_size 由 128K 改为 256K;
fastcgi_temp_file_write_size 由 128K 改为 256K。
# vi /etc/init.d/nginx 写入
#!/bin/bash
# chkconfig: - 30 21
# description: http service.
# Source Function Library
. /etc/init.d/functions
# Nginx Settings
NGINX_SBIN="/usr/local/nginx/sbin/nginx"
NGINX_CONF="/usr/local/nginx/conf/nginx.conf"
NGINX_PID="/usr/local/nginx/var/nginx.pid"
RETVAL=0
prog="Nginx"
start() {
echo -n $"Starting $prog: "
mkdir -p /dev/shm/nginx_temp
daemon $NGINX_SBIN -c $NGINX_CONF
RETVAL=$?
echo
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc -p $NGINX_PID $NGINX_SBIN -TERM
rm -rf /dev/shm/nginx_temp
RETVAL=$?
echo
return $RETVAL
}
reload(){
echo -n $"Reloading $prog: "
killproc -p $NGINX_PID $NGINX_SBIN -HUP
RETVAL=$?
echo
return $RETVAL
}
restart(){
stop
start
}
configtest(){
$NGINX_SBIN -c $NGINX_CONF -t
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
restart
;;
configtest)
configtest
;;
*)
echo $"Usage: $0 {start|stop|reload|restart|configtest}"
RETVAL=1
esac
exit $RETVAL
# chmod 755 /etc/init.d/nginx
server
{
listen 80;
server_name www.aldjflas.cn;
access_log /home/logs/bbs/access.log combined buffer=32k;
error_log /home/logs/bbs/error.log warn;
index index.html index.htm index.php;
root /data/www/wwwroot/bbs;
allow 219.232.244.234;
deny all;
}
在server部分加如下代码:
server {
listen 80 default;
server_name suibian.com; #这里的域名可以乱填一个
return 444;
}
开发的人跟我说基于thinkphp框架开发的代码在apache下能用,在nginx下为什么用不了呢,总是提示404的错误,原来apache默认就支持thinkphp等所需的PATH_INFO,而nginx不可以,那么接下来,我们就配置一下nginx,让他支持PATH_INFO,我是这么做的:
1,更改php.ini
首先php.ini的配置中把
;cgi.fix_pathinfo=0 改为
cgi.fix_pathinfo=1
2,改nginx配置文件中php的location如下:
location ~ \.php {
fastcgi_pass unix:/dev/shm/php-fcgi.sock;
fastcgi_index index.php;
set $path_info "";
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
set $real_script_name $1;
set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME /data/www/wwwroot$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
include /usr/local/nginx/conf/fastcgi_params;
}
以前是这样的:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/tmp/php-fcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www/wwwroot$fastcgi_script_name;
具体请看帖子
http://mylinux.5d6d.com/viewthre ... mp;fromuid=1#pid526
漏洞介绍: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.txt
HTTP/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: timeout=20
Accept-Ranges: bytes
访问访问http://www.80sec.com/robots.txt/80sec.php
HTTP/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: timeout=20
X-Powered-By: PHP/5.2.6
其中的Content-Type的变化说明了后端负责解析的变化,该站点就可能存在漏洞。
漏洞厂商:http://www.nginx.org
解决方案:
我们已经尝试联系官方,但是此前你可以通过以下的方式来减少损失
关闭cgi.fix_pathinfo为0
或者
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}
转载至:http://www.80sec.com/nginx-securit.html
Nginx编译后就一个小文件,不带动态库,升级也可以无缝升级,并不影响访问。
首先下载Nginx:nginx-0.7.65.tar.gz
再执行 ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module ,按原来的路径配置,自己需要的包打上,基本上没啥,基本功能Nginx都自带了。
然后make,但不要install
编译完,在objs目录下有一个nginx执行文件,就是它了。
备份下原来老的nginx文件
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
在把新objs下的nginx cp到sbin下。
cp -p objs/nginx /usr/local/nginx/sbin/
nginx -t 测试下,显示通过。
//让nginx把nginx.pid改成nginx.pid.oldbin 跟着启动新的nginx,一般lnmp一键安装包安装的按下面执行命令即可。
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
//退出旧的nignx
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
升级完成!
错误信息 "proxy_pass" may not have URI part in location given by regular expression,
我的配置文件
location ~ .*\.(php|jsp|cgi)?$ {
proxy_pass http://192.168.2.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
修改为
location ~ .*\.(php|jsp|cgi)?$ {
proxy_pass http://192.168.2.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
不要加斜杠,否则就会报错。
在 nginx.conf中的server部分中添加如下代码
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip|doc|pdf|gz|bz2|jpeg|bmp|xls)$ {
valid_referers none blocked server_names *.taobao.com *.baidu.com *.google.com *.google.cn *.soso.com ; // 对这些域名的网站不进行盗链。
if ($invalid_referer) {
# rewrite ^/ http://www.52blackberry.com/403.html;
# return 403;
rewrite ^/ http://www.example.com/nophoto.gif;
}
}
其中 rewrite ^/ 后边可以是一个错误页面,如上边那一行,也可以是一个图片,如下面那个。
对于开头location 部分有的是这样的形式 location ~ .*\.(gif|jpg|png),经我验证都可以实现。
upstream bbs.aaa.cn{
server 1.2.3.1:80;
server 1.2.3.4:80;
}
server {
listen 80;
server_name bbs.aaa.cn;
location / {
proxy_pass http://bbs.aaa.cn/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# access_log /home/logs/bbs.access combined;
}
upstream blog.aaa.cn{
server 1.2.3.1:80;
server 1.2.3.4:80;
}
server {
listen 80;
server_name blog.aaa.cn;
location / {
proxy_pass http://blog.aaa.cn/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# access_log /home/logs/ss.access combined;
}
需要第三方的ngx_cache_purge模块:
wget http://labs.frickle.com/files/ngx_cache_purge-1.0.tar.gz
如果上边地址失效,可以下载这里的 http://mylinux.5d6d.com/userdirs ... he_purge-1.0.tar.gz
编译nginx时,需要加上参数
--add-module=/usr/local/src/ngx_cache_purge-1.0
nginx.conf 需要有下面参数
proxy_connect_timeout 600; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 600; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_send_timeout 600; #后端服务器数据回传时间(代理发送超时)
proxy_buffer_size 32k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 1024m; #设定缓存文件夹大小,大于这个值,将从upstream服务器传递请求,而不缓冲到磁盘
proxy_ignore_client_abort on; #不允许代理端主动关闭连接
#注:proxy_temp_path和proxy_cache_path指定的路径必须在同一分区
proxy_temp_path /cache/proxy_temp_path; 这里的/cache/proxy_temp_path 是要手动创建的,否则会报错。
#设置Web缓存区名称为cache_one,内存缓存空间大小为200MB,1天没有被访问的内容自动清除,硬盘缓存空间大小为30GB。
proxy_cache_path /cache/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
另外虚拟主机配置文件如下:
server {
listen 80;
server_name www.test.com;
location / {
proxy_pass http://192.168.1.111:8080;
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache cache_one;
proxy_cache_valid 200 304 12h;
proxy_cache_valid 301 302 1m;
proxy_cache_valid any 1m;
proxy_cache_key $host$uri$is_args$args;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
expires 12h;
}
location ~ .*\.(php|jsp|cgi)?$ {
proxy_pass http://192.168.1.111:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log /dev/null combined_realip;
}
我的需求: 当请求的目录是 /aaa/ 则把请求发送到机器a,当请求的目录为/bbb/则把请求发送到机器b,除了目录/aaa/与目录/bbb/外,其他的请求发送到机器b
我的配置文件内容为:
upstream aaa.com
{
server 192.168.111.6;
}
upstream bbb.com
{
server 192.168.111.20;
}
server {
listen 80;
server_name li.com;
location /aaa/
{
proxy_pass http://aaa.com/aaa/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /bbb/
{
proxy_pass http://bbb.com/bbb/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /
{
proxy_pass http://bbb.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}说明:
1 以上配置文件中的 aaa.com 以及 bbb.com 都是自定义的,随便写。
2 upstream 中的server 可以写多个,例如
upstream aaa.com
{
server 192.168.111.6;
server 192.168.111.4;
server 192.168.111.5;
}
3 proxy_pass http://aaa.com/aaa/ 这里必须要加这个目录,不然就访问到根目录了。
4 实际上,上述配置文件中, localtion /bbb/ 部分是可以省略掉的,因为后边的 location / 已经包含了/bbb/,所以即使我们不去定义 localtion /bbb/ 也是会访问到 bbb.com 的。
配置nginx 日志切割
修改日志格式
log_format combined_realip '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
如果,你使用了代理,那么日志格式为:
log_format combined_realip '$http_x_forwarded_for - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
下载awstats 软件
wget http://cdnetworks-kr-1.dl.source ... awstats-6.95.tar.gz
或者:http://www.ypl.cc/attachments/month_1011/awstats-6.95.tar.gz
tar zxvf awstats-6.95.tar.gz
安装 awstats
mv awstats-6.95 /usr/local/awstats
cd /usr/local/awstats/tools
创建一个新的统计
./awstats_configure.pl
-----> Check for web server install
Enter full config file path of your Web server.
Example: /etc/httpd/httpd.conf
Example: /usr/local/apache2/conf/httpd.conf
Example: c:\Program files\apache group\apache\conf\httpd.conf
Config file path ('none' to skip web server setup):
#> none #因为我们这里用的是 Nginx,所以写 none,跳过。
回车
Your web server config file(s) could not be found.
You will need to setup your web server manually to declare AWStats
script as a CGI, if you want to build reports dynamically.
See AWStats setup documentation (file docs/index.html)
-----> Update model config file '/usr/local/awstats/wwwroot/cgi-bin/awstats.model.conf'
File awstats.model.conf updated.
-----> Need to create a new config file ?
Do you want me to build a new AWStats config/profile
file (required if first install) [y/N] ?
#> y #y 创建一个新的统计配置
回车
-----> Define config file name to create
What is the name of your web site or profile analysis ?
Example: www.ypl.cc
Example: demo
Your web site, virtual server or profile name:
#> www.ypl.cc #统计网站的域名 例:
www.ypl.cc
回车 -----> Define config file path
In which directory do you plan to store your config file(s) ?
Default: /etc/awstats
Directory path to store config file(s) (Enter for default):
#>
使用默认直接回车,接下来便会出现以下的提示 ----> Add update process inside a scheduler
Sorry, configure.pl does not support automatic add to cron yet.
You can do it manually by adding the following command to your cron:
/usr/local/awstats/wwwroot/cgi-bin/awstats.pl -update -config=www.ypl.cc
#回头把该命令填入crontab 按指定时间执行
Or if you have several config files and prefer having only one command:
/usr/local/awstats/tools/awstats_updateall.pl now
Press ENTER to continue... 回车继续
A SIMPLE config file has been created: /etc/awstats/awstats.www.ypl.cc.conf
#新配置文件所在的路径
You should have a look inside to check and change manually main parameters.
You can then manually update your statistics for 'www.ypl.cc' with command:
> perl awstats.pl -update -config=www.ypl.cc
You can also build static report pages for 'www.ypl.cc' with command:
> perl awstats.pl -output=pagetype -config=www.ypl.cc
Press ENTER to finish...
~ 匹配,区分大小写
~* 不区分大小写的匹配
!~ 不匹配
!~* 不匹配
^~ 常用于location 语法中,后边是一个字符串。它的意思是,在这个字符串匹配后停止进行正则表达式的匹配。
如: location ^~ /images/,你希望对/images/这个目录进行一些特别的操作,如增加expires头,防盗链等,但是你又想把除了这个目录的图片外的所有图片只进行增加expires头的操作,这个操作可能会用到另外一个location,例如:location ~* \.(gif|jpg|jpeg)$,这样,如果有请求/images/1.jpg,nginx如何决定去进行哪个location中的操作呢?结果取决于标识符^~,如果你这样写:location /images/,这样nginx会将1.jpg匹配到location ~* \.(gif|jpg|jpeg)$这个location中,这并不是你需要的结果,而增加了^~这个标识符后,它在匹配了/images/这个字符串后就停止搜索其它带正则的location。
= 表示精确的查找地址,如location = /它只会匹配uri为/的请求,如果请求为/index.html,将查找另外的location,而不会匹配这个,当然可以写两个location,location = /和location /,这样/index.html将匹配到后者,如果你的站点对/的请求量较大,可以使用这个方法来加快请求的响应速度。
@ 表示为一个location进行命名,即自定义一个location,这个location不能被外界所访问,只能用于Nginx产生的子请求,主要为error_page和try_files。
- «
- 1
- ...
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- ...
- 63
- »