140 lines
4.4 KiB
Lua
140 lines
4.4 KiB
Lua
package.path = package.path .. ";./lib/?.lua"
|
|
|
|
local config = require "config"
|
|
local lrucache = require "lrucache"
|
|
local logging = require "logging"
|
|
local log_file = require "logging.file"
|
|
local socket = require "socket"
|
|
local http = require("socket.http")
|
|
local https = require("ssl.https")
|
|
|
|
|
|
-- contain runtime = {}
|
|
local runtime = {}
|
|
|
|
|
|
function ipToInt( str )
|
|
local num = 0
|
|
if str and type(str)=="string" then
|
|
local o1,o2,o3,o4 = str:match("(%d+)%.(%d+)%.(%d+)%.(%d+)" )
|
|
num = 2^24*o1 + 2^16*o2 + 2^8*o3 + o4
|
|
end
|
|
return num
|
|
end
|
|
|
|
|
|
local csmod = {}
|
|
|
|
function getLogLevel( level )
|
|
if level and type(level)=="string" then
|
|
if level:upper() == "INFO" then
|
|
return logging.INFO
|
|
end
|
|
if level:upper() == "WARN" then
|
|
return logging.WARN
|
|
end
|
|
if level:upper() == "DEBUG" then
|
|
return logging.DEBUG
|
|
end
|
|
if level:upper() == "ERROR" then
|
|
return logging.ERROR
|
|
end
|
|
if level:upper() == "FATAL" then
|
|
return logging.FATAL
|
|
end
|
|
end
|
|
return logging.INFO
|
|
end
|
|
|
|
-- init function
|
|
function csmod.init(configFile, userAgent)
|
|
local conf, err = config.loadConfig(configFile)
|
|
if conf == nil then
|
|
return nil, err
|
|
end
|
|
runtime.conf = conf
|
|
|
|
local logger = log_file(conf["LOG_FILE"])
|
|
logger:setLevel (getLogLevel(conf["LOG_LEVEL"]))
|
|
runtime.logger = logger
|
|
runtime.userAgent = userAgent
|
|
local c, err = lrucache.new(conf["CACHE_SIZE"])
|
|
if not c then
|
|
error("failed to create the cache: " .. (err or "unknown"))
|
|
end
|
|
runtime.cache = c
|
|
return true, nil
|
|
end
|
|
|
|
|
|
function csmod.allowIp(ip)
|
|
if runtime.conf == nil then
|
|
return nil, "Configuration is bad, cannot run properly"
|
|
end
|
|
local resp = runtime.cache:get(ip)
|
|
|
|
if resp ~= nil then -- we have it in cache
|
|
runtime.logger:debug("'" .. ip .. "' is in cache")
|
|
return resp, nil
|
|
end
|
|
|
|
-- not in cache
|
|
local link = runtime.conf["API_URL"] .. "/v1/decisions?ip=" .. ip
|
|
local resp = {}
|
|
local one, body, code, headers, status
|
|
|
|
if link:find("https://") == 1 then
|
|
https.TIMEOUT = runtime.conf['REQUEST_TIMEOUT']
|
|
one, code, headers, status = https.request{
|
|
url = link,
|
|
headers = {
|
|
['Connection'] = 'close',
|
|
['X-Api-Key'] = runtime.conf["API_KEY"],
|
|
['User-Agent'] = runtime.userAgent
|
|
},
|
|
content_type = 'application/json',
|
|
sink = ltn12.sink.table(resp),
|
|
protocol = "tlsv1",
|
|
options = "all",
|
|
verify = "none"
|
|
}
|
|
else
|
|
body, code, headers = http.request{
|
|
url = link,
|
|
headers = {
|
|
['Connection'] = 'close',
|
|
['X-Api-Key'] = runtime.conf["API_KEY"],
|
|
['User-Agent'] = runtime.userAgent
|
|
},
|
|
content_type = 'application/json',
|
|
sink = ltn12.sink.table(resp),
|
|
create = function()
|
|
local req_sock = socket.tcp()
|
|
req_sock:settimeout(runtime.conf['REQUEST_TIMEOUT'], 't')
|
|
return req_sock
|
|
end
|
|
}
|
|
end
|
|
|
|
resp = table.concat(resp)
|
|
if code~=200 then
|
|
ngx.log(ngx.ERR, "[Crowdsec] Http error " .. code .. " while talking to LAPI (" .. link .. ")") -- API error, don't block IP
|
|
runtime.logger:error("Http error " .. code .. " while talking to LAPI (" .. link .. ")")
|
|
return true, nil
|
|
end
|
|
if resp == "null" then -- no result from API, no decision for this IP
|
|
-- set ip in cache and DON'T block it
|
|
runtime.cache:set(ip, true,runtime.conf["CACHE_EXPIRATION"])
|
|
return true, nil
|
|
end
|
|
-- set ip in cache and block it
|
|
runtime.cache:set(ip, false,runtime.conf["CACHE_EXPIRATION"])
|
|
return false, nil
|
|
end
|
|
|
|
|
|
-- Use it if you are able to close at shuttime
|
|
function csmod.close()
|
|
end
|
|
|
|
return csmod
|