# Nginx 内置变量，细化规则，真实IP获取及限制连接请求

http://www.bzfshop.net/article/176.html

http://www.cr173.com/html/19761_1.html

http://blog.pixelastic.com/2013/09/27/understanding-nginx-location-blocks-rewrite-rules/

## 2.1 现在我们面对的最直接的问题就是， 经过这么多层加速，我怎么得到“最前面普通用户的 IP 地址”呢？

(这里只说明结果，不了解 Http 协议的人请自行 Google 或者 Wikipedia  http://zh.wikipedia.org/zh-cn/X-Forwarded-For  )

X-Forwarded-For :  用户IP, 代理服务器IP

X-Forwarded-For :  用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ….

## 2.3 测试、测试

Nginx 这种配置怎么测试呢？ 用 Echo 模块，如果你知道 Nginx 这个模块的话。

# 后记：

~~~~~~~~~~~~~~~~~~~~

limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s; ... server { ... location ~ .*\.(gif|png|css|js|icon)$ {
proxy_set_header Host $http_host; proxy_set_header X-Real_IP$remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~* .*\.(jpeg|jpg|JPG)$ {
proxy_set_header Host $http_host; proxy_set_header X-Real_IP$remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # image_filter resize 480 -; # image_filter_jpeg_quality 50; # image_filter_sharpen 10; # image_filter_buffer 4M; } location / { proxy_set_header Host$http_host;
proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
#limit
limit_req zone=one burst=5;
}
}

Location配置简单介绍：

= 开头表示精确匹配

^~ 开头表示uri以某个常规字符串开头，理解为匹配 url路径即可。nginx不对url做编码，因此请求为/static/20%/aa，可以被规则^~ /static/ /aa匹配到（注意是空格）。

~ 开头表示区分大小写的正则匹配

~*  开头表示不区分大小写的正则匹配

!~和!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则

/ 通用匹配，任何请求都会匹配到。

~~~~~~~~~~~~~~~~~~

 1 2 3 4 5 192.168.71.51/log.aspx –> 192.168.80.147:8338/log   192.168.71.51/do.aspx –> 192.168.80.147:8338/do   192.168.71.51/uplog.aspx –> 192.168.80.147:8338/log

……
server {
listen       6061;
server_name  192.168.71.51;

rewrite  ^(.*)(?i)uplog.aspx(.*)1log$2 break; rewrite ^(.*)(?i)log.aspx(.*)$  $1log$2  break;
rewrite  ^(.*)(?i)do.aspx(.*)1do$2 break; location / { proxy_pass http://log; proxy_redirect off; proxy_set_header Host$host;
proxy_set_header            Remote_Addr $remote_addr; proxy_set_header X-REAL-IP$remote_addr;
proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } …… 关于这里的rewrite配置主要说明以下几点： 1. rewrite用法: rewrite 正则 替换 标志位 2. 第一行配置和第二行配置顺序不能颠倒，因为nginx会从上往下依次rewrite（break在这里不起作用）； 3. （?!）表示忽略大小写匹配（网上说的是~*，但好像不起作用，我的nginx版本是1.0.12）； 4. 5. rewrite可以在server里也可以在location里，nginx会首先执行server里的rewrite，然后才会执行location，意味着location的是重写后的url,之后还会执行location里的rewrite,最后nginx还会拿结果去执行剩下的location。 关于nginx的rewrite详细用法可以参考详细参考文档：http://blog.cafeneko.info/2010/10/nginx_rewrite_note/（很详细） # 根据url参数location 实际开发中经常有根据请求参数来路由到不同请求处理者的情况，根据POST请求参数需要些nginx插件，这里主要简单介绍下如何根据GET参数来路由。 还是上面的配置文件。比如我们希望访问http://192.168.71.51:6061/do1.aspx?t=1212&c=uplog当url中的参数c为config或uplog的时候（忽略大小写）我们路由到其他地方： 首先增加一个upstream，比如： …… upstream other { server 192.168.71.41:2210; } …… 然后在location里增加如下的判断即可： …… location / { if ($query_string ~* ^(.*)c=config\b|uplog\b(.*)$){ proxy_pass http://other; } …… 关键是标红的行，$query_string表示url参数，后面是标准的正则匹配，需要的注意的是nginx中if有很多限制，语法很苛刻，具体参看上面的文档。

~~~~~~~~~~~~~~~~~~

I recently moved a cakePHP website from an Apache server to an Nginx one. I had to translate url rewriting rules from one syntax to the other, and here is what I learned.

First of all, Nginx internal logic for processing rewrite rules is not as straightforward as Apache. In Apache, rules are processed in the order in which they appear in your config file/.htaccess. In Nginx, they follow a more complex pattern.

## Initial Apache rules

First of all, here are the (simplified) set of rules I had to convert :

RewriteRule ^(css|js)/packed_(.*)1/packed/$2 [L] RewriteRule ^files/([0-9]{4})/([0-9]{2})/([0-9]{2})/([[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12})/(.*)\.(.{3,4}) /files/$1/$2/$3/$4.$6 [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$index.php?url=$1 [QSA,L]


The first rule deals with compressed css and js files. Minified css and js files are saved in /css/packed/ with a filename made of a md5 hash of the original filenames and a timestamp. So a url of/css/packed_6e4f31ffc48b6_1330851887.css will actually return the file located in/css/packed/6e4f31ffc48b6_1330851887.css

The second rule is about media files uploaded on the server. Each uploaded file is stored in the /files/ directory, in a subfolder made from the uploading date (like/files/2012/08/25/). The actual file is given a UUID when saved, and this UUID is used as its filename on disk. The rewrite rule allow the use of any custom filename when linking the file. This helps for SEO purposes as well as making it more user-friendly when we present a download to our users. So /files/2012/08/25/50483446-4b00-4d5b-8498-763e45a3e447/Subscription_form.pdf actually returns the file at/files/2012/09/06/50483446-4b00-4d5b-8498-763e45a3e447.pdf

And the last rule is the default cakePHP rewrite rule. It first checks if the requested url points to an existing directory or file, and if not dispatch it to the main entry point :index.php with the requested url as a parameter.

## Converting it to Nginx

Rewrite rules in Nginx are usually found in location blocks. There are several ways you can define a location block, and it affects the order in which the rules will be parsed.

Nginx first checks for location = blocks. Those blocks are used to catch an exact match of the requested url. Once such a block is found, its content is applied, and Nginx stops looking for more matches.

location = /my-exact-file.html {
rewrite /my-exact-file.html http://external-website.com/
}


In this example, a request for /my-exact-file.html will be redirected tohttp://external-website.com. Note that you need to repeat the url in both thelocation = block and the rewrite rule.

The location = is of very limited use as it only accepts an exact match on a string. Much more useful are the location ~ blocks that performs matches on regex (and the location ~* for a case-insensitive version).

Such blocks are tested after the location =ones, in the order they appear in your configuration file. Once a block matches, Nginx applies its content but does not stop. It keeps looking for other blocks that might match and apply them. It's up to you, in the block content, to define if the parsing should stop, using the break command.

location ~ /(css|js)/packed_ {
rewrite ^/(css|js)/packed_(.*)$/$1/packed/$2 break; } location ~ /files { rewrite ^/files/(.*)/(.*)/(.*)\.(.*)$ /files/$1/$2.$4 break; }  In the first rule I'm looking for any /css/packed_* or /js/packed_* request, and converting them to /css/packed/* or /js/packed/*. Note the use of backreferences in the rewrite using $x variables. In the second rule I simplified the original regex from Apache to catch the /2012/08/23/ in $1, the UUID in $2, the filename in $3 and the extension in $4 and rewriting the request to the correct file on disk.

Both rewrites ends with the break flag. It tells Nginx that it should stop looking for other location ~ blocks matching the requested url and just serve the file. Another useful flag is last, which tells Nginx to restart its whole url matching process from the beginning but this time using the newly rewritten url.

There is one last location block that we can use, and it's the simple location, without any prefix. These location blocks will be checked last, if no location =or location ~ had stopped the processing. They are especially good for a last "catch all" solution, and we are going to use them to dispatch urls to index.php

location / {
try_files $uri /index.php?url=$request_uri;
}


Using location /, we'll catch any remaining requests. The try_files command will test every one of its arguments in order to see if they exist on disk and serve them if they do. So in our example it will first check for the requested uri, and if such a file exists, will serve it. Otherwise it will simply dispatch it to the main index.php with the requested url as an argument and cakePHP will do the rest.

There is one last thing we must do, it's telling Nginx to pass any .php file to the PHP fastcgi. This is quite easy using a location ~ block matching any .php file. This will even apply to files served through try_files.

location ~ \.php\$ {
fastcgi_pass   127.0.0.1:9000;
fastcgi_index  index.php;
fastcgi_intercept_errors on;
include fastcgi.conf;
}


## Conclusion

Wrapping your mind around the order in which Nginx applies your rewrites is not easy at first. I hope this post helped you making sense of it.

Note that there also is the location ^~ block but I found it to be of very limited used as its behavior can be replicated with the more generic location ~ blocks.

+ 订阅