Tag Archives: nginx

nginx php 错误配置导致安全漏洞

后知后觉发现了此文 Setting up PHP-FastCGI and nginx? Don’t trust the tutorials: check your configuration! 基本上是说,网上的大部分 nginx + php 配置教程中有一个错误,导致 php 会试图执行非 php 文件,甚至是用户上传的图片。

事实上看到此漏洞的描述我已经立刻想到问题之所在了,的确,之前我写的那篇配置笔记也是有此问题的。基本原理就是 nginx 配置中有这么一段

location ~ .*.php5?$ {
        include fastcgi_params;
        root /var/host/phpMyAdmin;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php_fcgi.sock;
        fastcgi_index index.php;
    }

凡是以 .php 或者 .php5 结尾的 uri 都会被交给 php 处理,于是类似于 user.jpg/aaa.php 也会交给 php 处理,于是 user.jpg 就被当成 php 代码给执行了。

解决此问题的方法有好几种,codex.wordpress.com 上面提供的一种方式是如下修改 nginx 中有关 php 的配置。不过如果 nginx 和 php 不运行在同一台机器上时,此方法无效。

location ~ \.php$ {
	# Zero-day exploit defense.
	# http://forum.nginx.org/read.php?2,88845,page=3
	# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
	# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.
	try_files $uri =404;

	fastcgi_split_path_info ^(.+\.php)(/.+)$;
	include fastcgi_params;
	fastcgi_index index.php;
	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#	fastcgi_intercept_errors on;
	fastcgi_pass php;
}

nginx 的 wordpress rewrite 规则

我目前在用的 nginx 设置就是这个,已经包含了 WP Super Cache 的 rewrite rule,大部分内容是我搜来的,很不幸暂时找不到来自哪里了…… 其实网上类似的内容太多了~

server {
  listen 80;
  server_name www.example.net;

  location / {
    index index.php;
    root /var/host/wordpress;
    gzip_static on;

    if (-f $request_filename) {
      break;
    }

    set $supercache_file '';
    set $supercache_uri $request_uri;

    if ($request_method = POST) {
      set $supercache_uri '';
    }

    if ($query_string) {
      set $supercache_uri '';
    }

    if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) {
      set $supercache_uri '';
    }

    if ($supercache_uri ~ ^(.+)$) {
      set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html;
    }

    if (-f $document_root$supercache_file) {
      rewrite ^(.*)$ $supercache_file break;
    }

    if (!-e $request_filename) {
      rewrite . /index.php last;
    }
  }

  location ~ .*.php5?$ {
    include fastcgi_params;
    root /var/host/wordpress;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/var/run/php_fcgi.sock;
    fastcgi_index index.php;
  }
}

[配置笔记]CentOS + nginx + PHP

之前的这篇文章似乎是挖了个坑一直没填,然而每每出现这种情况的时候,都会发现还偏偏总有人通过 Google 搜索过来……一定让不少人失望了,真是过意不去~于是这次重新写一篇,但愿能把坑填上……

和上次略有不同,这次 Linux 发行版是用的 CentOS,因为最近一段时间来其实我接触最多的还是 RHEL,所以就不写 Ubuntu 了。MySQL 也不在本文叙述范围之内,我实际应用的时候是直接 yum install mysql-server 装的,没有什么好说的。

nginx 用了 0.7.x 开发版。php 当然是通过 fastcgi 运行,不过没有用从 lighttpd 里分离出来的 spawn-fcgi,而是用了 php-fpm 这个补丁。
Continue reading

校内出错的那几分钟

貌似最近通过搜索 校内 502 Bad Gateway 来到此页面的同学越来越多了。简单明了的告诉你,这是校内的服务器不行了,不是用户的问题,也许等等就好了,如果等等也不好……那……校内,你倒底行不行啊? — Updated on 2 Jun, 2009

晚上开着校内的时候,突然弹了个框出来,说是 502 Bad Gateway,然后按刷新就看不到校内了,看到了……我熟悉的 nginx 502 错误页面~ 当时就想,校内又出错了啊,还是 nginx,可以研究一下哈。

