-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5e94856
commit ac5504b
Showing
13 changed files
with
964 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
local iputils = require "resty.iputils" | ||
local responses = require "kong.tools.responses" | ||
local utils = require "kong.tools.utils" | ||
|
||
local _M = {} | ||
|
||
function _M.execute(conf) | ||
local block = false | ||
|
||
if conf.blacklist and utils.table_size(conf.blacklist) > 0 then | ||
if iputils.ip_in_cidrs(ngx.var.remote_addr, conf._blacklist_cache) then | ||
block = true | ||
end | ||
end | ||
|
||
if conf.whitelist and utils.table_size(conf.whitelist) > 0 then | ||
if iputils.ip_in_cidrs(ngx.var.remote_addr, conf._whitelist_cache) then | ||
block = false | ||
else | ||
block = true | ||
end | ||
end | ||
|
||
if block then | ||
ngx.ctx.stop_phases = true -- interrupt other phases of this request | ||
return responses.send_HTTP_FORBIDDEN("Your IP address is not allowed") | ||
end | ||
end | ||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
local BasePlugin = require "kong.plugins.base_plugin" | ||
local init_worker = require "kong.plugins.ip-restriction.init_worker" | ||
local access = require "kong.plugins.ip-restriction.access" | ||
|
||
local IpRestrictionHandler = BasePlugin:extend() | ||
|
||
function IpRestrictionHandler:new() | ||
IpRestrictionHandler.super.new(self, "ip-restriction") | ||
end | ||
|
||
function IpRestrictionHandler:init_worker() | ||
IpRestrictionHandler.super.init_worker(self) | ||
init_worker.execute() | ||
end | ||
|
||
function IpRestrictionHandler:access(conf) | ||
IpRestrictionHandler.super.access(self) | ||
access.execute(conf) | ||
end | ||
|
||
IpRestrictionHandler.PRIORITY = 990 | ||
|
||
return IpRestrictionHandler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
local iputils = require "resty.iputils" | ||
|
||
local _M = {} | ||
|
||
function _M.execute() | ||
iputils.enable_lrucache() | ||
end | ||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
local iputils = require "resty.iputils" | ||
|
||
local function validate_ips(v, t, column) | ||
local new_fields | ||
if v and type(v) == "table" then | ||
for _, ip in ipairs(v) do | ||
local _, err = iputils.parse_cidr(ip) | ||
if type(err) == "string" then -- It's an error only if the second variable is a string | ||
return false, err | ||
end | ||
end | ||
new_fields = { ["_"..column.."_cache"] = iputils.parse_cidrs(v) } | ||
end | ||
return true, nil, new_fields | ||
end | ||
|
||
return { | ||
fields = { | ||
whitelist = { type = "array", func = validate_ips }, | ||
blacklist = { type = "array", func = validate_ips }, | ||
|
||
-- Internal use | ||
_whitelist_cache = { type = "array" }, | ||
_blacklist_cache = { type = "array" } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
-- Copyright (C) Yichun Zhang (agentzh) | ||
|
||
|
||
local ffi = require "ffi" | ||
local ffi_new = ffi.new | ||
local ffi_sizeof = ffi.sizeof | ||
local ffi_cast = ffi.cast | ||
local ffi_fill = ffi.fill | ||
local ngx_now = ngx.now | ||
local uintptr_t = ffi.typeof("uintptr_t") | ||
local setmetatable = setmetatable | ||
local tonumber = tonumber | ||
|
||
|
||
-- queue data types | ||
-- | ||
-- this queue is a double-ended queue and the first node | ||
-- is reserved for the queue itself. | ||
-- the implementation is mostly borrowed from nginx's ngx_queue_t data | ||
-- structure. | ||
|
||
ffi.cdef[[ | ||
typedef struct lrucache_queue_s lrucache_queue_t; | ||
struct lrucache_queue_s { | ||
double expire; /* in seconds */ | ||
lrucache_queue_t *prev; | ||
lrucache_queue_t *next; | ||
}; | ||
]] | ||
|
||
local queue_arr_type = ffi.typeof("lrucache_queue_t[?]") | ||
local queue_ptr_type = ffi.typeof("lrucache_queue_t*") | ||
local queue_type = ffi.typeof("lrucache_queue_t") | ||
local NULL = ffi.null | ||
|
||
|
||
-- queue utility functions | ||
|
||
local function queue_insert_tail(h, x) | ||
local last = h[0].prev | ||
x.prev = last | ||
last.next = x | ||
x.next = h | ||
h[0].prev = x | ||
end | ||
|
||
|
||
local function queue_init(size) | ||
if not size then | ||
size = 0 | ||
end | ||
local q = ffi_new(queue_arr_type, size + 1) | ||
ffi_fill(q, ffi_sizeof(queue_type, size + 1), 0) | ||
|
||
if size == 0 then | ||
q[0].prev = q | ||
q[0].next = q | ||
|
||
else | ||
local prev = q[0] | ||
for i = 1, size do | ||
local e = q[i] | ||
prev.next = e | ||
e.prev = prev | ||
prev = e | ||
end | ||
|
||
local last = q[size] | ||
last.next = q | ||
q[0].prev = last | ||
end | ||
|
||
return q | ||
end | ||
|
||
|
||
local function queue_is_empty(q) | ||
-- print("q: ", tostring(q), "q.prev: ", tostring(q), ": ", q == q.prev) | ||
return q == q[0].prev | ||
end | ||
|
||
|
||
local function queue_remove(x) | ||
local prev = x.prev | ||
local next = x.next | ||
|
||
next.prev = prev | ||
prev.next = next | ||
|
||
-- for debugging purpose only: | ||
x.prev = NULL | ||
x.next = NULL | ||
end | ||
|
||
|
||
local function queue_insert_head(h, x) | ||
x.next = h[0].next | ||
x.next.prev = x | ||
x.prev = h | ||
h[0].next = x | ||
end | ||
|
||
|
||
local function queue_last(h) | ||
return h[0].prev | ||
end | ||
|
||
|
||
local function queue_head(h) | ||
return h[0].next | ||
end | ||
|
||
|
||
-- true module stuffs | ||
|
||
local _M = { | ||
_VERSION = '0.04' | ||
} | ||
local mt = { __index = _M } | ||
|
||
|
||
local function ptr2num(ptr) | ||
return tonumber(ffi_cast(uintptr_t, ptr)) | ||
end | ||
|
||
|
||
function _M.new(size) | ||
if size < 1 then | ||
return nil, "size too small" | ||
end | ||
|
||
local self = { | ||
keys = {}, | ||
hasht = {}, | ||
free_queue = queue_init(size), | ||
cache_queue = queue_init(), | ||
key2node = {}, | ||
node2key = {}, | ||
} | ||
return setmetatable(self, mt) | ||
end | ||
|
||
|
||
function _M.get(self, key) | ||
local hasht = self.hasht | ||
local val = hasht[key] | ||
if not val then | ||
return nil | ||
end | ||
|
||
local node = self.key2node[key] | ||
|
||
-- print(key, ": moving node ", tostring(node), " to cache queue head") | ||
local cache_queue = self.cache_queue | ||
queue_remove(node) | ||
queue_insert_head(cache_queue, node) | ||
|
||
if node.expire >= 0 and node.expire < ngx_now() then | ||
-- print("expired: ", node.expire, " > ", ngx_now()) | ||
return nil, val | ||
end | ||
return val | ||
end | ||
|
||
|
||
function _M.delete(self, key) | ||
self.hasht[key] = nil | ||
|
||
local key2node = self.key2node | ||
local node = key2node[key] | ||
|
||
if not node then | ||
return false | ||
end | ||
|
||
key2node[key] = nil | ||
self.node2key[ptr2num(node)] = nil | ||
|
||
queue_remove(node) | ||
queue_insert_tail(self.free_queue, node) | ||
return true | ||
end | ||
|
||
|
||
function _M.set(self, key, value, ttl) | ||
local hasht = self.hasht | ||
hasht[key] = value | ||
|
||
local key2node = self.key2node | ||
local node = key2node[key] | ||
if not node then | ||
local free_queue = self.free_queue | ||
local node2key = self.node2key | ||
|
||
if queue_is_empty(free_queue) then | ||
-- evict the least recently used key | ||
-- assert(not queue_is_empty(self.cache_queue)) | ||
node = queue_last(self.cache_queue) | ||
|
||
local oldkey = node2key[ptr2num(node)] | ||
-- print(key, ": evicting oldkey: ", oldkey, ", oldnode: ", | ||
-- tostring(node)) | ||
if oldkey then | ||
hasht[oldkey] = nil | ||
key2node[oldkey] = nil | ||
end | ||
|
||
else | ||
-- take a free queue node | ||
node = queue_head(free_queue) | ||
-- print(key, ": get a new free node: ", tostring(node)) | ||
end | ||
|
||
node2key[ptr2num(node)] = key | ||
key2node[key] = node | ||
end | ||
|
||
queue_remove(node) | ||
queue_insert_head(self.cache_queue, node) | ||
|
||
if ttl then | ||
node.expire = ngx_now() + ttl | ||
else | ||
node.expire = -1 | ||
end | ||
end | ||
|
||
|
||
return _M |
Oops, something went wrong.