diff --git a/README.md b/README.md index c5bd565..02e33d7 100644 --- a/README.md +++ b/README.md @@ -19,37 +19,8 @@ It is an effective replacement to your NGINX installation, but you can have them coexisting (say, NGINX on port 80, OpenResty being reverse proxied by NGINX on port 8069, though I wouldn't recommend it in production environments). -### how does it work - -aproxy has two "hooks" into openresty: - - initialization of the lua vm - - callback for every incoming request - -initialization will run validation of your configuration file and check -if it is valid. if it is not you will see logs emitted about what failed - -when a request comes in, the scripts declared in the aproxy config file will -be executed sequentially (TODO: ensure order on conf file is chain order). - -each script has two types of callbacks: init and request - -init callbacks are called when initializing the request, so that the script -may do some conversion or transform the config data into a more performant -in-memory structure. - -request callbacks are called on each request, as directed by the main script. -scripts define which paths they want to attach to (via PCRE regex), and so -they can do their own filtering. - -look at `scripts/webfinger_allowlist.lua` for an example of how this looks -in a simple form. - ### actually installing aproxy -- get openresty installed - - keep in mind that the specifics of configuring openresty for a double reverse proxy setup aren't included here. - - instructions here are for aproxy's setup in an existing openresty installation - ```sh mkdir /opt git clone https://gitdab.com/luna/aproxy @@ -57,9 +28,6 @@ git clone https://gitdab.com/luna/aproxy cd aproxy mkdir /etc/aproxy cp ./conf.lua /etc/aproxy/conf.lua - -# keep in mind the default configuration will lead to your users not being discovered at all, -# it is provided as an example for you to modify. $EDITOR /etc/aproxy/conf.lua ``` @@ -83,26 +51,23 @@ http { You need to do the following: - Configure OpenResty package path so that it can call aproxy. - - insert aproxy hooks for initialization and for callbacks on every request + - Insert aproxy as a callback on `location / {` block -It'll look something like this if you use a single `location /` block: +It'll look something like this: ```nginx -# set this to 'on' after you have tested that it actually works. -# once you do that, performance will be increased -# while the friction to quickly debug aproxy will also be increased -lua_code_cache off; -lua_package_path '/opt/?.lua;/opt/aproxy/?.lua;;'; -init_by_lua_block { - require("aproxy.main").init() -} - http { + lua_package_path '/opt/?.lua;/opt/aproxy/?.lua;;'; + server { server_name example.com; location / { + # set this to 'on' after you have tested that it actually works. + # once you do that, performance will be increased + # while the friction to quickly debug aproxy will also be increased + lua_code_cache off; access_by_lua_block { - require("aproxy.main").access() + require("aproxy.main")() } proxy_http_version 1.1; diff --git a/config.lua b/config.lua index 0de4de9..278ee9b 100644 --- a/config.lua +++ b/config.lua @@ -2,12 +2,22 @@ local env_config_path = os.getenv('APROXY_CONFIG_PATH') local DEFAULT_CONFIG_PATH = ".;/etc/aproxy" local config_path = env_config_path or DEFAULT_CONFIG_PATH +function mysplit (inputstr, sep) + if sep == nil then + sep = "%s" + end + local t={} + for str in string.gmatch(inputstr, "([^"..sep.."]+)") do + table.insert(t, str) + end + return t +end + local function findConfigFile() - for _, config_directory in ipairs(string.split(config_path, ";")) do + for _, config_directory in ipairs(mysplit(config_path, ";")) do local possible_config_path = config_directory .. "/" .. "conf.lua" local fd, res = io.open(possible_config_path, "rb") if fd then - log('config found at ' .. possible_config_path) local data = fd:read("*a") fd:close() return data @@ -27,7 +37,7 @@ end local function fakeTableSchema(value_schema) return setmetatable({ __list = true }, { - __index = function () + __index = function (self, key) return value_schema end }) @@ -35,8 +45,8 @@ end local SPECIAL_KEYS = {__list = true} -local function validateSchema(schema, input, errors_in) - local errors = errors_in or {} +local function validateSchema(schema, input, errors) + local errors = errors or {} if schema.__list then -- generate full schema for lists that are same size as input for k, _ in pairs(input) do schema[k] = schema.__schema_value end @@ -95,8 +105,12 @@ local function validateConfigFile(config_object) return all_schema_errors end -local function loadConfigFile(options_in) - local options = options_in or {} +local function writeSchemaErrors(errors, out) + out('sex') +end + +local function loadConfigFile(options) + local options = options or {} local config_file_data = assert(findConfigFile(), 'no config file found, config path: ' .. config_path) local config_file_function = assert(loadstring(config_file_data)) diff --git a/ctx.lua b/ctx.lua index fb43089..78e3239 100644 --- a/ctx.lua +++ b/ctx.lua @@ -1,5 +1,3 @@ -local util = require("util") - function log(msg) ngx.log(ngx.STDERR, tostring(msg)) end @@ -15,14 +13,13 @@ function ctx:loadFromConfig(conf) ctx:loadChain() end - function ctx:loadChain() self.compiled_chain = {} for module_name, module_config in pairs(self._wanted_scripts) do local module = require('scripts.' .. module_name) - local module_config_readonly = table.readonly(module_config) - local module_state = module.init(module_config_readonly) - table.insert(self.compiled_chain, {module, module_config_readonly, module_state}) + local module_state = module.init(module_config) + -- TODO is it possible to make module_config readonly? + table.insert(self.compiled_chain, {module, module_config, module_state}) end end @@ -35,7 +32,7 @@ function ctx:onRequest() local module, module_config, state = unpack(filter) for callback_regex, callback_function in pairs(module.callbacks) do - local match = ngx.re.match(request_uri, callback_regex) + local match, error = ngx.re.match(request_uri, callback_regex) if match then table.insert(callbacks_to_call, {module, callback_function, module_config, state}) end @@ -50,7 +47,6 @@ function ctx:onRequest() ngx.status = status_code ngx.say(body or "request denied") ngx.exit(status_code) - return end end end diff --git a/main.lua b/main.lua index 0470522..b0cf8ff 100644 --- a/main.lua +++ b/main.lua @@ -1,3 +1,11 @@ + +-- function loadConfig() +-- -- TODO load config_path +-- return require("./config.lua") +-- end +-- +-- local config = loadConfig() + local ctx = require('ctx') local config = require('config') require('util') diff --git a/nginx.conf b/nginx.conf index 4904508..4b6e8bf 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,10 +1,10 @@ -lua_code_cache off; init_by_lua_block { require("aproxy.main").init() } server { listen 80; + lua_code_cache off; location / { default_type text/html; diff --git a/scripts/pleroma_restrict_unauthenticated_search.lua b/scripts/pleroma_restrict_unauthenticated_search.lua deleted file mode 100644 index 965f311..0000000 --- a/scripts/pleroma_restrict_unauthenticated_search.lua +++ /dev/null @@ -1,35 +0,0 @@ -local function searchInit(cfg) - return {} -- no ctx -end - -local function searchCallback(cfg, _ctx) - local h, err = ngx.req.get_headers() - - if err == "truncated" then - return 400, 'too many headers' - end - - local authheader = h["authorization"] - - if authheader == nil then - return 401, "requires authentication" - else - return nil - end -end - -return { - name='PleromaRestrictUnauthenticatedSearch', - author='luna@l4.pm', - title='restrict unauth search', - description=[[ - Search can be a DoS vector. restrict it without Authorization header. - Useful for small instances. - ]], - version=1, - init=searchInit, - callbacks = { - ['/api/v2/search'] = searchCallback - }, - config={}, -} diff --git a/scripts/webfinger_allowlist.lua b/scripts/webfinger_allowlist.lua index 7e7355f..41d5c80 100644 --- a/scripts/webfinger_allowlist.lua +++ b/scripts/webfinger_allowlist.lua @@ -1,4 +1,4 @@ -local function webfingerInit(cfg) +function webfingerInit(cfg) local accounts_set = {} for _, account in ipairs(cfg.accounts) do accounts_set["acct:" .. account] = true @@ -6,7 +6,7 @@ local function webfingerInit(cfg) return accounts_set end -local function webfingerCallback(cfg, accounts_set) +function webfingerCallback(cfg, accounts_set) local args, err = ngx.req.get_uri_args() if err == "truncated" then return 400, 'uri args too long' diff --git a/test.lua b/test.lua index ded2270..968117b 100644 --- a/test.lua +++ b/test.lua @@ -64,7 +64,7 @@ function setupTest(module_require_path, input_config) local count = table.pprint(schema_errors) lu.assertIs(count, 0) - local state = module.init(input_config) + state = module.init(input_config) ctx.compiled_chain = { {module, input_config, state} } @@ -74,9 +74,9 @@ end function onRequest() ctx:setWantedScripts() - local context = require('ctx') + local ctx = require('ctx') do - context:onRequest() + ctx:onRequest() end end diff --git a/util.lua b/util.lua index 5c0b74f..4db2229 100644 --- a/util.lua +++ b/util.lua @@ -4,11 +4,11 @@ function table.len(t) return count end -function table.pprint(t, options_in, ident_in, total_count_in) - local ident = ident_in or 0 - local total_count = total_count_in or 0 +function table.pprint(t, options, ident, total_count) + local ident = ident or 0 + local total_count = total_count or 0 - local options = options_in or {} + local options = options or {} local print_function = options.call or print if type(t) == 'table' then local count = 0 @@ -18,7 +18,7 @@ function table.pprint(t, options_in, ident_in, total_count_in) total_count = table.pprint(v, options, ident + 1, total_count) end if count == 0 then - print_function('{}') + --print('') end else print_function(string.rep('\t', ident) .. tostring(t)) @@ -26,26 +26,3 @@ function table.pprint(t, options_in, ident_in, total_count_in) end return total_count end - -function table.readonly(t) - return setmetatable({}, { - __index = t, - __newindex = function () - error("Attempt to modify read-only table") - end, - __metatable = false - }); -end - -function string.split(inputstr, sep) - if sep == nil then - sep = "%s" - end - local t={} - for str in string.gmatch(inputstr, "([^"..sep.."]+)") do - table.insert(t, str) - end - return t -end - -