立刻问了一下小野猪,他说校内是可以上的,就是有点慢。而我却是立刻返回 502 页面,服务器 nginx 0.6.32,校内正常的服务器应该是 resin 才对。两个人访问结果不同的情况,除了我 RP 差之外,还是有其他原因的,我猜就是我这两天碰巧在搞得 DNS Round Robin

$ nslookup xiaonei.com
Server:        208.67.222.222
Address:    208.67.222.222#53

Non-authoritative answer:
Name:    xiaonei.com
Address: 211.157.20.6
Name:    xiaonei.com
Address: 211.157.20.3
Name:    xiaonei.com
Address: 211.157.20.2

和 google.com 一样,xiaonei.com 解析的时候也会有三个 IP,DNS Server 会在每次回复的时候改变顺序,不过究竟用哪个 IP 还是客户端说了算,有时候 DNS Cache 久了,你可能长时间使用一个 IP 访问。不过这个在减低服务器负载上还是有效果的,因为人多了之后,还是大致上 IP 均分的。

DNS Round Robin 的实现是很容易,然后也有很大的弊端:由于 DNS propagation delay 通常要很久,几十分钟到几个小时甚至几天都有可能,所以如果一个服务器要临时下线的话,客户端是不知道这一情况的,还是会继续访问那个 IP,并不会被自动分流到好得 IP 上去。当然还是可以在 router/firewall 上把下线的 IP 分给某一台在线的服务器,不过要做到完全平滑过渡似乎是不大可能了(你至少得把所有 TCP 连接给断开才能改吧?)

回到校内这个问题上来…… 我试着反复清空 DNS cache,情况是,有一个 IP 返回 502,两个 IP 是好的,之后似乎情况又有变化,甚至有一段时间有两个 IP 是 502…… 于是猜测校内在重启 back-end server,但由于 DNS round robin 并不能解决平滑过渡的问题,即使是三只服务器依次重启,我还是遇到了出错的页面。

至于 nginx 的出现,我并不觉得惊讶,因为 nginx 的优秀性能总能让用它的人从中受益,校内可能省了点硬件的钱,我们则得到更好的用户体验~ 对于校内背后的服务器结构,我依旧迷惑。最外层是 squid,直接打 IP 就能看出来,而且即使 nginx 报 502 的时候,同一个 IP 还是能看到 squid,所以 squid 是最外层。然后是 nginx,可是再里面呢?resin?如果用 nginx 做 reverse proxy 的话,他的 server tag 是不会变的,永远都会自称 nginx,这个和 Apache 不同, Apache mod_proxy 做 reverse proxy 的话,server tag 是显示的 back-end server 的 server tag。于是迷惑了,更加奇怪的是,既然用到了 nginx,为什么校内的静态图片却是在 Apache 上呢…… 也许要等下次,下下次,不知道多少次校内出错的时候才能猜出来了~~

中国人只会山寨?

开始有个习惯每个月看看 NetCraft 的 Web Server Survey,了解一下最新的服务器发展。通常总是那么几个产品上下沉浮,感觉也就和看浏览器市场占有率差不多。却没有浏览器竞争来的激烈,服务器排名也没那么好看。

和浏览器不同的是,服务器可以是独家享用的,Google 的 GFE 就是占据 第三的宝座,却不能让外人尝鲜。这也说明 Google 的强大,看了报告总是想,他一家公司做的服务器,自家用,竟然能排到第三

然而,2月的报告出来看了感觉很雷……真的,真的是雷了。Google 的第三没了……给腾讯抢走了……竟然,是腾讯!仔细看看倒也觉得不出奇了,腾讯出了个自称是 QZHTTP 的 Web Server,然后把旗下 QZone 的网站都给换上了 QZHTTP。NetCraft 的统计是按照域名算的,而 QZone 是无数子域名的泛解析,我不知道是不是每个 QQ 用户都会自动拥有 QZone 的子域名,反正这一下子就是来了2千万个域名,nginx 说是发展很快,出道这几年也才有3百万个站点……

于是大家的好奇心也就不在这“为啥有这么多站点”上面,而是,QZHTTP 到底是个什么东西?略加搜索,在某外国友人的博客找到此文

