【Day5】Nginx实战训练营

故事扮演 提交于 2020-02-05 01:56:01

16 Nginx全局变量

nginx 常用全局变量

变量 说明
$args 请求中的参数,如 www.123.com/1.php?a=1&b=2 的$args 就是 a=1&b=2
$content_length HTTP请求信息里的 “Content-Length”
$conten_type HTTP请求信息里的 “Content-Type”
$document_root nginx 虚拟主机配置文件中的 root 参数对应的值
$document_uri 当前请求中不包含指令的 URI,如www.123.com/1.php?a=1&b=2 的 $document_uri 就是 1.php,不包含后面的参数
$host 主机头,也就是域名
$http_user_agent 客户端的详细信息,也就是浏览器的标识,用 curl -A 可以指定
$http_cookie 客户端的 cookie 信息
$limit_rate 如果 nginx 服务器使用 limit_rate 配置了显示网络速率,则会显示,如果没有设置, 则显示 0
$remote_addr 客户端的公网 ip
$remote_port 客户端的 port
$remote_user 如果 nginx 有配置认证,该变量代表客户端认证的用户名
$request_body_file 做反向代理时发给后端服务器的本地资源的名称
$request_method 请求资源的方式,GET/PUT/DELETE 等
$request_filename 当前请求的资源文件的路径名称,相当于是 $document_root/$document_uri 的组合
$request_uri 请求的链接,包括 $document_uri和 $args
$scheme 请求的协议,如 ftp,http,https
$server_protocol 客户端请求资源使用的协议的版本,如 HTTP/1.0,HTTP/1.1,HTTP/2.0 等
$server_addr 服务器 IP 地址
$server_name 服务器的主机名
$server_port 服务器的端口号
$uri 和 $document_uri 相同
$http_referer 客户端请求时的 referer,通俗讲就是该请求是通过哪个链接跳过来的,用 curl -e 可以指定

17/18 rewrite实战

本部分内容为nginx生产环境中使用的场景示例。

1、域名跳转(域名重定向)

  • 示例1(不带条件的):
server{
    listen 80;
    server_name www.1.com;
    rewrite /(.*) http://www.1.com/$1 permanent;
    ......
}
  • 示例2(带条件的):
server{
    listen 80;
    server_name www.1.com 1.com;
    if ($host != 'www.1.com')
    {
        rewrite /(.*) http://www.1.com/$1 permanent;
    }
    ......
}
  • 示例3(http 跳转到 https):
server{
    listen 80;
    server_name www.1.com;
    rewrite /(.*) https://www.1.com/$1 permanent;
    ......
}
  • 示例4(域名访问二级目录)
server{
    listen 80;
    server_name bbs.1.com;
    rewrite /(.*) http://www.1.com/bbs/$1 last;
    ......
}
  • 示例5(静态请求分离)
server{
    listen 80;
    server_name www.1.com;
    location ~* ^.+.(jpg|jpeg|gif|css|png|js)$
    {
        rewrite /(.*) http://img.1.com/$1 permanent;
    }
    ......
}

外国服务器访问国内静态文件,可以跳转到国内已备案域名的服务器上去

或者:

server{
    listen 80;
    server_name www.1.com;
    if ( $uri ~* 'jpg|jpeg|gif|css|png|js$')
    {
        rewrite /(.*) http://img.1.com/$1 permanent;
    }
    ......
}

2、防盗链

  • 示例6
server{
    listen 80;
    server_name www.1.com;
    location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
    {
       valid_referers none blocked server_names *.1.com 1.com *.1.com 2.com;
        if ($invalid_referer)
        {
            rewrite /(.*) http://img.1.com/images/forbidden.png;
        }
    }
    ......   
}

valid_referers 白名单
invalid_referer 黑名单

说明:* 这里是通配,跟正则里面的 * 不是一个意思,none 指的是 referer 不存在的情况(curl -e 测试),blocked 指的是 referer 头部的值被防火墙或者代理服务器删除或者伪装的情况,该情况下,referer 头部的值不以 http:// 或者 https:// 开头(curl -e 后面跟的 referer 不以 http:// 或者 https:// 开头)。

或者

    location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
    {
        valid_referers none blocked server_names *.1.com *.1.com 1.com 2.com;
        if ($invalid_referer)
        {
            return 403;
        }
    }

测试
1、去掉白名单中的 none,测试结果,没有 referer 时,403,用白名单中域名可以访问

[root@alexis-01 ~]# curl -x127.0.0.1:80 'www.2.com/abc/1.png' -I
HTTP/1.1 403 Forbidden
Server: nginx/1.16.1
Date: Tue, 29 Oct 2019 13:54:59 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

[root@alexis-01 ~]# curl -e "http://www.2.com/1.html" -x127.0.0.1:80 'www.2.com/abc/1.png' -I
HTTP/1.1 404 Not Found
Server: nginx/1.16.1
Date: Tue, 29 Oct 2019 13:57:46 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

2、去掉白名单中的 blocked,测试结果,不以 http:// 或 https:// 开头域名访问,403

[root@alexis-01 ~]# curl -e "www.2.com/1.html" -x127.0.0.1:80 'www.2.com/abc/1.png' -I
HTTP/1.1 403 Forbidden
Server: nginx/1.16.1
Date: Tue, 29 Oct 2019 13:59:22 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

