YOLO813

Cloudflare(3) - 404状态码的缓存和nginx的ngx_http_geoip2_module模块失效

    对于大数据量的网站来说,有众多采集爬虫不足为奇,这些爬虫总会发现你网站的路径规则,例如,通过你的日期分类页每天轮询,这对使用CDN(因为我只使用过cloudflare,所以单指cloudflare,下称CF)的用户造成了困扰,例如今天为2月14号,因为爬虫的提前访问(当时该页面数据没有更新),会导致2月14号页面下的数据返回状态码为404。

    之前一直担心404的页面也被缓存下来,经过测试,确实是会被缓存,按照网上的一些操作,例如在nginx的server段添加如下代码:

error_page  404 /404.html;
location = /404.html {
   root   /usr/share/nginx/html;
   add_header Cache-Control "no-cache" always;
}


    很遗憾,没有效果(据说apache可以生效,我没有测试)。

    在CF社区找到了一篇参考答案(下方参考中),按照它的说明,404页面不会被缓存超过3分钟,我经过实际测试,应该是可以相信社区的答案的,为什么我也不太肯定,因为我的多次测试只成功了一次,大概率是浏览器缓存搞的鬼。

    测试浏览器:火狐,谷歌浏览器

    测试步骤:制作了一个A页面,数据库删除该条数据,返回404,再次添加该条数据,让其可以返回状态码200,3分钟之后再次强制刷新访问,查看其是否可以正常返回200状态码。

    之前在实战-nginx嵌入GEOIP一文中,介绍了nginx禁止某区域访问,那么在配置了CF之后,还可以生效吗?如果可以生效,禁止某区域访问,这个页面是否会被缓存呢?

    先说结论:无法生效!nginx的ngx_http_geoip2_module也是依赖于$remote_addr内容的判断,由于现在这个字段内容全都是CF的缓存服务器IP,因此无法实现这个功能。

    测试如下,nginx配置文件:

load_module /opt/nginx-1.18.0/objs/ngx_http_geoip2_module.so;
http{
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for" "$geoip2_data_city_name" ';
    
    geoip2 /usr/local/share/GeoIP/GeoLite2-City.mmdb {
      $geoip2_data_city_name default=London city names en;
    }
    server{
      if ($geoip2_data_city_name = "Guangzhou") {
            return 403;
      }
    }
}


    上面我为log_format增加了一个字段geoip2_data_city_name,用于输出城市名称,因此,在nginx日志中,可以看到如下内容

    所有的城市名称都变成了CF缓存服务器的IP所在城市,地址为Los Angeles,因此在web服务器这一块对地理位置的屏蔽也就无法生效了。

    在CF的防火墙规则中,其实也存在屏蔽某些国家/地区的IP功能,但是会占用一条防火墙规则,另外无法精确到城市名。

参考:

# How to avoid caching 404
https://community.cloudflare.com/t/how-to-avoid-caching-404/196262