外国人也是关心 QZHTTP 的,不过他们会比我们多想一点,就是,怎么是“中国人”做了个牛逼服务器出来?于是激烈的讨论也就展开了。所谓激烈,自然是有各种观点,基本分了这么几类:

  • 技术派:QZHTTP 不知道用了啥技术,也许就是换了名字的 Apache?IIS都有可能啊。拿各种软件测一下,好像是 thttpd?不过在没有可靠信息的情况下,也不能乱说。我宁愿知道更多有关的信息啊。
  • 中国人爱山寨派:QZHTTP,呸!明显是山寨的 Apache 啊,中国人 Windows 用盗版的,迪士尼乐园有山寨的,Web Server 肯定也是假的!
  • 国货当自强派:我就是腾讯的!QZHTTP 就是我们自己写的,和 Apache 什么开源软件,通通没有关系!
  • “中国人都不行”之无逻辑派:中国人能写 Web Server?那牛奶里怎么会有三聚氰胺的?
  • “楼上某些人法盲”派:你们想什么啊,抄就抄呗,开源的 License 只规定,改了之后如果发布出去,才需要公开代码。人家只是改了自己用,给别人提供服务,那就不用公开源代码啊。那明明是合法的嘛。法盲们,回家好好看看那些 License 吧~
  • “对对!中国人都不行”之反语派:是啊是啊,中国人都不行,完全不懂创新,只会抄袭。什么指南针、印刷术、火药、造纸术,通通都是抄的。开源软件的协议里都写了嘛,本软件的代码大家随便看,随便改,就是中国人不行~

对于 QZHTTP 和相关讨论,我的观点和认识是:

  • QZHTTP 应该不是简单的 Apache 换了名字。我想腾讯没有必要这么做,因为 qq.com 还是用的 Apache,而用 Apache 不是什么丢人的事,除非腾讯玩非主流~
  • 自称来自腾讯的某人说法太过绝对了一点。has nothing to do with 说的轻松,我不否认腾讯有能力写一个自己的 Web Server,但是我觉得一个程序员在开始写 Web Server  之前没有好好研究过 Apache 或者其他优秀的开源项目就动手,是难以令人置信的。
  • 中国人的不注意知识产权以及食品安全问题,早已伤害了各国人民的感情,也许脆弱的不仅仅是我们,但最后受伤的还是我们。
  • 老祖宗创造四大发明的那个时代已经远去,要证明中国人除了山寨还是会创新,或者山寨也是另一种创新,这都得靠我们自己。

ARP 擒贼记

注意!本文涉及标题党

之前一直在做的一个 reverse proxy,在 RHEL 上用了 nginx 。基本功能是根据 cookie 做 load balance 和特定网页内容的替换。功能上是没有问题了吧,性能的话我觉得能满足公司需要,虽然看上去不是太好。

这个小项目一直是不顺利的,主要原因就是 nginx 得不到认可。基本上和每一个人说我用了什么的时候,都要先介绍 nginx。Net Craft 给的报告是不难看,好歹也算第四大应用广泛的 Web Server 了。前三是 Apache、IIS 和 GFE。Apache 做 reverse proxy 太慢,IIS 我不会用(也不知能不能做 reverse proxy),GFE 是人家的私人珍藏…… 那么用 nginx 还是有些道理的吧。

昨天,正当梁生还在质疑 nginx seems too young to be proven 的时候,我们的 server 开始变得不稳定。基本上就是好一阵坏一阵,不能用的时候错误很奇怪,不是连不到而是 connection refused。不但网页看不到,连 ssh 都连不到。连上的 ssh 也会在几分钟内断开。起先是以为网线接触不良,但是看 message.log 没有看到 eth0 down 的迹象。于是只好带着疑问下班,哦,我真不愿意看到这种情况啊。梁生会不会得意的笑,哈,我说你这 server 不行吧,too young~

我知道这个问题和 nginx 是无关的,应该是网络问题。硬件是不大会有问题的,我一直以为这还是软件的问题。不知道为啥,遇到诡异的局域网问题,我就会自然的想到 ARP。百度上搜 ARP 的结果是恐怖的,Google 上要好些,曾几何时 ARP 劫持在中国大陆的泛滥,让很多人以为这是一个病毒的名字。我是觉得处处防范的企业内部出现病毒是不大可能的,而且现在的故障不像是 ARP 劫持,倒像是……哦,谁偷了我的 IP 啊~~

