nginx nginx正则表达式匹配匹配

Nginx配置指令location匹配符优先级和安全问题
转载 & & 作者:
使用nginx 很久了,它的性能高,稳定性表现也很好,得到了很多人的认可。特别是它的配置,有点像写程序一样,每行命令结尾一个&;&号,语句块用&{}&括起来。 配制好,直接nginx -t 检查配制情况,配制成功,直接运行:service nginx reload .服务器没有任何宕机情况下,实现平稳修改配置
最近一直在做location 配置,遇到优先级别问题(如果配置不当可能存在安全隐患哦),以下是个人学习一点体会。
一、 location 的匹配符1.等于匹配符:=等于匹配符就是等号,特点可以概括为两点:精确匹配不支持正则表达式2.空匹配符空匹配符的特点是:匹配以指定模式开始的 URI不支持正则表达式3.正则匹配符:~正则匹配符是可以使用正则表达式的匹配符。不过这里要强调的是,一般来说~是指:区分大小写的正则匹配而~*表示:不区分大小写的正则匹配但是对于一些对大小写不敏感的操作系统,这两者没有区别。另外一个就是^~,其表示以指定模式开始的正则匹配。
4.内部访问符:@一般用于错误页面等,这个暂不讨论。
二、匹配符优先级1.=2.空匹配符,满足精确匹配时3.^~4.~或~*5.空匹配符,满足以指定模式开始时的匹配时这样说比较抽象,我们来看例子吧。
2.1 等于匹配符与精确匹配时的空匹配符
看下面的例子(用到我们此前一起完成的Hello World模块): 代码如下:location /poechant {&&& hello_world no1;}
location = /poechant {&&& hello_world no2;}如果我们的请求是http://my.domian/poechant,则我们发现两个location都与请求的 URI 匹配,这时根据我们的优先级顺序,第一个是精确匹配时的空匹配符,第二个是等于匹配符,所以第二个的优先级高,也就是应该输出:
hello_world, no2同时也说明 Nginx 的 locatoin 不是按照配置文件中的书写顺序来匹配的。
2.2 精确匹配时的空匹配符与正则匹配的^~
下面这个例子中,两者开始都精确匹配了,连这个正则匹配都是精确匹配。 代码如下:location ^~ ^/poechant$ {&&& hello_world no1;}
location /poechant {&&& hello_world no2;}匹配哪一个?你测试一下,会得到:
hello_world, no2与我们上面说的优先级顺序相吻合。2.3 其他匹配优先级比较的实例略
三、实战经验总结
1.location 匹配的优先级(来自实践总结中)(location =) & (location 完整路径 &) &(location ^~ 路径) &(location ~* 正则) &(location 路径)只要匹配到,其它的都会忽略,然后返回到改匹配。用以下例子来测试:
代码如下: #1&&& location / {&& return 500;}#2location /a/ {&&& return 404;}#3location ~* \.jpg$ {&&& return 403;}#4location ^~ /a/ {&&& return 402;}#5location& /a/1.jpg {&&& return 401;}#6location = /a/1.jpg {&&& return 400;}
说明:测试的时候,先要将#2全部注释掉,不然会认为#2 与#4 完全一样。会提示:重复配置,提示如下 代码如下:D:\nginx-0.8.7&nginx -s reload[emerg]: duplicate location "/a/" in D:\nginx-0.8.7/conf/nginx.conf:53
浏览测试:每次都是访问:http://localhost:9999/a/1.jpg (在windows 安装测试,然后端口是9999) 文件a/1.jpg 根本不存在。关键是测试看页面返回情况。
a.用上面的配置请求后的结果
代码如下:<div class="codebody" id="code7 Bad Request--------------------------------------------------------------------------------nginx/0.8.7从测试中可以看到,优先级最高的是:= 号。 它会最先匹配到。b.接下来我们 屏蔽掉 #6 如下: 代码如下:#6#&&& location = /a/1.jpg {#&&&&&&& return 400;#&&& }
然后重载配置:D:\nginx-0.8.7& nginx -s reload& 并访问:http://localhost:9999/a/1.jpg ,返回以下结果: 代码如下:401 Authorization Required--------------------------------------------------------------------------------nginx/0.8.7
结论:从这个测试发现,没有“=”情况下,location 后面直接接完整路径是优先匹配。 通过测试发现,如果将:location/a/1.jpg&& 改成:location /a/1\.jpg会出现意外情况,直接出现是:return 402.& 从这一点,可以推测到nginx 匹配优先是:网站路径,并且不带正则表达式的优先。
c.同理测试 屏蔽掉 #5 如下:注释及重新加载同上.访问:http://localhost:9999/a/1.jpg 返回如下结果。 代码如下:402 Payment Required--------------------------------------------------------------------------------nginx/0.8.7
结论:通过这个测试可以得出:location ^~ 优先级 高于 location ~* 优先级 ,其中:^~ 主要后面接路径。
c.同理测试 屏蔽掉 #4 如下:注释及重新加载同上.访问:http://localhost:9999/a/1.jpg 返回如下结果。 代码如下:403 Forbidden--------------------------------------------------------------------------------nginx/0.8.7结论:从以上比较得到,正则优先 未带任何匹配符的路径匹配
d.同理测试 屏蔽掉 #3 如下:注释及重新加载同上. 并且去掉#2 的注释“#”访问:http://localhost:9999/a/1.jpg 返回如下结果。 代码如下:<div class="codebody" id="code1 Not Found--------------------------------------------------------------------------------nginx/0.8.7结论:比较有意思是:/a/ 与 /& 应该是 同种类型的匹配表达式, 可以从中得到,该匹配顺序是,将路径从右匹配, 可以推测形如逐个字符,那个先匹配到,就是那个优先。 因此得到是:/a/ 优先于 / .
以上测试,是我测试结果,优先级别以以上规律。 在实际我们书写中,经常会犯错误。 还记得前段时间:80后安全团队曝nginx漏洞 其实,个人认为不能算是nginx 漏洞,只是,我们不了解nginx 配制规则,而出现一个配置上面致命漏洞而已。 其实,通过上面优先级,我们在配置时候可能也一样经常犯一个致命错误。 代码如下:#以下是随便写例子,个人可能各不相同#假设站点在:/home/www/html/目录下,所有的php 及上传文件都在这个目录下面。location ~* \.php$ {&&& proxy_pass http://www.a. }
location& /upload/ {&&& alias&& /home/www/html/upload/;}
而且,这个upload 目录,是静态目录,我们想法是下面所有文件是不能够执行的,包括php文件。如果有用户访问:http://www.a.com/upload/1.css , 会直接显示该css, 但是,如果有用户访问:http://www.a.com/upload/1.php& 类似文件,正如上面所说,实际匹配到:~* \.php$& 了。 upload 下面是执行了。从这个里面,我们发现一个问题,实际没有达到我们要求。 静态目录下面的文件一样执行了。 这下比较麻烦了。 一旦出现个什么上存漏洞的,别人上存了一个php,我们还以为,我们配置是ok的。 觉得很安全,缺在不知不觉中被别人打开一扇门。
那么我们怎么样修改呢?
代码如下:location ~* \.php$ {&&& proxy_pass http://www.a. }location ^~ /upload/ {&&& alias&& /home/www/html/upload/;}
对,就是必须用:"^~" ,这样是不是就已经安全了呢。 如果你再访问下:http://www.a.com/upload/1.php& 你会发现,这段代码源码显示出来了。 这个其实对于我们而言也是不想见到了。 一段显示源码,在各个搜索引擎,很容易通过所有特殊关键字,搜索到改文件的。那么我们该怎么样配置安全的上存目录呢? 对,你想到了:限制允许的特殊文件类型。 代码如下:location ~* \.php$ {&&& proxy_pass http://www.a. }
location ^~ /upload/ {  if ($request_filename ! ~* \.(jpg|jpeg|gif|png|swf|zip|rar|txt)$) {  return 403;&&& }&&& alias&& /home/www/html/upload/;}
只要不是满足上面扩展名文件,就自动提示:403 不能访问,有可以避免源代码显示。刚才从匹配结果已经知道了,同级不带任何匹配符的,是以右为准匹配。 那么,如果都用正则表达式,以什么方式匹配呢?测试如下:(新建配置文件,server 包含) 代码如下:&&& location ~* \.jpg$ {&&&&&&&&&&& return 402;&&& }
&&& location ~* 1\.jpg$ {&&&&&&&&&&& return 403;&&& }
结果如下:
代码如下:402 Payment Required--------------------------------------------------------------------------------nginx/0.8.7
看来是返回的是:402 上面一个呢。 按理论说,1.jpg 配置 比 .jpg 更准确,看来跟上面说的顺序不同,那它会不会是那个在前以那个匹配呢? 我们再测试下: 代码如下:location ~* 1\.jpg$ {&&&&&&&&&&& return 403;&&& }
&&& location ~* \.jpg$ {&&&&&&&&&&& return 402;&&& }
返回结果是:
代码如下:403 Forbidden--------------------------------------------------------------------------------nginx/0.8.7
哈哈,恰好相反,看来我的推断是正确的,如果都是正则,都能够匹配,以配置文件出现顺序来,谁在前谁优先。 一口气说了,不知道朋友你,明白我的思路吗?这样的比较会很多很多,大家可以逐一测试。 熟悉location 配置,对于熟练运用nginx 是一个必备基础。 因为nginx 太灵活,也太流行了。上面的问题,也许朋友你,会遇到。希望对你有帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具Nginx日志文件的正则表达式解析 | LinuxHub
Nginx日志文件的正则表达式解析
1.日志格式
'$http_host $server_addr $remote_addr "$http_x_forwarded_for" [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';
'$http_host $server_addr $remote_addr "$http_x_forwarded_for" [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';
2.日志文件
www.linuxhub.cn 192.168.60.74 192.168.60.59 "113.105.222.200, 192.168.62.184" [14/Mar/:00 +0800] "GET /hello.php HTTP/1.0" 200 2146 "http://www.ddd.cn/test9.php" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/ Firefox/52.0" 0.001 0.000
www.linuxhub.cn 192.168.60.74 192.168.60.59 "113.105.222.200, 192.168.62.184" [14/Mar/2017:10:27:00 +0800] "GET /hello.php HTTP/1.0" 200 2146 "http://www.ddd.cn/test9.php" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/ Firefox/52.0" 0.001 0.000
3.正则表达式匹配对应Nginx的字段列介绍
#匹配 $http_host
(\d+\.\d+\.\d+\.\d+)
#匹配 $server_addr,$remote_addr
(\"\d+\.\d+\.\d+\.\d+\,\s\d+\.\d+\.\d+\.\d+\"|\"\d+\.\d+\.\d+\.\d+\") #匹配 "$http_x_forwarded_for"
(\[[^\[\]]+\])
#匹配[$time_local]
(\"(?:[^"]|\")+|-\")
#匹配"$request","$http_referer","$http_user_agent"
#匹配$status
#匹配$body_bytes_sent
(\d*\.\d*|\-)
#匹配$request_time,$upstream_response_time'
#匹配每行数据的开头
#匹配每行数据的结局
12345678910
([^\s]*)&&&&&&&&&&&&&&#匹配 $http_host(\d+\.\d+\.\d+\.\d+)&&#匹配 $server_addr,$remote_addr(\"\d+\.\d+\.\d+\.\d+\,\s\d+\.\d+\.\d+\.\d+\"|\"\d+\.\d+\.\d+\.\d+\") #匹配 "$http_x_forwarded_for"(\[[^\[\]]+\])&&&& #匹配[$time_local](\"(?:[^"]|\")+|-\")&& #匹配"$request","$http_referer","$http_user_agent"(\d{3})&&&&&&&&&&&&#匹配$status (\d+|-)&&&&&&&&&&&&#匹配$body_bytes_sent(\d*\.\d*|\-)&&&&&&#匹配$request_time,$upstream_response_time'^&&&&&&&&&&&&&&&&&&#匹配每行数据的开头$&&&&&&&&&&&&&&&&&&#匹配每行数据的结局
4.完整正则表达式
^([^\s]*)\s(\d+\.\d+\.\d+\.\d+)\s(\d+\.\d+\.\d+\.\d+)\s(\"\d+\.\d+\.\d+\.\d+\,\s\d+\.\d+\.\d+\.\d+\"|\"\d+\.\d+\.\d+\.\d+\")\s(\[[^\[\]]+\])\s(\"(?:[^"]|\")+|-\")\s(\d{3})\s(\d+|-)\s(\"(?:[^"]|\")+|-\")\s(\"(?:[^"]|\")+|-\")\s(\d*\.\d*|\-)\s(\d*\.\d*|\-)$
^([^\s]*)\s(\d+\.\d+\.\d+\.\d+)\s(\d+\.\d+\.\d+\.\d+)\s(\"\d+\.\d+\.\d+\.\d+\,\s\d+\.\d+\.\d+\.\d+\"|\"\d+\.\d+\.\d+\.\d+\")\s(\[[^\[\]]+\])\s(\"(?:[^"]|\")+|-\")\s(\d{3})\s(\d+|-)\s(\"(?:[^"]|\")+|-\")\s(\"(?:[^"]|\")+|-\")\s(\d*\.\d*|\-)\s(\d*\.\d*|\-)$
5.日志匹配效果
【上一篇】
【下一篇】
最新文章热评文章随机文章
&&&微信扫码赞助.一个简单的正则表达式应用,正则匹配选出XPath表达式
凡事从积极的态度做起
发布时间: 14:37:21
需求是:一个字符串,中间包含XPath,XPath 使用&#8220;{&#8221;和&#8220;}&#8221; ,即{XPath1}xxx{XPath2}.需要取出XPath ,并且在一个XML文件中间计算XPath表达式的值。显然需要用到正则表达式:代码如下:
&static&void&Main(string[]&args)&&&&&&&&{&&&&&&&&&&&&String&inputString&=&"{/root/ID}:{/root/Name}";&&//使用{}为转义&&&&&&&&&&&&&&&&&&&&&&&Regex&r;&&&&&&&&&&&&Match&m;&&&&&&&&&&&&r&=&new&Regex("(?:{(?&1&[^}]*)})",&&&&&&&&&&&&&&&&RegexOptions.IgnoreCase&|&RegexOptions.Compiled);&&&&&&&&&&&&for&(m&=&r.Match(inputString);&m.S&m&=&m.NextMatch())&&&&&&&&&&&&{&&&&&&&&&&&&&&&&Console.WriteLine("Found&matchs&:&"&+&m.Groups[1]&+&"&at&"&&&&&&&&&&&&&&&&&&&&+&m.Groups[1].Index);&&&&&&&&&&&&}&&&&&&&&}
运行结果如下:有待改进的地方:这是一个使用单个字符{和}来分隔的,如果要是使用多个字符,比如&XPath&/root/ID&/XPath&,不知道该如何写?我看到这里好像有不少正则表达式的高手,不妨教教我,呵呵。为了满足需求,我们后来使用了正则表达式另外一个好用的功能:Split
只要使用这个就可以把字符串拆成一个字符数组:string[] sXPath = r.Split(inputString);
并且,所有的偶数位置的就是匹配出来的,就算2个表达式之间没有任何字符,也会在中间插入一个空的字符占位,这样,只要计算偶数位置的XPath就好了。看看数组里面的内容:
来源:http://www.cnblogs.com/cleo/archive//363622.html内置对象 ngx.re
正则在 nginx.conf 文件中错误的使用方法:
# nginx.conf
content_by_lua '
local regex = "\d+"
-- THIS IS WRONG!!
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
# evaluates to "not matched!"
nginx.conf 文件中正确使用方法 记得是\\\\才能转义
# nginx.conf
content_by_lua '
local regex = "\\\\d+"
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
# evaluates to "1234"
可以使用Lua中特有的 [[ 正则 ]] 定义符号
# nginx.conf
content_by_lua '
local regex = [[\\d+]]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
# evaluates to "1234"
这个自己翻译了
Here, [[\\d+]] is stripped down to [[\d+]] by the Nginx config file parser and this is processed correctly.
Note that a longer from of the long bracket, [=[...]=], may be required if the regex pattern contains [...] sequences. The [=[...]=] form may be used as the default form if desired.
# nginx.conf
content_by_lua '
local regex = [=[[0-9]+]=]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
# evaluates to "1234"
如果采用 content_by_lua_file 'test.lua'
\\\\d+ 简化为 \\d+
-- test.lua
local regex = "\\d+"
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
-- evaluates to "1234"
如果采用 content_by_lua_file 'test.lua'
[[\\d+]] 简化为
-- test.lua
local regex = [[\d+]]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
-- evaluates to "1234"
来源:http://wiki.nginx.org/HttpLuaModule
浏览: 4789 次
来自: 成都
谢谢分享,不过还是要给你个差
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'Nginx重写规则指南 &#8211; 运维生存时间
你可能喜欢
有回复时邮件通知我
12345678910
关于本站 本站以分享运维技术为主,欢迎大家参与技术分享,同时也欢迎大家吐槽,本站提供以下交流圈:QQ群①:*****(满)QQ群②:6690706 QQ群③: QQ群④:(新) 微信公众号:ttlsacom 商务合作QQ:
记住我的登录信息
点击“立即注册”转到用户注册页面。
输入用户名或电子邮箱地址,您会收到一封新密码链接的电子邮件。
用户名或电子邮件地址

我要回帖

更多关于 nginx 正则匹配数字 的文章

 

随机推荐