Nginx 限制来源地址相关配置

2019-10-19 45点热度 0人点赞 0条评论

Nginx 想限制访问源地址的时候,一般都想到是用 iptables 来控制。但是实际上 Nginx 自身也可以进行限制


1、ngx_http_access_module

官方文档 [ 链接 ]

最简单的方式,只需要添加 allowdeny 两个参数说明就可以控制。

判定方式是依照 $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

StarryVoid

Have a good time