总结:

  • 加 none,有没有 referer 都可以,不加 none,没有 referer 会 403

  • 加 blocked,访问的域名可以让不以 http:// 或 https:// 开头域名访问,不加 blocked 必须要加开头,否则 403

3、伪静态

  • 示例7( discuz 伪静态):
location /  {
    rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last;
    rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;
    rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;
    rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last;
    rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last;
    rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last;
}

4、rewrite 多个条件的并且

  • 示例8
location /{
    set $rule 0;
    if ($document_uri !~ '^/abc')
    {
        set $rule "${rule}1";
    }
    if ($http_user_agent ~* 'ie6|firefox')
    {
       set $rule "${rule}2";
    }
    if ($rule = "012")
    {
        rewrite /(.*) /abc/$1 redirect;
    }
}

测试
满足以上两个 if,结果到了 rewrite

[root@alexis-01 ~]# curl -x127.0.0.1:80 -A "ie6" www.2.com/1.html -I
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.16.1
Date: Tue, 29 Oct 2019 14:19:05 GMT
Content-Type: text/html
Content-Length: 145
Location: http://www.2.com/abc/1.html
Connection: keep-alive

19 Nginx的location配置

  • nginx 的 location 配置
    安装第三方模块做测试 echo-nginx-module
[root@alexis-01 src]# git clone https://github.com/openresty/echo-nginx-module.git
[root@alexis-01 src]# ./configure --prefix=/etc/nginx --add-module=/usr/local/src/echo-nginx-module
[root@alexis-01 nginx-1.14.2]# make && make install

重新编译安装 nginx

  • nginx location 语法规则: location [=|~|~*|^~] /uri/ { … }
    nginx 的 location 匹配的变量是 $uri
符号 说明
= 表示精确匹配
^~ 表示uri以指定字符或字符串开头
~ 表示区分大小写的正则匹配
~* 表示不区分大小写的正则匹配
/ 通用匹配,任何请求都会匹配到
  • 规则优先级
    = 高于 ^~ 高于 ~* 等于 ~ 高于 /

  • 规则示例

location = "/12.jpg" { ... }
如:
www.1.com/12.jpg 匹配
www.1.com/abc/12.jpg 不匹配

location ^~ "/abc/" { ... }
如:
www.1.com/abc/123.html 匹配
www.1.com/a/abc/123.jpg 不匹配

location ~ "png" { ... }
如:
www.1.com/aaa/bbb/ccc/123.png 匹配
www.1.com/aaa/png/123.html 匹配

location ~* "png" { ... }
如:
www.1.com/aaa/bbb/ccc/123.PNG 匹配
www.1.com/aaa/png/123.html 匹配

location /admin/ { ... }
如:
www.1.com/admin/aaa/1.php 匹配
www.1.com/123/admin/1.php 不匹配
  • 小常识
    有些资料上介绍 location 支持不匹配 !~,
    如: location !~ ‘png’{ … }
    这是错误的,location 不支持 !~

如果有这样的需求,可以通过 if 来实现,
如: if ($uri !~ ‘png’) { … }

注意:location 优先级小于 if

  • nginx location优先级
    = 高于 ^~ 高于 ~* 等于 ~ 高于 /

1、对比 / 和 ~
示例1:

server{
    listen 80;
    server_name www.1.com;
    root /data/wwwroot/www.1.com;

    location /abc/
    {
        echo "/";
    }
    location ~ 'abc'
    {
        echo "~";
    }
}

测试命令:curl -x127.0.0.1:80 ‘www.1.com/abc/1.png’
结果是:~

2、对比 ~ 和 ~*
示例2:

server
{
    listen 80;
    server_name www.1.com;
    root /data/wwwroot/www.1.com;

    location ~ 'abc'
    {
        echo '~';
    }
    location ~* 'abc'
    {
        echo '~*';
    }
}

测试命令:curl -x127.0.0.1:80 ‘www.1.com/abc/123.html’
结果是:~

示例3:

server
{
    listen 80;
    server_name www.1.com;
    root /data/wwwroot/www.1.com;

    location ~* 'abc'
    {
        echo '~*';
    }
    location ~ 'abc'
    {
        echo '~';
    }
}

测试命令:curl -x127.0.0.1:80 ‘www.1.com/abc/123.html’
结果是:~*

结论:~ 和 ~* 优先级其实是一样的,如果两个同时出现,配置文件中哪个location靠前,哪个生效。

3、对比 ^~ 和 ~
示例4:

server
{
    listen 80;
    server_name www.1.com;
    root /data/wwwroot/www.1.com;

    location ~ '/abc'
    {
        echo '~';
    }
    location ^~ '/abc'
    {
        echo '^~';
    }
}

测试命令:curl -x127.0.0.1:80 'www.1.com/abc/123.html
结果是:^~

4、对比 = 和 ^~
示例5:

server
{
    listen 80;
    server_name www.1.com;
    root /data/wwwroot/www.1.com;

    location ^~ '/abc.html'
    {
        echo '^~';
    }
    location = '/abc.html'
    {
        echo '=';
    }
}

测试命令:curl -x127.0.0.1:80 'www.1.com/abc.html
结果是:=

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!