Nginx笔记(二)

location

语法

语法:location [=|~|~*|^~] /uri/ { … }
默认:否
上下文:server

~* : 正则表达式,不分区大小写
~  : 正则表达式,区分大小写
=  : 严格匹配
^~ : 不测试正则表达式

总结,指令按下列顺序被接受:
1. = 前缀的指令严格匹配这个查询。如果找到,停止搜索。
2. 剩下的常规字符串,长的在前。如果这个匹配使用 ^~ 前缀,搜索停止。
3. 正则表达式,按配置文件里的顺序。
4. 如果第三步产生匹配,则使用这个结果。否则使用第二步的匹配结果。

例子:

location = / {
# 只匹配 / 查询。
[ configuration A ]
}

location / {
# 匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配。
[ configuration B ]
}

location ^~ /images/ {
# 匹配任何已 /images/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
[ configuration C ]
}

location ~* \.(gif|jpg|jpeg)$ {
# 匹配任何已 gif、jpg 或 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 完整路径 ) >(location ^~ 路径) >(location ~*, ~ 正则) >(location 部分起始路径)
正则表达式根据配置文件中的前后顺序影响匹配, 前面的优先匹配. 其它则根据匹配长度来优先匹配.

匹配顺序实例

正则表达式前后顺序影响匹配

以dokuwiki为例。dokuwiki需要配置某些目录禁止访问,如果以下面的顺序,则请求 conf data 等目录下的php文件仍然会返回200,原因是优先匹配了前面的正则。如果调换位置,则禁止目录下的php文件也会返回403。

location ~ .*\.(php|php5)?$
            {
                try_files $uri =404;
                fastcgi_pass  unix:/tmp/php-cgi.sock;
                fastcgi_index index.php;
                include fcgi.conf;
            }

location ~ /(conf|data|bin|inc)/ { deny all; }

另外一种方法是使用 ^~ 前缀严格限制目录访问,可以做到被禁目录下所有文件都返回403

location ^~ /conf/ { deny all; }
location ^~ /data/ { deny all; }
location ^~ /bin/  { deny all; }
location ^~ /inc/  { deny all; }

参考:http://www.annhe.net/article-2415.html

防盗链实例

server {
        listen 80;
        server_name b.lab1;
        root /home/wwwroot/b.lab1;

        location ~* \.(jpg|png|gif)$ {
                valid_referers none blocked *.lab1 *.baidu.com;
                if ($invalid_referer) {
                        return 504;
                }
        }
}

测试结果:

[root@lab1 doc]# r=(http://baidu.com http://www.baidu.com http://a.lab1/ http://a.lab2/ none);for id in ${r[*]};do code=`curl -s -w %
{http_code} http://b.lab1/doc/logo.png -e $id -o /dev/null`;echo "$code -- $id";done
504 -- http://baidu.com
200 -- http://www.baidu.com
200 -- http://a.lab1/
504 -- http://a.lab2/
200 -- none
[root@lab1 doc]# 

rewrite

正则表达式匹配,其中:
* ~ 为区分大小写匹配
* ~* 为不区分大小写匹配
* !~和!~*分别为区分大小写不匹配及不区分大小写不匹配

文件及目录匹配,其中:
* -f和!-f用来判断是否存在文件
* -d和!-d用来判断是否存在目录
* -e和!-e用来判断是否存在文件或目录
* -x和!-x用来判断文件是否可执行

flag标记有:
* last 相当于Apache里的[L]标记,表示完成rewrite
* break 终止匹配, 不再匹配后面的规则
* redirect 返回302临时重定向 地址栏会显示跳转后的地址
* permanent 返回301永久重定向 地址栏会显示跳转后的地址

域名重定向

server {
server_name c.lab1;
rewrite ^/(.*) http://b.lab1/$1 permanent;
}

测试结果:

[root@HADOOP-215 doku]# curl -I http://c.lab1/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.9.3
Date: Tue, 11 Aug 2015 07:36:32 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: http://b.lab1/

参考:http://www.annhe.net/article-1860.html

dokuwiki伪静态

    rewrite ^(/)_media/(.*) $1lib/exe/fetch.php?media=$2 last;
    rewrite ^(/)_detail/(.*) $1lib/exe/detail.php?media=$2 last;
    rewrite ^(/)_export/([^/]+)/(.*) $1doku.php?do=export_$2&id=$3 last;
    location /
    {
        if (!-f $request_filename)
        {
            rewrite ^(/)(.*)?(.*)  $1doku.php?id=$2&$3 last;
            rewrite ^(/)$ $1doku.php last;
        }
    }

参考:http://www.annhe.net/article-1344.html

error_page

error_page 404 = /404.html; #只是转跳而已,返回200
error_page 404 /8c6f66dcfc8a3282/index.html;  #正确的设置方法应该是这样(去掉等号),返回404

参考:http://www.annhe.net/article-1671.html

proxy and upstream

用nginx代理访问Google。需要使用ngx_http_sub_module模块,编译选项--with-http_sub_module。

增加--with-http_sub_module重新编译nginx
./configure ............. --with-http_sub_module
make
不要make install,直接替换二进制文件即可
cp ./obj/nginx /usr/local/nginx/sbin/nginx
查看版本及编译选项
[gjc@server1 ~]$ nginx -V
nginx version: nginx/1.9.3
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-htt
p_gzip_static_module --with-ipv6 --with-http_sub_module
upstream google {
                #server 74.125.239.112:80 max_fails=3;
                #server 74.125.239.113:80 max_fails=3;
                #server 74.125.239.114:80 max_fails=3;
                #server 74.125.239.115:80 max_fails=3;
                #server 74.125.239.116:80 max_fails=3;
        server www.google.com max_fails=3;
        server www.google.com.hk max_fails=3;
        server www.google.co.jp max_fails=3;
        }

        server {
                listen 80;
                server_name google.yourdomain.com;
                rewrite ^(.*) https://google.yourdomain.com$1 permanent;
        }

        server {
        listen 443;
        server_name google.yourdomain.com;
        ssl on;
        ssl_certificate /usr/local/nginx/conf/server.crt;
        ssl_certificate_key /usr/local/nginx/conf/server.key;
        location / {
        proxy_cache_key "$scheme://$host$request_uri";    #缓存key规则,用于自动清除缓存。
        proxy_cache cache_g4w; #缓存区名称,必须与前面定义的相同
        proxy_cache_valid  200 304 3h; #200 304状态缓存3小时
        proxy_cache_valid 301 3d;  #301状态缓存3天
        proxy_cache_valid any 1m;  #其他状态缓存(如502 404)1分钟
        proxy_cache_use_stale invalid_header error timeout http_502;  #当后端出现错误、超时、502状态时启用过期缓存
                proxy_redirect https://www.google.com/ /;     #修改从被代理服务器传来的应答头中的"Location"和"Refresh"字段
                proxy_cookie_domain google.com google.yourdomain.com;  #把cookie的作用域替换成我们的域名
                proxy_pass http://google;                                #指定代理的后端服务器地址和端口,可以是主机名或者IP地址,也可以是通过upstream指令设定的负载均衡组名称
        
        #proxy_set_header设置由后端的服务器获取用户的主机名或真实IP地址,以及代理者的真实IP地址。
                proxy_set_header Host "www.google.com";
                proxy_set_header Accept-Encoding "";
                proxy_set_header User-Agent $http_user_agent;
                proxy_set_header Accept-Language "zh-CN";
                proxy_set_header Cookie "PREF=ID=047808f19f6de346:U=0f62f33dd8549d11:FF=2:LD=zh-CN:NW=1:TM=1325338577:LM=1332142444:GM=1:SG=2:S=rE0SyJh2w1IQ-Maw";                
        sub_filter www.google.com google.yourdomain.com;    #把谷歌的域名替换成自己的域名
                sub_filter_once off;                                #字符串替换一次还是多次替换
                }
        access_log  /home/wwwlogs/p.google.log  access;
        }

参考:http://www.annhe.net/article-1132.html

参考资料

[1]. http://www.annhe.net/article-2415.html
[2]. http://www.annhe.net/article-1860.html
[3]. http://www.annhe.net/article-1344.html
[4]. http://www.annhe.net/article-1671.html
[5]. http://www.annhe.net/article-1132.html

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注