init work remote API

This commit is contained in:
bunkerity 2021-10-02 20:29:50 +02:00
parent 5d94cc8f43
commit 64aa9c2530
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
6 changed files with 165 additions and 0 deletions

View File

@ -3,6 +3,7 @@ init_by_lua_block {
local dataloader = require "dataloader"
local logger = require "logger"
local cjson = require "cjson"
local remoteapi = require "remoteapi"
local use_redis = {% if USE_REDIS == "yes" %}true{% else %}false{% endif +%}
@ -12,6 +13,8 @@ local use_tor_exit_nodes = {% if has_value("BLOCK_TOR_EXIT_NODE", "yes") %}true{
local use_user_agents = {% if has_value("BLOCK_USER_AGENT", "yes") %}true{% else %}false{% endif +%}
local use_referrers = {% if has_value("BLOCK_REFERRER", "yes") %}true{% else %}false{% endif +%}
local use_remote_api = {% if has_value("USE_REMOTE_API", "yes") %}true{% else %}false{% endif +%}
if not use_redis then
if use_proxies then
dataloader.load_ip("/etc/nginx/proxies.list", ngx.shared.proxies_data)
@ -72,4 +75,44 @@ for dir in p:lines() do
end
p:close()
-- Remote API
if use_remote_api then
-- Save server
ngx.shared.remote_api:set("server", "{{ REMOTE_API_SERVER }}", 0)
-- Save version
local f = io.open("/opt/bunkerized-nginx/VERSION", "r")
ngx.shared.remote_api:set("version", f:read("*all"), 0)
f:close()
-- Save and ask a machine ID if needed
local f = io.open("/opt/bunkerized-nginx/cache/machine.id", "rw")
if f == nil then
local res, id = remoteapi.register()
if not res then
logger.log(ngx.ERR, "REMOTE API", "Can't register to the remote API")
else
logger.log(ngx.ERR, "REMOTE API", "Successfully registered to the remote API")
f:write(data)
ngx.shared.remote_api:set("id", data, 0)
end
else
logger.log(ngx.ERR, "REMOTE API", "*NOT AN ERROR* Using existing machine ID from cache")
id = f:read("*all")
end
f:close()
-- Test the machine ID
if id ~= nil then
local res, pong = remoteapi.ping()
if not res or pong ~= "pong" then
logger.log(ngx.ERR, "REMOTE API", "Ping failed, the remote server may be down or your machine ID is invalid")
else
logger.log(ngx.ERR, "REMOTE API", "*NOT AN ERROR* Ping successful")
end
end
end
}

View File

@ -91,6 +91,7 @@ http {
{% if has_value("USE_BAD_BEHAVIOR", "yes") %}lua_shared_dict behavior_ban 10m;{% endif +%}
{% if has_value("USE_BAD_BEHAVIOR", "yes") %}lua_shared_dict behavior_count 10m;{% endif +%}
lua_shared_dict plugins_data 10m;
{% if has_value("USE_REMOTE_API", "yes") %}lua_shared_dict remote_api 1m;{% endif +%}
# shared memory zone for limit_req
{% if has_value("USE_LIMIT_REQ", "yes") %}limit_req_zone $binary_remote_addr$uri zone=limit:{{ LIMIT_REQ_CACHE }} rate={{ LIMIT_REQ_RATE }};{% endif +%}

View File

@ -1,5 +1,7 @@
log_by_lua_block {
local logger = require "logger"
-- bad behavior
local use_bad_behavior = {% if USE_BAD_BEHAVIOR == "yes" %}true{% else %}false{% endif +%}
local behavior = require "behavior"
@ -12,4 +14,20 @@ if use_bad_behavior then
behavior.count(bad_behavior_status_codes, bad_behavior_threshold, bad_behavior_count_time, bad_behavior_ban_time)
end
-- remote API
local use_remote_api = {% if USE_REMOTE_API == "yes" %}true{% else %}false{% endif +%}
local remoteapi = require "remoteapi"
if use_remote_api then
if ngx.status == ngx.HTTP_FORBIDDEN then
-- TODO check if IP is global + good reason
local res, data = remoteapi.ip(ngx.var.remote_addr, "other")
if res then
logger.log(ngx.NOTICE, "REMOTE API", "Successfully reported ip " .. ngx.var.remote_addr)
else
logger.log(ngx.ERR, "REMOTE API", "Error while reporting ip " .. ngx.var.remote_addr .. " : " .. data)
end
end
end
}

View File

@ -749,6 +749,10 @@ fi
echo "[*] Copy bunkerized-nginx"
do_and_check_cmd cp /tmp/bunkerized-nginx/helpers/bunkerized-nginx /usr/local/bin
# Copy VERSION
echo "[*] Copy VERSION"
do_and_check_cmd cp /tmp/bunkerized-nginx/VERSION /opt/bunkerized-nginx
# Replace old nginx.service file
if [ "$OS" != "alpine" ] ; then
do_and_check_cmd mv /lib/systemd/system/nginx.service /lib/systemd/system/nginx.service.bak

81
lua/remoteapi.lua Normal file
View File

@ -0,0 +1,81 @@
local M = {}
local http = require "resty.http"
local cjson = require "cjson"
local logger = require "logger"
function M.send(method, url, data)
local httpc, err = http.new()
if not httpc then
logger.log(ngx.ERR, "REMOTE API", "Can't instantiate HTTP object : " .. err)
return false, nil, nil
end
local res, err = httpc:request_uri(ngx.shared.remote_api:get("server") .. url, {
method = method,
body = cjson.encode(data),
headers = {
["Content-Type"] = "application/json",
["User-Agent"] = "bunkerized-nginx/" .. data["version"]
}
})
if not res then
logger.log(ngx.ERR, "REMOTE API", "Can't send HTTP request : " .. err)
return false, nil, nil
end
if res.status ~= 200 then
logger.log(ngx.WARN, "REMOTE API", "Received status " .. res.status .. " from API : " .. res.body)
end
return true, res.status, cjson.decode(res.body)["data"]
end
function M.gen_data(use_id, data)
local all_data = {}
if use_id then
all_data["id"] = ngx.shared.remote_api:get("id")
end
all_data["version"] = ngx.shared.remote_api:get("version")
for k, v in pairs(data) do
all_data[k] = v
end
return all_data
end
function M.register()
local request = {}
local res, status, data = M.send("POST", "/register", M.gen_data(false, request))
if res and status == 200 then
return true, data
end
return false, data
end
function M.ping()
local request = {}
local res, status, data = M.send("GET", "/ping", M.gen_data(true, request))
if res and status == 200 then
return true, data
end
return false, data
end
function M.ip(ip, reason)
local request = {
["ip"] = ip,
["reason"] = reason
}
local res, status, data = M.send("POST", "/ip", M.gen_data(true, request))
if res and status == 200 then
return true, data
end
return false, data
end
function M.db()
local request = {}
local res, status, data = M.send("GET", "/db", M.gen_data(true, request))
if res and status == 200 then
return true, data
end
return false, data
end
return M

View File

@ -1274,6 +1274,24 @@
"regex": "^([A-Za-z0-9\\-\\.\\_]+|.{0})$",
"type": "text"
}
{
"context": "multisite",
"default": "no",
"env": "USE_REMOTE_API",
"id": "use-remote-api",
"label": "Use a remote service for enhanced security",
"regex": "^(yes|no)$",
"type": "checkbox"
},
{
"context": "global",
"default": "",
"env": "REMOTE_API_SERVER",
"id": "remote-api-server",
"label": "The URL of the remote service",
"regex": "^.*$",
"type": "text"
}
]
},
"nginx": {