Keats 给我的信息是很有用的,就是不断地 ping 那个 IP,TTL 值竟然会变,一会儿 64 一会儿 128,64的时候能连上,128就connection refused。于是问题变得清晰起来,这分明是两台机器嘛,RHEL5 的默认 TTL 是 64 的,返回 128 估计就是给某台 Windows XP 抢了 IP。于是乎,arp -a 蹲点蹲了一阵,终于让我揪出了抢我 IP 的 MAC Address~ 交给 Keats,剩下的事情,就不是我们 Team 的啦,Technical Team 的同事们加油啊,你们有什么妙招根据 MAC 地址把那台机器的主人找出来吗……

init.d script for nginx, RedHat

在RHEL 5.2上经过测试,debian/ubuntu系其实不需此脚本,因为apt源里装的已经自带了。不是我写的,我只是拿来改到能用为止…… 不过还真是找了挺久。网上流传的某些版本不如这个好~
start-stop-daemon 好像 RedHat 上也没有自带,那个就随便搜搜装一个吧。

#! /bin/sh

### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the nginx web server
# Description:       starts nginx using start-stop-daemon
### END INIT INFO


PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/nginx/sbin/nginx
NAME=nginx
DESC=nginx
PIDFILE=/usr/local/nginx/logs/nginx.pid

test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
        . /etc/default/nginx
fi

set -e

case "$1" in
  start)
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --pidfile $PIDFILE 
          --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --pidfile $PIDFILE 
          --exec $DAEMON
        echo "$NAME."
        ;;
  restart|force-reload)
        echo -n "Restarting $DESC: "
        start-stop-daemon --stop --quiet --pidfile $PIDFILE 
          --exec $DAEMON
        sleep 1
        start-stop-daemon --start --quiet --pidfile $PIDFILE 
          --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  reload)
      echo -n "Reloading $DESC configuration: "
      start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE 
        --exec $DAEMON
      echo "$NAME."
      ;;
  *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
        exit 1
        ;;
esac

exit 0

nginx, AWStats or Not?

JAWStats

虽然已经有了免费好用的 Goolge Analytics,我想还是不能放弃原始 log 的分析。于是想到了 AWStats,然而我并非一个经验丰富的 Web Master,我只是一个菜鸟……我发现我根本搞不定 perl 和 cgi 🙁 。因为 nginx 本身不支持执行 cgi,而 fcgi 似乎也配置复杂(远不如 php 的 fcgi 方便啊),于是我只能用 AWStats 生成静态页面来看,大大降低了可用度……当然,还有非常重要的一点,AWStats 生成的页面太难看了,对于我这种只是想做了看看而非实际应用的人来说,根本就是不能忍的~

于是乎,nginx, AWStats or Not?

好吧,长话短说,Yes! 最后我终于发现了 JAWStats…… 这个使用 PHP 写的,可以读取 AWStats 生成的 data,再生成更加漂亮的页面,或者那个说烂了时髦词汇—— Web 2.0/AJAX。 对我来说还有更大的意义,我不需要去搞难缠的 perl/cgi 了,在我已经配置好 php 的 nginx 上,JAWStats 只需5分钟便能安装完毕~ 然后这个界面还是挺令人满意的哈~

[配置笔记]Ubuntu + nginx + MySQL + PHP

本来想写个How-To的,但是突然觉得自己没有功力教会别人,所以就不做标题党了。配置笔记,基本上是记录给自己看得,能够给别人有所帮助就更好了~

最近不断的看到有关 nginx 的消息,基本上都是正面的,看起来性能非常好。对于性能好的东西,我通常有一种莫名的恐惧,因为这些高级货一是要用到好的硬件上,二是配置复杂,如果还有三的话,那就是我通常不需要这么高的性能。然而这次稍稍看多了些 nginx 的介绍,其实它还是轻量级的,出道也不久,却能够被不少网站重用。俄罗斯人写的程序,作者自称英文较差,不过文档却也有了多国语言版,看来这东西真是受世界各国人民的喜爱啊~

晚上不想玩WoW,就装了个虚拟机,搞了 nginx 玩玩,记录如下。 Continue reading