Skip to content

Commit

Permalink
perf(ip-restriction) faster iputils checking
Browse files Browse the repository at this point in the history
Using the binary representation of the address (e.g. via
ngx.var.binary_remote_addr) is a more efficient approach, as
we no longer need to rely on a small LRU cache to store binary-
parsed CIDR and IP objects. To achieve this, we rely on a read-through
module-level cache of parsed CIDR objects to call iputils.binip_in_cidrs
directly; parsed CIDRs objects by definition are consistent, so we
needn't worry about cache invalidation here.
  • Loading branch information
p0pr0ck5 committed May 17, 2017
1 parent bedf0c8 commit b74e195
Showing 1 changed file with 47 additions and 4 deletions.
51 changes: 47 additions & 4 deletions kong/plugins/ip-restriction/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,53 @@ local BasePlugin = require "kong.plugins.base_plugin"
local responses = require "kong.tools.responses"
local iputils = require "resty.iputils"

local new_tab
do
local ok
ok, new_tab = pcall(require, "table.new")
if not ok then
new_tab = function() return {} end
end
end


-- cache of parsed CIDR values
local cache = {}


local IpRestrictionHandler = BasePlugin:extend()

IpRestrictionHandler.PRIORITY = 990

local function cidr_cache(cidr_tab)
local cidr_tab_len = #cidr_tab

local parsed_cidrs = new_tab(cidr_tab_len, 0) -- table of parsed cidrs to return

-- build a table of parsed cidr blocks based on configured
-- cidrs, either from cache or via iputils parse
-- TODO dont build a new table every time, just cache the final result
-- best way to do this will require a migration (see PR details)
for i = 1, cidr_tab_len do
local cidr = cidr_tab[i]
local parsed_cidr = cache[cidr]

if parsed_cidr then
parsed_cidrs[i] = parsed_cidr

else
-- if we dont have this cidr block cached,
-- parse it and cache the results
local lower, upper = iputils.parse_cidr(cidr)

cache[cidr] = { lower, upper }
parsed_cidrs[i] = cache[cidr]
end
end

return parsed_cidrs
end

function IpRestrictionHandler:new()
IpRestrictionHandler.super.new(self, "ip-restriction")
end
Expand All @@ -21,18 +64,18 @@ end
function IpRestrictionHandler:access(conf)
IpRestrictionHandler.super.access(self)
local block = false
local remote_addr = ngx.var.remote_addr
local binary_remote_addr = ngx.var.binary_remote_addr

if not remote_addr then
if not binary_remote_addr then
return responses.send_HTTP_FORBIDDEN("Cannot identify the client IP address, unix domain sockets are not supported.")
end

if conf.blacklist and #conf.blacklist > 0 then
block = iputils.ip_in_cidrs(remote_addr, iputils.parse_cidrs(conf.blacklist))
block = iputils.binip_in_cidrs(binary_remote_addr, cidr_cache(conf.blacklist))
end

if conf.whitelist and #conf.whitelist > 0 then
block = not iputils.ip_in_cidrs(remote_addr, iputils.parse_cidrs(conf.whitelist))
block = not iputils.binip_in_cidrs(binary_remote_addr, cidr_cache(conf.whitelist))
end

if block then
Expand Down

0 comments on commit b74e195

Please sign in to comment.