基于 ngx_lua 实现 IP(分组) 访问控制
需求场景
- 仅允许白名单访问
- 禁止黑名单访问
IP 分组定义
IP 分组定义 是我从 Fabric 获取的灵感。我通过分组的方式对 IP 地址进行归类,目的是使 IP 列表管理集中化、方便不同的业务上下文复用,还可以动态把多个分组组合成一个分组(下面有使用场景)。
分组定义为一个 Lua 模块(ip_groups.lua
)中的一个变量,结构如下:
local group_defs = {
localhost = {
'127.0.0.1',
},
staff = {
'1.1.1.1',
'1.1.1.2',
'10.10.10.1/24',
},
ecs = {
'8.8.8.8',
'8.8.8.9',
},
banned = {
'2.2.2.2',
'2.2.2.4',
'2.2.2.6',
},
all = {
'0.0.0.0/24',
},
}
group_defs
中定义了多个 IP分组,每个分组中包含一个或多个 IP(支持CIDR
)。比如 staff
里面包含了所有办公网络的 IP,ecs
里面包含了相关的云主机 IP。
需要引用分组的地方只需导入这个 Lua 模块即可。
实现模式1: 变量配置方式
指导思想:约定优先,力求配置简化
在具体上下文配置如下两个 Nginx 变量:
denied_ip_groups
: 默认为空
allowed_ip_groups
: 默认ALL
(或者默认为空
?)
处理流程:
- 扫描
denied_ip_groups
, 遇到匹配则停止扫描并禁止访问 ,
没有匹配则继续扫描
- 扫描
allowed_ip_groups
, 遇到匹配则停止扫描并允许访问,
没有匹配也停止扫描并禁止(?)
假设核心逻辑实现在 ip_access_ctrl.lua
中,配置样例如下:
server {
access_by_lua_file 'ip_access_ctrl.lua';
location /foo {
# white list example
set $allowed_ip_groups 'staff,ecs';
proxy_pass foo_upstream;
}
location /bar {
# black list example
set $denied_ip_groups 'banned';
proxy_pass bar_upstream;
}
}
实现模式2:指令式控制
指导思想:指令控制,力求灵活
假设核心逻辑实现在 ip_access_ctrl.lua
中,配置样例如下:
server {
init_by_lua_block {
ip_access_ctrl = require('ip_access_ctrl.lua')
}
location /foo {
# white list example
access_by_lua_block {
ip_access_ctrl.allow_group('staff,ecs')
ip_access_ctrl.deny_group('all')
}
proxy_pass foo_upstream;
}
location /bar {
# black list example
access_by_lua_block {
ip_access_ctrl.deny_group('banner')
ip_access_ctrl.allow_group('all')
}
proxy_pass bar_upstream;
}
}