├── lua-resty-ddos-v0.1.0-1.rockspec ├── LICENSE ├── lib └── resty │ └── ddos.lua └── README.md /lua-resty-ddos-v0.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "lua-resty-ddos" 2 | version = "v0.1.0-1" 3 | 4 | source = { 5 | url = "git://github.com/satrobit/lua-resty-ddos.git" 6 | } 7 | 8 | description = { 9 | summary = "A sample module to ddos mitigation in OpenResty", 10 | homepage = "https://github.com/satrobit/lua-resty-ddos", 11 | license = "MIT", 12 | maintainer = "amirkekh@gmail.com" 13 | } 14 | 15 | dependencies = { 16 | "lua >= 5.1", 17 | "lua-resty-jwt >= 0.2.0-0", 18 | "lua-resty-cookie >= 0.1.0-1" 19 | } 20 | 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["resty.ddos"] = "lib/resty/ddos.lua" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Amir Keshavarz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/resty/ddos.lua: -------------------------------------------------------------------------------- 1 | local cjson = require "cjson" 2 | local jwt = require "resty.jwt" 3 | local ck = require "resty.cookie" 4 | 5 | local function return_rf_cookie(cookie, key) 6 | 7 | -- Make JWT 8 | local jwt_token = jwt:sign(key, 9 | { 10 | header={typ="JWT", alg="HS256"}, 11 | payload={remote_addr=ngx.var.remote_addr} 12 | }) 13 | 14 | -- set cookie 15 | local ok, err = cookie:set({key = "Ref", value = jwt_token}) 16 | if not ok then 17 | ngx.log(ngx.ERR, err) 18 | return 19 | end 20 | 21 | -- Return to the same page with the Ref cookie included 22 | return ngx.redirect(ngx.var.request_uri) 23 | 24 | end 25 | 26 | 27 | local ok, new_tab = pcall(require, "table.new") 28 | if not ok then 29 | new_tab = function (narr, nrec) return {} end 30 | end 31 | 32 | 33 | local _M = new_tab(0, 155) 34 | _M._VERSION = '0.1' 35 | 36 | 37 | function _M.run(key) 38 | 39 | local cookie, err = ck:new() 40 | if not cookie then 41 | ngx.log(ngx.ERR, err) 42 | return 43 | end 44 | 45 | 46 | -- get Ref cookie 47 | local Ref_field, err = cookie:get("Ref") 48 | if not Ref_field then 49 | return return_rf_cookie(cookie, key) 50 | end 51 | 52 | -- Verify the Ref 53 | local jwt_obj = jwt:verify(key, Ref_field) 54 | 55 | if jwt_obj.verified ~= true or jwt_obj.payload.remote_addr ~= ngx.var.remote_addr then 56 | return return_rf_cookie(cookie, key) 57 | end 58 | 59 | 60 | end 61 | 62 | return _M 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Name 2 | ==== 3 | 4 | lua-resty-ddos - This library uses Cookie Validation to detect bots from real users. 5 | 6 | Table of Contents 7 | ================= 8 | 9 | * [Name](#name) 10 | * [Status](#status) 11 | * [Synopsis](#synopsis) 12 | * [Methods](#methods) 13 | * [run](#run) 14 | * [Installation](#installation) 15 | * [Authors](#authors) 16 | 17 | Status 18 | ====== 19 | 20 | This library is WIP. Please don't use in production! 21 | 22 | Synopsis 23 | ======== 24 | ```lua 25 | lua_package_path "/path/to/lua-resty-ddos/lib/?.lua;;"; 26 | 27 | server { 28 | location / { 29 | rewrite_by_lua ' 30 | local ddos = require "resty.ddos" 31 | ddos.run("some-key") 32 | '; 33 | } 34 | } 35 | ``` 36 | 37 | Methods 38 | ======= 39 | 40 | [Back to TOC](#table-of-contents) 41 | 42 | run 43 | --- 44 | `syntax: ddos:run(key)` 45 | 46 | Runs the module with the provided key to use in JWT. 47 | 48 | [Back to TOC](#table-of-contents) 49 | 50 | Installation 51 | ============ 52 | 53 | Run the following in the module directory: 54 | ``` 55 | luarocks make 56 | ``` 57 | 58 | You need to configure 59 | the [lua_package_path](https://github.com/chaoslawful/lua-nginx-module#lua_package_path) directive to 60 | add the path of your `lua-resty-ddos` source tree to ngx_lua's Lua module search path, as in 61 | 62 | ``` 63 | http { 64 | lua_package_path "/path/to/lua-resty-ddos/lib/?.lua;;"; 65 | ... 66 | } 67 | ``` 68 | 69 | 70 | and then load the library in Lua: 71 | 72 | ```lua 73 | local ck = require "resty.ddos" 74 | ``` 75 | 76 | [Back to TOC](#table-of-contents) 77 | 78 | Authors 79 | ======= 80 | 81 | Amir Keshavarz . 82 | 83 | [Back to TOC](#table-of-contents) 84 | --------------------------------------------------------------------------------