Nginx 想限制访问源地址的时候,一般都想到是用 iptables 来控制。但是实际上 Nginx 自身也可以进行限制
1 、 ngx_http_access_module
官方文档 [ 链接 ]
最简单的方式,只需要添加 allow
和 deny
两个参数说明就可以控制。
判定方式是依照 $remote_addr
这个变量的值。
location / { deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; allow 2001:0db8::/32; deny all; }
你可以在 http, server, location, limit_except 内容块中使用这些命令,从上到下匹配,匹配到就处理。
2 、 ngx_http_geo_module
官方文档 [ 链接 ]
判定来源方式默认是根据 $remote_addr
,等价于 $remote_addr $your_list
。也可以手动指定为其他来源参数 $realip_remote_addr $your_list
首先创建源列表,左侧是来源值,也就是默认的 $remote_addr 。右侧是赋予的值 这里是 $geo 。
当左侧条件匹配时,该变量的值为右侧的值(可以是数字,字符串)
geo $geo { default 0; 127.0.0.1 2; 127.0.0.0/24 US; 192.168.1.0/24 1; ::1 2; 2001:0db8::/32 1; }
然后在其他地方调用即可 [ 链接 ]
if ($geo == 1) { return 404; }
关于常见的 反向代理 导致的 $remove_addr 变化,还可以通过 ngx_http_realip_module 进行置换 [ 链接 ] [ 链接 ] [ 链接 ]
比如对 Cloudflare 进行置换,置换后可以得到真实 IP 。(注意 ngx_http_access_module 会在 ngx_http_realip_module 执行后进行判定)
set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 2400:cb00::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2405:b500::/32; set_real_ip_from 2606:4700::/32; set_real_ip_from 2803:f800::/32; set_real_ip_from 2a06:98c0::/29; set_real_ip_from 2c0f:f248::/32; real_ip_header CF-Connecting-IP; real_ip_recursive on;
在地址格式为如下时,同样的访问会产生两种不同的结果
log_format main '"$remote_addr" - SIP="$realip_remote_addr" - FIP="$http_x_forwarded_for" - CF_IP="$http_cf_connecting_ip" ';
访问路径 Client -- 111.222.111.222 -- 108.162.215.228 -- Server
旧 "108.162.215.228" - SIP="108.162.215.228" - FIP="111.222.111.222" - CF_IP="111.222.111.222"
新 "111.222.111.222" - SIP="108.162.215.228" - FIP="111.222.111.222" - CF_IP="111.222.111.222"
转换后注意 remote_addr 已经变更了,根据该变量执行的操作可能出现问题,比如代理安全风险。
如果这时需要 ngx_http_access_module 来控制访问,则可以改用 Geo 来进行管控,如下例
geo $realip_remote_addr $cloudflare_cdn_ip { default 0; 10.0.0.0/8 1; 172.16.0.0/12 1; 192.168.0.0/16 1; 127.0.0.0/8 1; # Source https://www.cloudflare.com/ips/ 103.21.244.0/22 1; 103.22.200.0/22 1; 103.31.4.0/22 1; 104.16.0.0/13 1; 104.24.0.0/14 1; 108.162.192.0/18 1; 131.0.72.0/22 1; 141.101.64.0/18 1; 162.158.0.0/15 1; 172.64.0.0/13 1; 173.245.48.0/20 1; 188.114.96.0/20 1; 190.93.240.0/20 1; 197.234.240.0/22 1; 198.41.128.0/17 1; 2400:cb00::/32 1; 2405:8100::/32 1; 2405:b500::/32 1; 2606:4700::/32 1; 2803:f800::/32 1; 2a06:98c0::/29 1; 2c0f:f248::/32 1; }
if ($cloudflare_cdn_ip != 1) { return 404; }
含义是 检测 $realip_remote_addr 是否为 Cloudflare CDN 地址和私网地址,如果是,则直接将 $cloudflare_cdn_ip 的值配置为 1 ,否则返回 0 。而后对 $cloudflare_cdn_ip 进行判定,为 0 时返回 404 not found