CDN下配置nginx获取用户真实IP

背景

  • 由于网站使用了CDN,CDN的使用有助于提高网站的访问速度,其实现方式是CDN服务器根据用户的请求,自己请求Web服务器内容,然后根据返回的内容通过CDN服务器返回给用户,这样造成的结果就是会使得nginx记录的全是CDN服务器的IP,而不是真实的客户端IP,其结果并不利于访问日志的分析。
  • 此外我想屏蔽国外IP对本网站的访问请求,将其重定向到国外的另一个网站,纯粹为了试验。

配置

  1. 在nginx配置文件/etc/nginx.conf中添加map配置,配置项位于http项中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 以下内容全部配置在http项中
    # 获取用户真实IP,并赋值给变量$clientRealIP
    map $http_x_forwarded_for $clientRealIp {
    "" $remote_addr;
    ~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
    }

    # 添加日志记录的配置格式,将其命名为:myLog
    log_format myLog '$http_x_forwarded_for - $remote_user [$time_local] "$request" '
    '"$status" $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for" '
    '"$gzip_ratio" $request_time $bytes_sent $request_length';

    # 设置日志记录的格式为自定义的配置格式
    access_log /var/log/nginx/access.log myLog;

    关于上述配置的缘由,在某一篇博文中也见到了一些解释:

    1
    2
    3
    4
    5
    6
    7
    其实,当一个CDN或者透明代理服务器把用户的请求转到后面服务器的时候,这个CDN服务器会在Http的头中加入一个记录:
    X-Forwarded-For: 用户IP,代理服务器IP

    如果中间经历了不止一个代理服务器,这个记录会是这样:
    X-Forwarded-For: 用户IP,代理服务器1-IP,代理服务器2-IP,代理服务器3-IP,….

    可以看到经过好多层代理之后,用户的真实IP在第一个位置,后面会跟一串中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个IP地址做限制就可以了。
  2. 配置完毕后重启nginx,然后访问网站,查看nginx的日志信息【/var/log/nginx/access.log】中是否记录的是客户端的IP

    1
    2
    sudo nginx -s reload
    vim /var/log/nginx/access.log

域名重定向

该重定向的配置建立在GeoIP2的IP筛选基础上,详情可查看【Nginx配置GeoIP2】的记录。

  • 修改nginx的配置文件信息:/etc/nginx/nginx.conf,在GeoIP2的配置中添加source

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 以下内容配置在http项中
    geoip2 /var/GeoIP2/GeoLite2-Country.mmdb {
    auto_reload 60m;
    # 此处的$clientRealIp来源于前文【配置】中map
    $geoip2_metadata_country_build source=$clientRealIp metadata build_epoch;
    $geoip2_data_country_code source=$clientRealIp country iso_code;
    $geoip2_data_country_name source=$clientRealIp country names en;
    }

    geoip2 /var/GeoIP2/GeoLite2-City.mmdb {
    auto_reload 60m;
    $geoip2_metadata_city_build source=$clientRealIp metadata build_epoch;
    $geoip2_data_city_name source=$clientRealIp city names en;
    }
  • 配置完成后修改nginx网站的重定向:/etc/nginx/sites-available/default

    1
    2
    3
    4
    5
    6
    # 以下配置项位于server项中
    location / {
    if ($geoip2_data_country_code = BG) {
    rewrite ^(.*)? https://test.test.bg$1 redirect;
    }
    }

    关于nginx配置项中rewrite,作简要解释:

    • rewrite的语法格式:

      1
      2
      3
      4
      5
      rewrite [正则表达式] [替代内容] [处理方式]

      # 正则:就是匹配用于请求的URI,它支持正则表达式,可对单个或一类URL进行匹配处理
      # 替代内容:对配置正则的请求,将其重定向到此处设定的替代内容链接上
      # 处理方式:分为last、break、redirect、permanent
    • 针对上文【处理方式】再做细说

      1
      2
      3
      4
      last:本条规则匹配完成后,继续向下匹配新的location URI规则
      break:本条规则匹配完成即终止,不再匹配后面的任何规则
      redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
      permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
    • 本次最疑惑的是redirect和permanent两个的区别,但就实际使用效果而言,两者都能够实现重定向到目标地址。但临时重定向不会缓存域名解析记录(A记录),而永久重定向会缓存重定向的数据到本地。

引用

  1. 上述内容主要参考如下链接,感谢博主细心整理:

    重定向区别:https://www.cnblogs.com/yinzhengjie/p/12064108.html

    重定向解释:https://www.cnblogs.com/czlun/articles/7010604.html

    CDN获取真实IP:https://zhang.ge/5096.html

    CDN配置日志:https://cloud.tencent.com/developer/article/1411940