Access controll based on IP address
-- Access controll based on IP address
local iputils = require("resty.iputils")
local ip_groups = require('lib.ip_groups')
function get_real_ip()
if not ngx.var.http_x_forwarded_for then
-- return ngx.null;
return ngx.var.remote_addr
end
local m = ngx.re.match(ngx.var.http_x_forwarded_for, [=[[\d\.]+]=])
return m and m[0]
end
function match_group(remote_grp, client_grp)
-- Returns:
-- true: matched
-- false: not matched or no need to match
local matched_r, matched_c
if ngx.ctx._ip_access_ctrl_has_matched_rule then
return false
end
-- evaluate matched_r
local remote_list = ip_groups:get_parsed(remote_grp)
matched_r = iputils.ip_in_cidrs(ngx.var.remote_addr, remote_list)
-- Judge directly if no client_grp provided
if not client_grp then
if matched_r then
ngx.ctx._ip_access_ctrl_has_matched_rule = true
return true
else
return false
end
end
local real_ip = get_real_ip()
local client_list = ip_groups:get_parsed(client_grp)
matched_c = iputils.ip_in_cidrs(real_ip, client_list)
if matched_r and matched_c then
ngx.ctx._ip_access_ctrl_has_matched_rule = true
return true
else
return false
end
end
local exports = {
allow_group = function(remote_grp, client_grp)
-- remote_grp and client_grp must all match!
if not ngx.ctx._ip_access_ctrl_has_matched_rule then
ngx.log(ngx.INFO, string.format('Try matching %s/%s for allow', remote_grp or '--', client_grp or '--'))
end
local matched = match_group(remote_grp, client_grp)
if matched then
ngx.log(ngx.INFO, 'Allowed directly')
end
end,
deny_group = function(remote_grp, client_grp)
if not ngx.ctx._ip_access_ctrl_has_matched_rule then
ngx.log(ngx.INFO, string.format('Try matching %s/%s for deny', remote_grp or '--', client_grp or '--'))
end
local matched = match_group(remote_grp, client_grp)
if matched then
ngx.log(ngx.ERR, 'Denied')
ngx.exit(ngx.HTTP_FORBIDDEN)
end
end
}
return exports