nginx是一把利刃,配置起来也有很多学问,配置不当可能对性能有一定影响,甚至导致错误,引起安全隐患。
本文对nginx的rewrite模块的last、break做个测试,使存在的性能问题和安全隐患显露出来。
功能一:用nginx的proxy模块代理一台windows的iis7
功能二:用nginx的fastcgi模块处理php脚本
架构及拓扑:
192.168.0.6:nginx+fastcgi
192.168.0.8:windows的iis7服务器
目标:
将10000以内的帖子通过nginx转发到iis7上,将10000及以上的帖子转给nginx本机的fastcgi模块处理
数据:
iis7的根目录有post目录和其下的9999个htm文件,如:1.htm.......9999.htm,内容就是文件的绝对路径。
nginx的根目录是/usr/local/nginx/html,其下有php脚本文件post.php,内容如下:
<?php
$id = $_GET['id'];
print "id = [$id]";
nginx配置文件内容:
server {
listen 80;
server_name localhost;
root html;
location ~* "/\d{1,4}\.htm$" {
proxy_pass http://192.168.0.8;
rewrite /(\d+\.htm)$ /post/$1 last;
}
location ~* "/\d{5,}\.htm$" {
rewrite "/(\d{5,})\.htm" /post.php?id=$1 last;
fastcgi_pass 127.0.0.1:9000;
include fastcgi.conf;
location / {
}
现在我们访问1w以内的帖子:
[root@demo conf]# curl 192.168.0.6/1.htm
<html>
<head><title>500 Internal Server Error</title></head>
<body bgcolor="white">
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx/1.2.5</center>
</body>
</html>看,发生了500 内部服务器错误,看日志可以确定是内部循环重定向错误,即rewrite死循环。因为这里在location里使用了last,第一次请求的uri是/1.htm匹配<location ~* "/\d{1,4}\.htm$">,rewrite后的uri为/post/1.htm,因为是last所以会再次对server发起请求,再一次匹配了<location ~* "/\d{1,4}\.htm$">,继续反复循环下去,直到达到服务器定义的10次,才终止,并返回500内部服务器错误
解决:将last换成break
现在我们访问1w以外的帖子:
[root@demo conf]# curl 192.168.0.6/10000.htm
print "id = [$id]";看到了吧,多危险啊,php脚本代码暴露了,如果用浏览器访问会下载这个php处理脚本文件,即10000.htm。这是什么原因导致的呢?这是因为在location里使用了last造成的,具体是这样的:第一次请求的uri是/10000.htm,匹配<location ~* "/\d{5,}\.htm$">,rewrite后的uri为/post.php?id=10000,因为是last所以会再次对server发起请求,这次匹配不上前面两个location了,只能匹配最后的一个location /了,因为location /的根目录在/usr/local/nginx/html,而且是对post.php文件的请求,就处理这个请求,将post.php文件的内容作为10000.htm的内容返回,由于这个不是正常的htm文件,就用默认的default_type application/octet-stream处理,就是下载了。如果将默认类型换成text/plain,即文本文件的类型,就不会提示下载了,直接显示出来了。一样危险!!!
总结:last会对server再次发起请求,而break不会,因此看需求,如果rewrite后还需要再次请求完成正确的匹配,那就用last。