From 52ca6cea21569c6bdf9dc175ef4113e511645d7b Mon Sep 17 00:00:00 2001 From: simon987 Date: Mon, 2 Mar 2020 09:00:33 -0500 Subject: [PATCH] Update readme & quick cleanup --- CMakeLists.txt | 2 +- README.md | 22 ++++++++++++++ build.sh | 4 +-- config | 10 +++---- library.c => ngx_http_js_challenge.c | 41 +++++++++++++-------------- throughput.png | Bin 0 -> 27526 bytes 6 files changed, 50 insertions(+), 29 deletions(-) rename library.c => ngx_http_js_challenge.c (88%) create mode 100644 throughput.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 71663a1..ee94831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(nginx_js C) set(CMAKE_C_STANDARD 11) -add_library(nginx_js SHARED library.c) +add_library(nginx_js SHARED ngx_http_js_challenge.c) target_include_directories( nginx_js diff --git a/README.md b/README.md index ff84b55..8d4add0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,26 @@ +## ngx_http_js_challenge_module + +![GitHub](https://img.shields.io/github/license/simon987/ngx_http_js_challenge_module.svg) +[![CodeFactor](https://www.codefactor.io/repository/github/simon987/ngx_http_js_challenge_module/badge)](https://www.codefactor.io/repository/github/simon987/ngx_http_js_challenge_module) +[![Development snapshots](https://ci.simon987.net/app/rest/builds/buildType(JsChallenge_Build)/statusIcon)](https://files.simon987.net/artifacts/JsChallenge/Build/) + +Simple javascript proof-of-work based access for Nginx with virtually no overhead. + +Easy installation: just add `load_module /path/to/ngx_http_js_challenge_module.so;` to your +`nginx.conf` file and follow the [configuration instructions](#configuration). + + +![throughput.png](throughput.png) + + +### Configuration + +//todo + + +### Build from source + //todo ```bash diff --git a/build.sh b/build.sh index 90283d2..7e7fc64 100755 --- a/build.sh +++ b/build.sh @@ -14,7 +14,7 @@ make modules #cp objs/ "${WD}" ) -#rm /test/*.so -mv /home/simon/Downloads/nginx-1.16.1/objs/ngx_http_hello_world_module.so /test/module.so +rm /test/*.so +mv /home/simon/Downloads/nginx-1.16.1/objs/ngx_http_js_challenge_module.so /test/module.so chown -R www-data /test/ systemctl restart nginx diff --git a/config b/config index 37f5e68..f20118b 100644 --- a/config +++ b/config @@ -1,11 +1,11 @@ -ngx_addon_name=ngx_http_hello_world_module +ngx_addon_name=ngx_http_js_challenge_module if test -n "$ngx_module_link"; then ngx_module_type=HTTP - ngx_module_name=ngx_http_hello_world_module - ngx_module_srcs="$ngx_addon_dir/library.c" + ngx_module_name=ngx_http_js_challenge_module + ngx_module_srcs="$ngx_addon_dir/ngx_http_js_challenge.c" . auto/module else - HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module" - NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/library.c" + HTTP_MODULES="$HTTP_MODULES ngx_http_js_challenge_module" + NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_js_challenge.c" fi \ No newline at end of file diff --git a/library.c b/ngx_http_js_challenge.c similarity index 88% rename from library.c rename to ngx_http_js_challenge.c index b6468f4..7b992c9 100644 --- a/library.c +++ b/ngx_http_js_challenge.c @@ -1,14 +1,14 @@ #include #include "ngx_http.c" -static ngx_int_t ngx_http_hello_world(ngx_conf_t *cf); +static ngx_int_t ngx_http_js_challenge(ngx_conf_t *cf); static char *setup1(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_js_challenge_handler(ngx_http_request_t *r); -static ngx_command_t ngx_http_hello_world_commands[] = { +static ngx_command_t ngx_http_js_challenge_commands[] = { {ngx_string("hello_world"), @@ -16,22 +16,19 @@ static ngx_command_t ngx_http_hello_world_commands[] = { // NGX_CONF_FLAG for boolean NGX_HTTP_LOC_CONF | NGX_HTTP_SRV_CONF | NGX_CONF_NOARGS, - setup1, /* configuration setup function */ 0, /* No offset. Only one context is supported. */ 0, /* No offset when storing the module configuration on struct. */ NULL}, - - ngx_null_command /* command termination */ + ngx_null_command }; -/* The hello world string. */ -//static u_char ngx_hello_world[] = HELLO_WORLD; - -/* The module context. */ -static ngx_http_module_t ngx_http_hello_world_module_ctx = { +/** + * Module context + */ +static ngx_http_module_t ngx_http_js_challenge_module_ctx = { NULL, /* preconfiguration */ - ngx_http_hello_world, /* postconfiguration */ + ngx_http_js_challenge, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ @@ -39,15 +36,16 @@ static ngx_http_module_t ngx_http_hello_world_module_ctx = { NULL, /* create server configuration */ NULL, /* merge server configuration */ + //todo NULL, /* create location configuration */ NULL /* merge location configuration */ }; /* Module definition. */ -ngx_module_t ngx_http_hello_world_module = { +ngx_module_t ngx_http_js_challenge_module = { NGX_MODULE_V1, - &ngx_http_hello_world_module_ctx, /* module context */ - ngx_http_hello_world_commands, /* module directives */ + &ngx_http_js_challenge_module_ctx, /* module context */ + ngx_http_js_challenge_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ @@ -60,7 +58,7 @@ ngx_module_t ngx_http_hello_world_module = { }; __always_inline -void buf2hex(const unsigned char *buf, size_t buflen, char *hex_string) { +static void buf2hex(const unsigned char *buf, size_t buflen, char *hex_string) { static const char hexdig[] = "0123456789ABCDEF"; const unsigned char *p; @@ -90,7 +88,7 @@ static const u_char JS_SOLVER[] = " document.cookie = 'res=' + c + i + ';';" " window.location.reload();" " break;" - " };" + " }" " i++;" " }" "Hello"; @@ -155,6 +153,7 @@ int verify_response(int32_t bucket, ngx_str_t addr, const char *secret, ngx_str_ * ^ offset 24 */ + //todo also check if the response is too large if (response.len <= SHA1_STR_LEN) { return -1; } @@ -199,7 +198,7 @@ int get_cookie(ngx_http_request_t *r, ngx_str_t *name, ngx_str_t *value) { return -1; } -static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r) { +static ngx_int_t ngx_http_js_challenge_handler(ngx_http_request_t *r) { //TODO: If the bucket is less than 5sec away from the next one, accept both current and latest bucket @@ -245,11 +244,11 @@ static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r) { static char *setup1(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { // ngx_http_core_loc_conf_t *clcf; /* pointer to core location configuration */ // clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); -// clcf->handler = ngx_http_hello_world_handler; +// clcf->handler = ngx_http_js_challenge_handler; return NGX_CONF_OK; } -static ngx_int_t ngx_http_hello_world(ngx_conf_t *cf) { +static ngx_int_t ngx_http_js_challenge(ngx_conf_t *cf) { ngx_http_handler_pt *h; ngx_http_core_main_conf_t *cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); @@ -260,7 +259,7 @@ static ngx_int_t ngx_http_hello_world(ngx_conf_t *cf) { return NGX_ERROR; } - *h = ngx_http_hello_world_handler; + *h = ngx_http_js_challenge_handler; return NGX_OK; } diff --git a/throughput.png b/throughput.png new file mode 100644 index 0000000000000000000000000000000000000000..34d04f54794399ebf778484c1b2d64ae3e75290c GIT binary patch literal 27526 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