{"id":19174637,"url":"https://github.com/equalitie/banjax","last_synced_at":"2026-06-20T06:30:18.039Z","repository":{"id":10705682,"uuid":"12951693","full_name":"equalitie/banjax","owner":"equalitie","description":"Apache Traffic Server Plugin performing various anti-DDoS measures","archived":false,"fork":false,"pushed_at":"2021-10-11T21:41:48.000Z","size":8514,"stargazers_count":35,"open_issues_count":19,"forks_count":20,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-01-04T01:36:50.781Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/equalitie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-09-19T15:12:47.000Z","updated_at":"2024-01-05T23:36:10.000Z","dependencies_parsed_at":"2022-09-22T21:42:07.174Z","dependency_job_id":null,"html_url":"https://github.com/equalitie/banjax","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/equalitie%2Fbanjax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/equalitie%2Fbanjax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/equalitie%2Fbanjax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/equalitie%2Fbanjax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/equalitie","download_url":"https://codeload.github.com/equalitie/banjax/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240254182,"owners_count":19772386,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T10:18:36.838Z","updated_at":"2026-06-20T06:30:17.976Z","avatar_url":"https://github.com/equalitie.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"Banjax\n======\n\nCircleCI status:\n  * master [![CircleCI](https://circleci.com/gh/equalitie/banjax/tree/master.svg?style=svg\u0026circle-token=86713a4ce3cf55d0c00b3ac62943f7fecd8a3e2a)](https://circleci.com/gh/equalitie/banjax/tree/master)\n  * devel [![CircleCI](https://circleci.com/gh/equalitie/banjax/tree/devel.svg?style=svg\u0026circle-token=86713a4ce3cf55d0c00b3ac62943f7fecd8a3e2a)](https://circleci.com/gh/equalitie/banjax/tree/devel)\n\nApache Traffic Server Plugin performing various anti-DDoS measures\n\nCopyright 2017 eQualit.ie\n\nBanjax is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as\npublished by the Free Software Foundation, either version 3 of the\nLicense, or (at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see `\u003chttp://www.gnu.org/licenses/\u003e`.\n\nInstallation\n============\n\nInstallation from so file\n-------------------------\nRequirements:\n\nFollowing standard Debian packages are required by banjax\n\n     apt-get install libzmq libyaml-cpp-dev\n\nGoogle re2 regex engine:\n\n        git clone https://github.com/google/re2\n        cd re2\n        make test\n        make install\n        make testinstall\n\nCopy banjax.so file in:\n\n     /usr/local/trafficserver/modules\n\nCopy banjax.conf file to the folder of your choice. The default directroy that banjax is going to look for banjax.conf is ATS default plugin directory, for example:\n\n     /usr/local/trafficserver/modules/banjax/\n\nAdd a line\n\n    banjax.so [/path/to/the/folder/where/banjax.conf/resides]\n\nto\n\n    /usr/local/trafficserver/conf/plugins.conf\n\nIf you omit the path arguement, banjax will look into ATS plugin directory for banjax.conf.\n\nInstallation from source\n------------------------\nStaging branch always contain the most recent semi stable source. Master branch is laging far behind the current development.\n\nBanjax is using automake frame work, to make and install banjax, cd into banjax directory, assuming that the plugin directory of the traffic server is\n\n    /usr/local/trafficserver/modules\n\nYou need the following dev deb package to compile banjax in addition to libre2 described above:\n\n    apt-get install build-essential git libzmq-dev unzip automake libtool pkg-config libssl-dev libboost-dev\n\nIf you do not have ATS installed, you need to install it as well:\n\n    apt-get install trafficserver-dev\n\nnotes that banjax require traffic server version 4 or higher and the build project might fails if you use earlier version provided by your distribution.\n\nClone banjax repo\n\n    git clone https://github.com/equalitie/banjax\n\nMove to the banjax folder\n\n    cd \u003cwhere you want banjax to be built\u003e\n\ninvoke following sequences of command\n\n    cmake \u003cbanjax directory\u003e\n    make\n    cp libbanjax.a /usr/local/trafficserver/modules/\n\nTesting:\n--------\nrunning unittests in banjax/test will run the unittests corresponding to banjax filters.\n\nBehavior tests needs to be run as root. You also need to add the following line to conf/remap.conf\n\n```\nregex_map   http://^(www\\.)?127.0.0.1$/ ORIGIN_URL\n```\n\nFor example, if the http server is running on the same machine, listening on port 8000, you should add:\n\n```\nregex_map   http://^(www\\.)?127.0.0.1$/ http://127.0.0.1:8000/\n```\n\nYou should also need to have write access to the folder where http origin server websites from.\n\n```\nusage: banjax_behavior_test.py [-h] [--banjax-dir BANJAX_DIR]\n                               [--banjax-test-dir BANJAX_TEST_DIR]\n                               [--http-doc-root HTTP_DOC_ROOT]\noptional arguments:\n    -h, --help shows help\n    --banjax-dir banjax config folder (default: /usr/local/trafficserver/modules/banjax/)\n    --banjax-test-dir (default: current folder)\n    --http-doc-root origin website folder (default: /var/www)\n```\n\n\n```\ncd test\npython banjax_behavior_test\n```\n\nAvailable Filters\n=================\nCurrently 4 filters are implemented in Banjax. One can configure each filter behavior in banjax.conf. The configuration of each filter is accomplished via yaml, with a \"challenger\" and a \"regex_banner\" dictionary existing in the configuration. The \"challenges\" list under \"challenger\" contains the challenges to be proffered to users\".\n\nThe order that each filter configuration appears in banjax.conf matters and  determine the order that banjax.conf run the filter. For example, there is no point to put white_lister filter at the end.\n\nwhite_lister\n============\n\nWhite listed IPs do not go through any other filter configured with lower priority than white_lister. For example the ip address of  monitoring programs such as nagios needs to be white listed, so bot stoppers such as challenger does not prevent them from their duty. To white list an ip range, such as Google bots or a subnet use CIDR (IP/number of matching bits) notation.\n\nWhite listed ips need to be added to the white_listed_ips array.\n---------------\n    white_lister:\n      white_listed_ips:\n        - 192.168.1.1\n        - 10.0.0.1/24\n\nregex_banner\n============\n\nregex_banner bans each request based on the specific rate they are matching regexes.\n\nEach request consists of the following parts\n\nMETHOD uri host UA\n\nsuch as\n\nGET http://wiki/ equalit.ie \"Firefox 1.0.1\"\n\nCurrently the hit rate computed for each regex in the sense that it is the  number of time that a request matches each regexes, hence for example if a request matches two different regexes, it counts once as hit for each regexes.\n\nTo configure a new regex, you need to add a new rule in to the banned_regexes array. fields of the rule should be specified in yaml format (using colon)\n\nrule: human readable explanation of what rule is about. It is *not* optional.\nregex: a regex to match the whole request. Pay attention that you need to put \\ when you are intending to have one \\ in the regex. Also there are characters which do not get matched to \".\" so you need to use \"[\\s\\S]\" instead.\n\ninterval: The span of time in seconds when you want banjax keep record of the hit.\n\nhits_per_interval: the number of hit per interval that results in banning\n\nBanjax bans based on 1/1000*hit_per_interval per millisecond rate. Hence it does not wait for number of hits to reach hits_per_interval, as soon as an ip reach the rate of 1/1000*hit_per_interval per millisecond it will get banned.\n\nIf you want to ban a specific regex in first apperance you need to set hits_per_interval = 0\n\nSample Attacks:\n---------------\n* If the bot net is alway requesting \"http://host.com/vmon\" you can use the first rule.\n* If a bot is requesting pages with rate of higher than 100 request per minute and you want to ban any IP with higher requests than that use the second rule.\n\n---------------\n    regex_banner :\n      - rule: 'too much veggie monster'\n        regex: '.*vmon[\\\\s\\\\S]*'\n        interval: 1;\n        hits_per_interval: 0\n      - rule: dos\n        regex: '[\\\\s\\\\S]*'\n        interval: 60\n        hits_per_interval: 100;\n\nHow does regex_banner works\n---------------------------\nRegex Banner uses the following method to keep the approximate rate of hit of each IP without storing every instance of hit.\n\nRegex banner stores the hit rate in hit/millisecond and keep the rate for the given interval and the time stamp for the beginning of the interval. Once a new hit comes in:\n\nIf the beginning time stamp till the hit time stamps is larger than the interval then it will subtracts (time stamp - now)/interval* rate from the rate.\n\nIndependently it sums the current rate with 1/(interval*1000) (rate computed in times per millisecond).\n\nChallenger\n==========\nChallenger serves different challenges to confirm the legitimacy of the client for the requested access (read, edit, etc). Currently partial inverse SHA256 , Captcha puzzles or password authentication are supported. The hash solution of the puzzle is also sent along side with the ip of the requester. It is mainly meant to be a cache busting prevention mechanism as well as cache-less access to the website.\n\nkey: is the string from which MAC key that is used to authenticate the cookie is being used. MAC prevents the attacker from tampering with the challenge or reuse its solution for different bots.\n\ndifficulty: it determines the number of leading zeros that the  SHA256(solution) at least should have in binary representation. Hence adding this value by 1 doubles the difficulty of the challenge.\n\nFor each host then the user needs to specifies the following parameters:\n\nname: the host name as it appears in the url, \"www.host.com\" and \"host.com\" are treated as two different hosts and needs two separate config records.\n\nvalidity_period: determine how often the challenger should re-challenge a client in seconds. When under cache-busting attack, it is advisable to decrease this number. Also because the solution is cookie based each client will be challenged once for each website.\n\nchallenge_type: can be \"captcha\", \"sha_inverse\" or \"auth\" at the moment. Note that currently banjax can only challenge each client using one challenge. Practically, this means that you should always define \"auth\" challenge before sha_inv or captcha challenge for a particular host.   \n\nchallenge: the name of the html file that contains the challenge. by default it is \"captcha.html\", \"solver.html\" and \"auth.html\", however user can copy these files (residing in modules/banjax/) to customize the appearance for example for localization.\n\nno_of_fails_to_ban (optional): If specifies, challenger reports the ip to swabber, if the ip asks for the challenge this many times and fails to solve it (ip needs two request per captcha challenges).\n\npassword_hash (mandatory for auth): B64 encoded of SHA256 of the password that needs to be verified by challenger.\n\nmagic_word (mandatory for auth): the word that need to appear in the requested url in order for the challenger to serve the auth challenge token, to enable the client to generate the auth cookie.\n\nSample Attacks:\n---------------\n* If www.equalit.ie is under cache busting attack and you want to prevent the bots from reaching the origin you can use the first set of host rules, so challenger serves captcha before reaching to the origin. Note that you need a new set of host rule for equalit.ie if both www.equalit.ie and equalit.ie are resolving to your website.\n\n* If wiki.deflect.ca is being attacked by a botnet that is not able to run Java Script or you would like to slow down each bot request by making them solve a problem before being served, at the same time you want to ban anybody who failed to solve 10 problems, you can use the second rule.\n\n---------------\n    challenger:\n      key : \"thisisakey\"\n      difficulty : 4 # Number of leading bits in the inverse sha challenge to be zero\n      challenges:\n        - name : \"www.equalit.ie_captcha\"\n          domains:\n           - \"equalit.ie\"\n           - \"www.equalit.ie\n          challenge_type : \"captcha\"\n          challenge : \"captcha.html\"\n          no_of_fails_to_ban: 20\n          validity_period : 86400\n          \n        - name : \"wiki.deflect.ca_sha\"\n          challenge_type : \"sha_inverse\"\n          challenge : \"solver.html\"\n          no_of_fails_to_ban : 10\n          validity_period : 120\n          \n         - name : \"example.com_auth\"\n           domains:\n             - \"example.com\"\n             - \"www.example.com\"\n           challenge_type : \"auth\"\n           challenge : \"auth.html\"\n           password_hash : \"BdZitmLkeNx6Pq9vKn6027jMWmp63pJJowigedwEdzM=\"\n           # This can either be a single entry or a list of entries\n           # Any URL that matches this regular expression will be protected by authorization.\n           magic_word : \"iec1OoghAogh0ionieJaot4p\"\n           # As a list of entries\n           #magic_word :\n           #  - \"foo\"\n           #  - \"bar\"\n           validity_period : 1200\n           no_of_fails_to_ban : 10\n\n\nBotSniffer\n==========\nBot sniffer reports the detail of each transaction to BotBanger to test the requester against a pre-learned model to see if the behavior of the ip resembles a bot. The data are encrypted using AES-GCM mode with subscription \"botbanger_log\" in clear text. The config is the zmq socket port where BotSniffer should publish the log into as well as the passphrase. The passphrase will be hashed by SHA256 to generate the encryption key for 32-byte AES-GCM. The encrypted token is organized as follows:\n\n    12BytesIV|ENCRYPTEDDATE|16BytesAuthtoken\n\nWith | stand for concatination with no separator.\n\nSample Attacks:\n---------------\n* If you have Learn2ban model for your attack and Botbanger is running on your edge listening to port 22621 then you can add the following to banjax.conf to inform BotBanger about the requests to the edge\n\n---------------\n    bot_sniffer :\n        botbanger_port: 22621\n        key: \"somebodysbeenworkingindark!\"\n\n\n\nSwabber\n=======\nThis is a configuration entry for the Swabber interface. all fields are optional\n\n    swabber:\n      server: 127.0.0.1\n      port: 22620\n      grace_period: 600\n\nserver: is the ip of the interface which Swabber is listening on. default is \"*\".\nport: is the port that swabber is listening on, default is \"22620\"\ngrace_period: swabber interface only report an ip to swabber only if: 1) ip is reported for banning by a filter and  \"grace_period\" seconds has passed since the first request for banning. if grace_period is set to 0 (when edges are too stressed) the ip is reported upon first banning request. default is 0.\n\nNote that all other filters are still in effect next time the reported ip send a new request and so it means that the request does not reach the origin. However, challenger and auth still provide challenges. If it is desired that no filter get engaged with the reported ip Denialator filter should be activated.\n\nSwabber interface records its log activities in\n\n    trafficserver/logs/ban_ip_list.log\n\nThe general format of swabber interface log is as follows:\n\n    [bot_ip], [time], [banning_reason], [flagged/banned]\n\nExample:\n\n    127.0.0.1, [2016-01-22T22:18:56], matched regex rule deflectsecret, GET, http:///secretpage, deflect.ca:8080, \"Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 conkeror/1.0pre1\", flagged\n    127.0.0.1, [2016-01-22T22:28:22], failed challenge deflectc-captcha for host deflect.ca:8080 10 times, \"Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 conkeror/1.0pre1\" asking for http   :///__validate/, flagged\n    127.0.0.1, [2016-01-22T22:28:46], flagged on 1453501702, grace period passed. reported by denialator, banned\n\nflagged/banned:\n  flagged: The IP is reported to swabber interface by a filter for the first time. it is not reported to swabber for banning.  until grace_period of the swabber is passed.\n  banned: The grace_period of the swabber for this IP is passed since it was flagged first and as such it is reported to the swabber.\n\nNote that the flagged line in the banjax log only appears once, the first time the ip is flagged. The all subsequent requests for banning does not appear in the log till it gets banned.\n\n  banning_reason\n\nEach filter send the reason by itself and not all filters have access to the same data, the banning filters log formats are as follows:\n\nregex_manager:\n\n    matched regex rule [rule_name], [METHOD], \"[URL]\", [HOST], \"[UA]\"\n\nchallenger:\n\n    failed challenge [challenge name]  [number of failures] times, \"[URL]\", [HOST], \"[UA]\"\n\ndenialator:\n\n    flagged on [flagged time in epoch], grace period passed. reported by denialator\n\nnotes that all internal double quotes (\") for the \"[URL]\" and \"[UA]\" is escaped (replace by \\\")\n\nDenialator\n==========\nTo activate Denialator following line need to put in the config.\n\n    denialator:\n\nUpon activation denialator checks if the ip previously has been reported for banning and if such it denies access to the ip. The denialator will report the ip to swabber again once it the ip visits after that the grace period is finished. To disengage all filters from dealing with reported ip, denialator priority need to be set to 1 or 2.\n\nHow To Write A Filter\n=====================\n\nTo add your own new filter to banjax you need to follow these steps:\n\n1) Inherit from BanjaxFilter.\n2) Add the constant representing your filter to the FilterIDType enum in filter_list.h e.g.\n   WHITE_LISTER_FILTER_ID\n\n3) Add the constant filter name in filter_list.h, e.g.:\n   const std::string WHITE_LISTER_FILTER_NAME = \"white_lister\";\n\n4) Write the constructor to set the filter name and id.\n\n5) Override the load_config and execute to load the config of your filter and execute the operation your filter suppose to do. Override\n\n6) Override requested_info to return the flags of all parts your filter need to analysis the request. for example:\n  uint64_t requested_info() { return\n      TransactionMuncher::IP     |\n      TransactionMuncher::METHOD |\n      TransactionMuncher::URL    |\n      TransactionMuncher::HOST   |\n      TransactionMuncher::UA;}\n\n6) If it is needed override generate_response to generate your response instead of serving the request.\n\n7) in Banjax::filter_factory add the new name to the loop\n\n8) include the filter header file in banjax.cpp\n\n9) add the cpp file to the src/Makefile.am\n\nIf your filter needs to keep state\n----------------------------------\nYou need to ask banjax to allocate space for your filter in ip_db. To do so add your filter id to filter_to_column array in ip_database.h:\n\nconst FilterIDType filter_to_column[] = {\n  REGEX_BANNER_FILTER_ID\n  };\n\nYou'll get 16 bytes of memory for each ip, if you need more memory to keep the state you need to allocate it yourself and store a pointer to it in ip_database.\n\nYou need to edit the constructor of the filter to receive a pointer to the ip_database:\n\n    RegexManager(const std::string\u0026 banjax_dir, const libconfig::Setting\u0026 main_root, IPDatabase* global_ip_database)\n\nAnd you need to store it in ip_database member variable of BanjaxFilter (the parent of your filter) for further use. Finally you need edit\n\n    Banjax::filter_factory\n\nand tell banjax to send the pointer to your filter upon creation.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fequalitie%2Fbanjax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fequalitie%2Fbanjax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fequalitie%2Fbanjax/lists"}