使用 proxy_protocol 时,在 nginx 中阻止 CIDR 范围的更好方法是什么?

what is the better way to block CIDR ranges in nginx when using proxy_protocol?

我在 AWS 的 ELB 后面有一小部分 nginx 实例。此 ELB 面向互联网并使用 PROXY 协议,而不是 HTTP。

这是我的 main.vhost

的相关部分
server {

    # speak only PROXY protocol
    # Accept 80/443; we'll do the http -> https re-dir elsewhere in conf
    # SSL is default mode
    listen 443 default_server ssl proxy_protocol;
    listen 80 proxy_protocol;

我正在尝试使用 ngx_http_access_module 中的 deny 指令来阻止访问一系列 CIDR 块。

例如: 在 nginx 启动时加载的 .conf 文件中:

include /etc/nginx/ip_block/*.conf;

并且在 /etc/nginx/ip_block/ 目录中至少有一个文件:

$ cat /etc/nginx/ip_block/some_cidr_ranges.conf | wc -l
361
$ head /etc/nginx/ip_block/some_cidr_ranges.conf
deny 2604:a880:1::/48;
<snip>
deny 208.68.36.0/22;

但是,nginx 的deny 指令似乎只对$remote_addr 变量起作用,对$proxy_protocol_addr 变量不起作用。这实际上意味着我不能同时使用 deny 指令和 proxy_protocol

似乎 ngx_stream_realip_module 模块可用于将 $remote_addr 的值调整为 $proxy_protocol_addr 值但是,我可用的 nginx 构建不是当前配置了 --with-stream_realip_module build-flag。我目前是 运行 1.10.3 但看起来 with-stream_realip_module 标志是在构建 1.11.4 (https://github.com/nginx/nginx/commit/fe2774a9d689fa1bf201dd0e89449e3d9e4ad926)

中引入的

选项 1: 从源代码构建一个 nginx 版本,其中包含我需要编译的功能。

在查看 deny 指令的文档时,我发现了这条注释:

In case of a lot of rules, the use of the ngx_http_geo_module module variables is preferable.

发件人:https://nginx.org/en/docs/http/ngx_http_access_module.html

这让我想知道是否有更好的方法来实现阻止 CIDR 范围的目标,该范围可以与我目前拥有的 nginx 二进制文件一起使用。

我可以试试这样吗:

geo $proxy_protocol_addr $blocked_cidr {
    default        01;
    include        conf/some_cidr_ranges_to_block.conf;
}

文件 conf/some_cidr_ranges_to_block.conf 看起来像:

2604:a880:1::/48    02;
<snip>
208.68.36.0/22      02;

然后在我的服务器指令中我可以做类似的事情:

if ($blocked_cidr != 01) {
 return 403;
}

选项 2: 尝试使用 geo 指令和自定义 IP 范围 -> "country code" 数据库来阻止流量。

我的问题:

- Is *option 1* going to be a better use of time / is it worth it to build my own version of nginx with the necessary `stream_realip_module` compiled in or is it going to be more performant / effective to use the `geo` directive to map the `$proxy_protocol_addr` onto a set of ranges as shown above (*option 2*) 


- Is there some other way to block or filter traffic in nginx by cidr block when using nginx in `proxy_protocol` mode that i have not yet considered?

快速更新/回答我的问题。

感谢Tan Hong Tat的建议,我不用自己编译nginx了。这使 选项 1 脱离了 table 并且节省了我一些工作。谢谢!

我已经将数百条 deny 规则加载到 nginx 中,我正在关注对性能的影响。

此外,我使用 geo 指令从我的 OP 中实现了类似于 选项 2 的东西。我同样在监测影响。

到目前为止,我不清楚为什么 nginx 文档会发出关于使用 deny 和 "lots" 规则的建议:

In case of a lot of rules, the use of the ngx_http_geo_module module variables is preferable.

geo 指令确实让我更灵活一些,因为我可以选择将用户发送到哪个位置。 deny 指令是 403,无法更改。

你可以使用 -

if ($proxy_protocol_addr != a.b.c.d) { return 403;
}