nginx map指令

  • Post author:
  • Post category:其他


nginx map指令用于根据现有的变量的值来赋值新变量。如根据

x-forwarded-for



remote_addr

的值,创建新变量

clientip



用法解析

Syntax: map string $variable { … }

Default: —

Context: http


  • string

    可以是一个或多个变量组成的字符串

  • $variable

    是新变量名

  • {...}

    中的内容为

    source



    resulting

    的映射


    • source

      可以为字符串或正则(

      ~

      区分大小写,

      ~*

      不区分大小写)

    • resulting

      赋予

      $variable

      新变量的值

  • {...}

    中可以使用以下关键字,当

    source

    与关键字重复时需要使用

    \

    转义


    • default value

      设置默认值

    • hostnames

      指明

      source

      的值是主机名,主机名可包含前缀或后缀

    • include file

      包含变量文件

    • volatile

      指明变量不可缓存



实例演示



获取client真实ip

nginx http区块配置如下:

    map $http_x_forwarded_for $clientip {
        "" $remote_addr;
        default $http_x_forwarded_for;
    }
    log_format  main  '$clientip - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$request_time"';

在客户端访问两次:

# curl -H 'x-forwarded-for:10.0.1.60' 10.2.1.105/f5.html
# curl 10.2.1.105/f5.html

访问日志:

10.0.1.60 - - [14/Aug/2019:18:37:44 +0800] "GET /f5.html HTTP/1.1" 200 2 "-" "curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5" "0.000"
10.0.1.60 - - [14/Aug/2019:18:37:58 +0800] "GET /f5.html HTTP/1.1" 200 2 "-" "curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5" "0.000"

这种办法有一个bug,如果客户端伪造了

x-forwarded-for

头部,后端主机的日志就没有参考价值了。

推荐在前端代理服务器上将

x-forwarded-for

重置为空之后再赋值。



转发到手机端页面

nginx http区块配置如下:

    map $http_user_agent $ifmobile {
        ~*iphone 1;
        ~*ipod 1;
        ~*android 1;
        default 0;
    }

nginx server区块配置如下:

        if (-f $request_filename/index.html) {
            rewrite ^(.*) $1/index.html;
        }

        if ( $ifmobile = 1 ) {
            rewrite (.*) /m$1;
        }


注:这里

rewrite

语句干扰了

index

语句的执行,在访问目录时,无法正确定位到目录下的index.html,故加了

$request_filename/index.html

的判断。

在客户端访问:

# curl -H 'user-agent:huaweimate20 android 9.0' 10.2.1.105/index.html
m/index.html
# curl -H 'user-agent:no' 10.2.1.105/index.html
index.html
# curl  10.2.1.105
index.html

上述需求也可以在nginx server区块使用以下配置来实现:

        if ( $http_user_agent ~* (iphone|ipod|android) ) {
            set $ifmobile 1;
        }

        if (-f $request_filename/index.html) {
            rewrite ^(.*) $1/index.html;
        }

        if ( $ifmobile = 1 ) {
            rewrite ^/(.*) /m/$1;
        }



匹配hostname

nginx http区块配置如下:

    map $http_referer $ifmyreferer {
        hostnames;
        *.example.com 1;
        example.com 1;
        .example.cn 1;
        default 0;
    }

    log_format  main  '$clientip - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$request_time" "$ifmyreferer"';

其中以下两行

*.example.com 1;
example.com 1;

可以简写为

.example.com 1;

前缀可以这样简写,后缀就不行了。

在nginx server区块添加以下配置,就可以防盗链了:

        location ~* \.(jpg|jpeg|png|gif|ico)$ {
            if ($ifmyreferer = 0) {
                return 404;
            }
        }

客户端请求:

# curl -H 'referer:www.example.com' 10.2.1.105/luozhao.jpg
GIF89aÿÿÿ!?L;
# curl -H 'referer:www.baidu.com' 10.2.1.105/luozhao.jpg
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

注:防盗链有专用指令

valid_referers



版权声明:本文为ketaobaobao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。