跳转至

Nginx location指令


2013-05-10 by dongnan

举个栗子

来看一个location配置示例:

server {
    #... 其它配置项省略

    # 匹配正则    
    location ~* /(fashion|life|men)/pic/ {  
      rewrite ^/ http://blog.test.com/ permanent;
    }

    # 匹配字符串
    location ^~ /fashion/pic/ {  
      proxy_pass http://blog.test.com/;
    }
}

测试结果:

curl -IL http://192.168.57.75/fashion/pic/
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 14 Aug 2012 07:56:10 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.6
X-Pingback: http://blog.test.com/xmlrpc.php

从配置文件看这两个 location 都能匹配/fashion/pic/,不同的是前者使用的是正则匹配,而后者是字符串匹配。

  • 这里涉及到匹配顺序问题,从服务器返回的结果可以知道 nginx选择了匹配字符串,
  • 这是因为使用了^~标识符字符串匹配后不再检查正则,也就是只使用字符串匹配结果。

location 指令

语法:location [=|^~|~|~*|@] /uri/ { … }
默认值:no
使用字段:server
功能: 根据URI的不同需求进行配置,可以使用字符串与正则表达式匹配。
如果要使用正则表达式,你必须指定下列前缀:
~* 不区分大小写。
~ 区分大小写。

匹配规则

要确定该指令匹配特定的查询,程序将首先对字符串进行匹配,字符串匹配将作为查询的开始,最确切的匹配将被使用。 然后正则表达式的匹配查询开始,匹配查询的第一个正则表达式找到后会停止搜索,如果没有找到正则表达式,将使用字符串的搜索结果。

  • 可以使用^~标记禁止在字符串匹配后检查正则表达式,如果最确切的匹配location有这个标记,那么正则表达式不会被检查。
  • 使用=标记可以在URI和location之间定义精确的匹配,在精确匹配完成后并不进行额外的搜索,例如有请求/发生,则可以使用location = /来加速这个处理。
  • 即使没有=^~标记,精确的匹配location在找到后同样会停止查询。

匹配顺序

  • 前缀=表示精确匹配查询,如果找到立即停止查询。
  • 使用标准字符串,如果匹配到使用^~前缀则停止查询。
  • 正则表达式按照他们在配置文件中定义的顺序。
  • 如果第三条产生一个匹配,这个匹配将被使用,否则将使用第二条的匹配。

匹配示例

location  = / {
  # 只匹配 / 的查询.
  [ configuration A ]
}
location  / {
  # 匹配任何以 / 开始的查询,但是正则表达式与一些较长的字符串将被首先匹配。
  [ configuration B ]
}
location ^~ /images/ {
  # 匹配任何以 /images/ 开始的查询并且停止搜索,不检查正则表达式。
  [ configuration C ]
}
location ~* \.(gif|jpg|jpeg)$ {
  # 匹配任何以gif, jpg, or jpeg结尾的文件,但是所有 /images/ 目录的请求将在Configuration C中处理。
  [ configuration D ]
}

各请求的处理如下例:

  • / -> configuration A
  • /documents/document.html -> configuration B
  • /images/1.gif -> configuration C
  • /documents/1.jpg -> configuration D

注意,你可以以任何顺序定义这4个配置并且匹配结果是相同的,但当使用嵌套的location结构时可能会意外的结果。

常用的location

PHP-FPM + Nginx 服务器:

server {
    #... 其它配置项省略

    # 使用正则匹配
    location ~ .*\.(php|php5)?$ {
      fastcgi_pass 127.0.0.1:9000;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
    }

    # 使用正则匹配
    location ~ \.(gif|jpg|jpeg|png|bmp|swf)$ {
      expires      30d;
    }

    # 使用正则匹配
    location ~ \.(js|css|htm|html|shtml)$ {
      expires      60m;
    }

    # 使用字符串+正则匹配
    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
      proxy_pass http://www.test.com/images/;
    }

    # 使用字符串匹配不再检查正则
    location ^~ /bao/m/ {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
      proxy_pass http://m.bao.test.com/images/;
    }
}

仅匹配字符串不匹配正则表达式

图片由php程序输出,直接访问nginx中的图片返回404状态。

配置文件

location ^~ /upload/ {
      return 404;
 }

使用^~标记禁止在字符串匹配后检查正则表达式,如果最确切的匹配location有这个标记,那么正则表达式不会被检查。

验证

跳转到404页面:

curl -IL -k -H "Host:trade.ywwd.net" https://server_ip/upload/qiyepack/000/00/00/06/zzjgz.jpg

HTTP/1.1 302 Found
Date: Wed, 16 Dec 2015 08:20:02 GMT
Content-Type: text/html
Content-Length: 235
Location: https://ywwd.net/404.html

程序生成的图片

URL:https://trade.ywwd.net/XXX/qyzzimg?path=qiyepack/000/00/00/06/yyzz.jpg

这种方式可能带来权限控制问题,造成的平行越权漏洞,导致信息泄露,例如:

/qyzzimg?path=../../../../../../../etc/passwd

解决方法是需要判断 path=something... 传递的参数是否合法。

回到页面顶部