diff --git a/.idea/endgame.iml b/.idea/endgame.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/endgame.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..38a2e28 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..550d3f1 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc b/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc index 0cdd74f..0cd8a6d 100644 --- a/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc +++ b/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc @@ -6,85 +6,94 @@ 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 @@ -95,18 +104,18 @@ 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 @@ -118,189 +127,645 @@ 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 +jGPylm4H2+8jlJ1+l5ietvoyiqOST1iIfOsbi30mxuVJ4JBvKtmapqpBwT6eNvCi +PKsMyjB5oWI5IVbK8MDIaYQM9TL+nyMGhl19GzcUMP8tZRlCifM9b/zmMMt1sgVY +0koF8AZfh3Ho9KLyXqNMUtXAFSQrAcTbN5SmzjlJtl+hz6uhiHH9kAeSX4MFRXX6 +JDfZxyAw72JqJkZaPEAKQCpodkNwNG9b2dedIBsTaD9IoEkryDtR17qV2ePwlCey +muwNnGVVaJ8hLbI7ZATbIaSn7XNvMGM8hX0N/ram5nTvrR2laG1o1ss5oxtg7PfT +rhMyCTrzTcxc8VskAgtbJjoyi4kCHAQQAQIABgUCUHsxcgAKCRBTnENrguQL99ul +EACwc68fdeLrP5U/oRJ38+WkQxO08Doa7dspj1cy763kXGlzp27xvXlc9xWMEkLZ +eFG6az+sI3YvW6Lq1PZYzQRLsjgMKDNDMDMB5xR3g65lRW4KKd0pCs5/CRxs2hDP +k6ulih2E12N/yqwgXTstbEDzXmaBe/66uGdtAnK0GinXdE+5wBMu0y0CFxJygkCm +to/hOeYufOHSLIcVVrzbsLH3meuPX9hUxjN4RIOduwWeHi0IWUCx5IyGPtMNBAfX ++AIVYmX7rWpEH+bqlfaEZYJh5kLDebzCq8gtRteRzvRz0jCX/Zr7SZu1PskjRN+e +MLdkNgsF9TXQy2vFFM5aRoEenHeD5gMla8pBFnbZP+AA4nPrbuKUyVcfdrLIIgQE +KIvxjKetSj3MV1PTuH5YNBw2I3qxrgmrv+YlClmiy/VQXt3///////////////// +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +/////////////////////////////////////////////4kCHAQQAQIABgUCUfg8 +wQAKCRAiLOjENkQCiI1OEACItuCpRR9YS9HeORrELMBSd2IqJBeto6V0VNse//g/ +nCVKgOKJo2hpEp9BqPidjBvP20Ek/xIqHr/Pz7R6T1UVsjqtQAlLngxab81wJsRA +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 +xahrBEYXphdNeqqXHa/udWpTYaKwSGYmIohTSIqBZh7Xa/rhLsx2UfgR5B0WW34E +8cTzuiZz//////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +////////iQIcBBABAgAGBQJW5/QxAAoJEPvqMRCoU3iU3SkP+wRdT8z3EczONAcv +Jsu7ZHgh1ggzsmozTciSuaAZRfvFmUyB9h63cKNTS86CIrqHmMZrtHRu9llkNNiE +4Nj8JAAsMPSR4YaKHfHxc3bOH0iWtcPxtIiQEwYs/7oP0/YzFAxcUmZBDeLvy7aK +pFqdPUcEhMTWmscVajjJXv+6G8IZwYGFAFvSkYSimZP102gmgKQhcfPDqmlqy78F +t+T5MfIha1Q950iZyAM3j46lVWMkBaKPQKq1G3kKaL7Sy3o75y4N7lgzY5WfYnBY +VAU8eUjv408FoFKAYFTsA3RG7P2VROoNefPaLRSgEgZPR6efVux9Z3R4zOUQuljv +q8r00zMS0t5RVcDp1gCNZQ9xv2QeN/ZDld0U0IbDQRrlT15+l3SthkXapMMvbSVK +EILMgaL+ysl7raMW/Zqv1KN2ByVJsPjWnwWCPnn0fMFWr15ExzfZBUNh2rZlQ56j +BsJanHF69Th0vI7JNm7/Gd5FRWL8RcXzAL/UbVDuyGaO2JPztQ2dL1lnHVL5mgOM +js90YpADenNR5XkQxuazTRiQIOXfoZhgPwe99S9vEdYM6UPYZjt8uo1bmFEkV0CG +jWngJc2ySSurftXPFJ7gzFhDbx70Ga/1lw/4H2RPs9ZiZKKTtiGcDLhDxSuX5z3M +gzzD3CNp7uKJQlTIg4aFeX9JWQvUiQIcBBABCAAGBQJX+0LWAAoJEAJ4If97HP7G +ahAQAMxf3Nyab2t+xJlFR+/ZCvqMq5rM8iq67ZK5fLG000RjLiBN5bd6BglAq03l +2DuE3b9hdnosKfU3FCeysivn0af0kxjMaH+W+9JSQJ9E5EjO+RgIJDkn3n6X/lQj +Vl3N7R6FeaWY6Ug9paSCtAlVlwCfg/rn2jFIiHQb++44nQFpaX4WuNzZWoy1SOGg +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 -sGsEejVHxvX7/iOE3rM= -=47bK +t+FzwPR67cVQXfz7jh6GktcqxrgA7KUmUwuaJ+DzGkIJEO6MvJ6Ibd2J7EMH/2sh +bVx9NRS36XNfQl6A1AXLCZ0+o4P+7zD1XsimSv2XsEMGzUxBk1FGao61QkXKuTEz +Y16bBE8tu7F0EbV6AyGoBdAqNauDZpJxq5OAHx7Od06R8KKil6T+OGGqPdPeEpgG ++i9d4hyDtESPeX+a8HDiIEC0czybPVzqvgtw8zTIpfQdaAMzv0ZPwYoU5mBG7SyP +ej5JjJj8Lfy/4LHHMRtwvqEqtNuukzePflnn0BR8UTQTQ9WlisRwUJzBdBJA23zh +GsFQ52ZUrxmcd65lC/CqYZEFwK0B8OwSzUxRbgFrCVzsizySv+QWXmi7EHd3bow4 +keSPmmDrjl8cySCNsMo= +=R0uO -----END PGP PUBLIC KEY BLOCK----- diff --git a/LOOKHERE-scripts/onionbalance/README.MD b/LOOKHERE-scripts/onionbalance/README.MD new file mode 100644 index 0000000..afa3ca9 --- /dev/null +++ b/LOOKHERE-scripts/onionbalance/README.MD @@ -0,0 +1,24 @@ +Onionbalance is the core of your scalability system. This is what makes all your seperate front onions work as a unified front! + +However it has it's limits. Onion Services have a limit to the amount of introduction points within a specific descriptor they can have and how large the descriptor can be. + +These limits lead to some pretty big problems. + + 1) There is a limit to the amount of fronts a single onion can have. + 2) Each front can only have a certain amount of introduction points themselves. + 3) Under attack descriptors can become spent before they can be replaced. + +"spent" descriptors are when all the introduction points to the onion service are no longer accepting clients. Introduction points have a certain amount of introduction cell requests it will accept before not accepting anymore. These requests are the Tor's main DDOS problem. By specifically requesting tons of introduction cells, which are computationally cheap to do, an attacker can overload an onion service. The only way to protect against this right now is by scaling out. + +First read the README.MD from the main directory and install onionbalance to a 2CPU 2GB RAM server seperate from your cluster of fronts. + +After you have installed onionbalance you will need to cd into the directory go to /onionbalance/hs_v3/params.py and change +N_INTROS_PER_INSTANCE = 2 -> N_INTROS_PER_INSTANCE = 1 + +Save the params.py file and go back to the main onionbalance directory. Run + +python3 setup.py install + +and then you can setup the configuration + +**When setting up your onionbalance configuration limit the amount of fronts to 18! Setting it higher you can get descriptor or introduction issues which will cause your onion's descriptor to not be correctly pushed.** \ No newline at end of file diff --git a/onionbalance/onionbalance.sh b/LOOKHERE-scripts/onionbalance/onionbalance.sh similarity index 94% rename from onionbalance/onionbalance.sh rename to LOOKHERE-scripts/onionbalance/onionbalance.sh index 83444f8..ea3fab3 100644 --- a/onionbalance/onionbalance.sh +++ b/LOOKHERE-scripts/onionbalance/onionbalance.sh @@ -24,7 +24,7 @@ service tor stop rm /etc/tor/torrc mv torrc /etc/tor/torrc -git clone https://gitlab.torproject.org/asn/onionbalance.git +git clone https://github.com/zscole/onionbalance.git cd onionbalance python3 setup.py install diff --git a/onionbalance/torrc b/LOOKHERE-scripts/onionbalance/torrc similarity index 100% rename from onionbalance/torrc rename to LOOKHERE-scripts/onionbalance/torrc diff --git a/README.MD b/README.MD index 21c78a5..e2fc3cf 100644 --- a/README.MD +++ b/README.MD @@ -1,34 +1,54 @@ -# EndGame - Onion Service DDOS Prevention Front System +# EndGame V2 - Onion Service DDOS Prevention Front System -Provided by [Dread](http://dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion/) and [White House Market](http://dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion/d/WhiteHouseMarket). With help from [Big Blue Market](http://dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion/d/BigBlueMarket) and [Empire Market](dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion/d/EmpireMarket). +V2 Provided by [Dread](http://dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion/) and [White House Market](http://dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion/d/WhiteHouseMarket). + +**Should be used with this [onionbalance](https://github.com/zscole/onionbalance) process for distinct descriptors. Use one onion for everything.** EndGame is - - a front system designed to protect the core application servers on an onion service in a safe and private way. - - locally complied and locally run (no trusted or middle party). - - a combination of multiple different technologies working together in harmony (listed below). - - FREE FOR ALL TO USE! - - *arguably* magic ㄟ( ▔, ▔ )ㄏ +- a front system designed to protect the core application servers on an onion service in a safe and private way. +- locally complied and locally run (no trusted or middle party). +- a combination of multiple different technologies working together in harmony (listed below). +- FREE FOR ALL TO USE! +- *arguably* magic ㄟ( ▔, ▔ )ㄏ # Main Features - - Fully scripted and easily deploy-able (for mass scaling!) on blank Debian 10 systems. - - Full featured NGINX LUA script to filter packets and provide a captcha directly using the NGINX layer. - - Rate limiting via Tor's V3 onion service circuit ID system with secondary rate limiting based on a testcookie like system. - - Easy Configuration for both local and remote (over Tor) front systems. - - Easily configurable and change-able to meet an onion service's needs. +- Fully scripted and easily deploy-able (for mass scaling!) on blank Debian 10 systems. +- Full featured NGINX LUA script to filter packets and provide a captcha directly using the NGINX layer. +- Rate limiting via Tor's V3 onion service circuit ID system with secondary rate limiting based on a testcookie like system. +- Easy Configuration for both local and remote (over Tor) front systems. +- Easily configurable and change-able to meet an onion service's needs. It can also: - - Cause you to grow a bigger dick than the asshole DDOSER (true *figurally*, lies *probably*) - - Save you millions of dollars do to DDOSER's downing your site for ransom or for their extorting fees. - - Make it look like you know what the fuck you are doing. +- Cause you to grow a bigger dick than the asshole DDOSER (true *figurally*, lies *probably*) +- Save you millions of dollars do to DDOSER's downing your site for ransom or for their extorting fees. +- Make it look like you know what the fuck you are doing. + +# V2 Updates +V2 EndGame has updates to the broken captcha generation process using a clock facing captcha. It includes extra features like +- updated documentation +- load balanced Tor socks processes for more stable socks_passes +- unix listening instead of ports for performance, stability, and security +- true randomization for captcha and cookie generation +- simple queue system (time based, read below) +- various theme configuration options right on the setup file +- dependency script to get all the dependencies only once. Effectively snapshotting all dependencies preventing future dependency repo exploits in the VERY unlikely case a repo was to get compromised. Paranoia mode. +- bug fixes and various performance tunings + +### Notes About Queue System + +V2 introduces a queue system which effectively prevents CPU exhaustion from mass get attacks. The clock captcha generation is computationally intensive and specifically vulnerable to this kind of attack. By limiting the amount of connections and amount of captcha tries it greatly reduces the CPU cycles to handle the attack. + +In this version there is a simple time on line 110 of the `lua/cap.lua` file which gets checked on line 143. It is recommended to variate this value by attaching a sliding scale time circumstance base on front CPU load. Exponential functions based on the "/proc/stat" value. If you do that, keep the curve private because there is always an "ideal" attack value. +When you set set the time value update the `queue.html` file via a script to rewrite the meta refresh variable. ### Tech Overview Endgame uses a number of open source projects (and libraries) to work properly. Projects: -* [NGINX](https://NGINX.org/) - NGINX! A web server *obviously* to provide the packet handling, threading, and proxying. +* [NGINX](https://NGINX.org/) - NGINX! A web server *obviously* to provide the packet handling, threading, and proxying. * [Tor](https://www.torproject.org/) - Tor is free and open-source software for enabling anonymous communication. It's awesome and makes all this possible. * [Vanguards](https://github.com/mikeperry-tor/vanguards) - A safer onion service circuit building system (to prevent some traffic analysis attacks) * [STEM](https://stem.torproject.org/) - A python controller for Tor. @@ -46,38 +66,44 @@ NGINX Modules: * [NGINX Development Kit](https://github.com/vision5/ngx_devel_kit) - Development Kit for NGINX (dependency) Libraries: -* [LUAJIT2 NGINX](https://github.com/openresty/luajit2) - Just in time compiler for LUA. +* [LUAJIT2 NGINX](https://github.com/openresty/luajit2) - Just in time compiler for LUA. * [LUA Resty String](https://github.com/openresty/lua-resty-string) - String functions for ngx_lua and LUAJIT2 * [LUA Resty Cookie](https://github.com/cloudflare/lua-resty-cookie) - Provides cookie manipulation * [LUA Resty Session](https://github.com/bungle/lua-resty-session) - Provides session manipulation * [LUA Resty AES](https://github.com/c64bob/lua-resty-aes/raw/master/lib/resty/aes_functions.lua) - AES Functions file for LUA. Used for shared session cookies. -* [LUA GD](https://github.com/ittner/lua-gd/) - GD image generation bindings For LUA +* [LUA Resty Random](https://github.com/bungle/lua-resty-random) - A *true* random number library for OpenResty. ### Configuration EndGame requires configuration to work properly. -The main configuration can be found at the top of the `setup.sh` file. It customizes most of the script +The main configuration can be found at the top of the `setup.sh` file. It customizes most of the script There are options. Such as: * MASTERONION - Your V3 Master OnionBalance Address **WITHOUT http://** (example: dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion) -* TORAUTHPASSWORD - Password which is used for your Tor Control Port Authentication with NGINX. Alphanumeric without spaces (example: passwordIcanremembertyping) +* TORAUTHPASSWORD - Password which is used for your Tor Control Port Authentication with NGINX. Alphanumeric without spaces (example: passwordIcanremembertyping) * KEY - Alphanumeric Key for the shared front session key. Random between 64-128 would do fine. (example: isthis64charactorsalreadyicantbelieveitwowsocoolwaitnotyetohdarn) * SALT - 8 character salt used with the key. 8 random alphanumeric characters (example: saltsalt) +* SESSION_LENGTH - In seconds the amount of time until cookie timeout. Set it high as you can. (example: 3600 [aka 1 hour]) * HEXCOLOR - HEX color put into the css file to be not purple but your main site's color. Any CSS hex will work. (example: #9b59b6) +* SITENAME - Site name automatically put in the captcha html file. (example: dread) +* LOCALPROXY - If true will set proxy_pass url to the PROXYPASSURL and disable load balanced Tor processes. If enabled will take the BACKENDONIONURL and configure load balanced socks_pass. It's highly recommended to proxy locally if possible. +* PROXYPASSURL - The local url used to proxy_pass all good connections. Not used if LOCALPROXY set to false. +* BACKENDONIONURL - The remote onion service endpoint. This onion is not public and should have no rate limiting or filtering on it. Generally the "core" server onion. Not used if LOCALPROXY set to true. -There is also some editing you need to do in the `caphtml_d.lua`, `naxsi_whitelist.rules`, `site.conf`, and `torrc` files. +There is also some editing you need to do in the `caphtml_d.lua`, `naxsi_whitelist.rules`, `site.conf`, and `torrc` files. - `resty/caphtml_d.lua` - Two Base64 Images. The favicon (line 143) and main logo (line 162). You can use [this](https://base64.guru/converter/encode/image/ico) for the favicon and [this](https://base64.guru/converter/encode/image) for the main logo. +- `queue.html` - Two base64 images. Search for .inner{position:absolute;top:50%;left:0;right:0;margin:0 auto;text-align:center;-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);transform:translateY(-50%);}.container>.inner>.logo{display:inline-block;vertical-align:middle;text-decoration:none;margin-bottom:10px}.container>.inner>.logo>.square{display:inline-block;vertical-align:middle;width:40px;height:40px;background-color:HEXCOLOR;background-size:24px 24px;background-position:center center;background-repeat:no-repeat;margin-right:10px}.container>.inner>.logo>.text{display:inline-block;vertical-align:middle;font-size:30px;color:#fff;font-weight:700}.container>.inner>.date{display:block;text-align:center;font-size:42px}.container>.inner>.date>.day{color:HEXCOLOR;font-weight:bold}.signed{display:block;width:400px;height:150px;margin-top:20px;margin:20px auto 0 auto;}.signed>textarea{margin:0 auto;width:400px;height:150px;min-width:400px;max-width:400px;display:block;padding:15px;background:#fff;border:1px solid HEXCOLOR;min-height:150px;max-height:150px;}p{margin:0 auto 20px auto;max-width:300px;}form.ddos_form .captcha-input{margin:0 auto 20px auto;display: block;width:300px;font-size:0;}form.ddos_form .captcha-input input{display:inline-block;vertical-align:top;height:50px;width:calc(100% - 150px);outline:0;border:none;font-size:16px;color:#000;padding:0 15px;line-height:50px;}form.ddos_form .captcha-input img{display:inline-block;vertical-align:top;}form.ddos_form button{border-radius:3px;display:block;width:300px;margin:0 auto;background:HEXCOLOR;cursor:pointer;color:#fff;font-size:16px;text-transform:uppercase;text-align:center;height:40px;line-height:40px;outline:0;border:none;} -.captchav2 {text-align: center;width: 100%;}.captchav2 > .imgWrap {display: inline-block;vertical-align: middle;width: 150px;height: 150px;background-size: cover;background-position: center center;}.captchav2 > .inputWrap {display: inline-block;vertical-align: middle;width: 120px;height: 120px;position: relative;margin-left: 15px;}.captchav2 > .inputWrap > div {position: absolute;width: 30px;height: 30px;cursor: pointer;border-radius: 100%;border: 2px solid #fff;} .captchav2 > .inputWrap > div.c1 { top: 0; left: 0; }.captchav2 > .inputWrap > div.c2 { top: 0; left: 0; right: 0; margin: 0 auto; }.captchav2 > .inputWrap > div.c3 { top: 0; right: 0; } .captchav2 > .inputWrap > div.c4 { top: 50%; left: 0; margin-top: -15px; }.captchav2 > .inputWrap > div.c5 { top: 50%; left: 0; right: 0; margin: -15px auto 0 auto; }.captchav2 > .inputWrap > div.c6 { top: 50%; right: 0; margin-top: -15px; } .captchav2 > .inputWrap > div.c7 { bottom: 0; left: 0; }.captchav2 > .inputWrap > div.c8 { bottom: 0; left: 0; right: 0; margin: 0 auto; }.captchav2 > .inputWrap > div.c9 { bottom: 0; right: 0; } .captchav2 > .inputWrap > input[type="checkbox"] {opacity: 0;margin: 0;padding: 0;cursor: pointer;position: absolute;width: 30px;height: 30px;z-index: 5;}.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(1) { top: 0; left: 0; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(1):checked ~ .c1 { background: #fff; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(2) { top: 0; left: 0; right: 0; margin: 0 auto; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(2):checked ~ .c2 { background: #fff; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(3) { top: 0; right: 0; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(3):checked ~ .c3 { background: #fff; } .captchav2 > .inputWrap > input[type="checkbox"]:nth-child(4) { top: 50%; left: 0; margin-top: -15px; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(4):checked ~ .c4 { background: #fff; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(5) { top: 50%; left: 0; right: 0; margin: -15px auto 0 auto; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(5):checked ~ .c5 { background: #fff; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(6) { top: 50%; right: 0; margin-top: -15px; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(6):checked ~ .c6 { background: #fff; } .captchav2 > .inputWrap > input[type="checkbox"]:nth-child(7) { bottom: 0; left: 0; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(7):checked ~ .c7 { background: #fff; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(8) { bottom: 0; left: 0; right: 0; margin: 0 auto; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(8):checked ~ .c8 { background: #fff; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(9) { bottom: 0; right: 0; }.captchav2 > .inputWrap > input[type="checkbox"]:nth-child(9):checked ~ .c9 { background: #fff; } +html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block} +strong{font-weight:bold} +body{line-height:1}ol,ul{list-style:none} +blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none} +table{border-collapse:collapse;border-spacing:0}*:focus{outline:0}input,select,textarea{border:0;box-shadow:0} +html{height:100%}body{height:100%;line-height:1;background:#1A1E23; +font-family:roboto, helvetica, sans-serif, arial, verdana, tahoma;font-size:16px;color:#fff} +.container {width:100%;margin:0 auto;min-height:100%;position:relative;max-height:100vh;overflow:hidden; } +.container>.inner{position:absolute;top:50%;left:0;right:0;margin:0 auto;text-align:center;-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%); transform:translateY(-50%);} +.container>.inner>.logo{display:inline-block;vertical-align:middle;text-decoration:none;margin-bottom:10px} +.container>.inner>.logo>.square{display:inline-block;vertical-align:middle;width:40px;height:40px;background-color:#9b59b6;background-size:24px 24px;background-position:center center;background-repeat:no-repeat;margin-right:10px} +.container>.inner>.logo>.text{display:inline-block;vertical-align:middle;font-size:30px;color:#fff;font-weight:700}.container>.inner>.date{display:block;text-align:center;font-size:42px} +.container>.inner>.date>.day{color:#9b59b6;font-weight:bold}.signed{display:block;width:400px;height:150px;margin-top:20px;margin:20px auto 0 auto;} +.signed>textarea {margin:0 auto;width:400px;height:150px;min-width:400px;max-width:400px;display:block;padding:15px;background:#fff;border:1px solid #9b59b6;min-height:150px;max-height:150px;}p{margin:0 auto 20px auto;max-width:300px;}form.ddos_form .captcha-input{margin:0 auto 20px auto;display: block;width:300px;font-size:0;}form.ddos_form .captcha-input input{display:inline-block;vertical-align:top;height:50px;width:calc(100% - 150px);outline:0;border:none;font-size:16px;color:#000;padding:0 15px;line-height:50px;}form.ddos_form .captcha-input img{display:inline-block;vertical-align:top;}form.ddos_form button{border-radius:3px;display:block;width:300px;margin:0 auto;background:#9b59b6;cursor:pointer;color:#fff;font-size:16px;text-transform:uppercase;text-align:center;height:40px;line-height:40px;outline:0;border:none;} +.captchav2 {text-align: center;width: 100%;} + +.captchav2 > .imgWrap { + display: inline-block; + text-align: center; + vertical-align: middle; + width: 195px; + height: 195px; + z-index: 4; + background-size: cover; + background-position: center center; + transition: transform .5s ease; + } + +.captchav2 > .inputWrap {text-align: center; display:inline-block;vertical-align: middle;width: 184px;height: 184px;position: relative;margin-left: 0px; transition: transform .5s ease; } +.captchav2 > .inputWrap > div {position: absolute;width: 60px;height: 60px;cursor: pointer;border-radius: 100%;border: 2px solid #fff;} + + +.expire { + display: inline-block; + vertical-align: top; + width: 100px; + height: 50px; + position: relative; + background: #888; + animation: timer-warning 1s 1; + animation-fill-mode: forwards; + animation-delay: 50s; + margin-bottom: 6px; + border-radius: 3px; +} + +.expire>.timer { + position: absolute; + top: 0; + left: 0; + width: 100px; + overflow: hidden; +} + +.expire>.timer>.time-part-wrapper { + display: inline-block; + vertical-align: top; + height: 50px; + line-height: 50px; + color: #fff; +} + +.expire>.timer>.time-part-wrapper:first-child:after { + content: ':'; + display: inline-block; + vertical-align: top; + width: 15px; + height: 50px; + line-height: 50px; + text-align: center; + font-size: 22px; +} + +.expire>.timer>.time-part-wrapper>.time-part { + display: inline-block; + vertical-align: top; + width: 15px; + position: relative; + animation: timer-expire; + animation-fill-mode: forwards; + animation-delay: 60s; +} + +.expire>.timer>.time-part-wrapper>.time-part>.digit-wrapper { + position: absolute; + top: 0; + left: 0; + width: 15px; + text-align: center; +} + +.expire>.timer>.time-part-wrapper>.time-part>.digit-wrapper>.digit { + display: block; + width: 100%; + text-align: center; + height: 50px; + line-height: 50px; + font-size: 22px; +} + +.expire>.timer>.time-part-wrapper>.time-part.seconds.tens>.digit-wrapper { + top: -50px; + animation: timer-seconds-tens 50s 1; + animation-fill-mode: forwards; + animation-delay: 1s; +} + +.expire>.timer>.time-part-wrapper>.time-part.seconds.ones>.digit-wrapper { + animation: timer-seconds-ones 10s 6; +} + +.expire>.timer>.time-part-wrapper>.time-part.hundredths.tens>.digit-wrapper { + animation: timer-seconds-ones 1s 60; +} + +.expire>.timer>.time-part-wrapper>.time-part.hundredths.ones>.digit-wrapper { + animation: timer-seconds-ones 500ms 120; +} + +@-webkit-keyframes timer-seconds-tens { + 0% { + top: -50px; + } + + 19% { + top: -50px; + } + + 20% { + top: -100px; + } + + 39% { + top: -100px; + } + + 40% { + top: -150px; + } + + 59% { + top: -150px; + } + + 60% { + top: -200px; + } + + 79% { + top: -200px; + } + + 80% { + top: -250px; + } + + 99% { + top: -250px; + } + + 100% { + top: -300px; + } +} + +@-webkit-keyframes timer-seconds-ones { + 0% { + top: 0; + } + + 9% { + top: 0; + } + + 10% { + top: -50px; + } + + 19% { + top: -50px; + } + + 20% { + top: -100px; + } + + 29% { + top: -100px; + } + + 30% { + top: -150px; + } + + 39% { + top: -150px; + } + + 40% { + top: -200px; + } + + 49% { + top: -200px; + } + + 50% { + top: -250px; + } + + 59% { + top: -250px; + } + + 60% { + top: -300px; + } + + 69% { + top: -300px; + } + + 70% { + top: -350px; + } + + 79% { + top: -350px; + } + + 80% { + top: -400px; + } + + 89% { + top: -400px; + } + + 90% { + top: -450px; + } + + 99% { + top: -450px; + } + + 100% { + top: -500px; + } +} + +@-webkit-keyframes timer-warning { + from { + background: #1A1E23; + } + + to { + background: #E7943C; + } +} + +@-webkit-keyframes timer-expire { + from { + color: #000; + } + + to { + color: #e7643c; + } +} + +@-webkit-keyframes button-expired { + from { + visibility: hidden; + } + + to { + visibility: visible; + } +} + +@-webkit-keyframes button-before { + from { + visibility: visible; + } + + to { + visibility: hidden; + } +} + +select { +font-size: 18px; +border: 1px solid #ccc; +padding: 0 10px; +height: 30px; +line-height: 40px; +color: #ffffe9; +background: #1a1e23; +} + +.center { +text-align: center; +} + +form.ddos_form button.before { + animation: button-before; + animation-fill-mode: forwards; + animation-delay: 60s; +} + +form.ddos_form button.expired { + visibility: hidden; + background: #E74C3C; + animation: button-expired; + animation-fill-mode: forwards; + animation-delay: 60s; + margin-top: -40px; +} diff --git a/font.ttf b/font.ttf deleted file mode 100644 index 51a18bc..0000000 Binary files a/font.ttf and /dev/null differ diff --git a/gen_background.py b/gen_background.py deleted file mode 100644 index c79640d..0000000 --- a/gen_background.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/python3 -u - -from PIL import Image -from PIL import ImageDraw -from PIL import ImageFont -import random -import os - - -def generate_background(): - random.seed() - unicode_chars = ( - "\u2605", - "\u2606", - "\u2663", - "\u2667", - "\u2660", - "\u2664", - "\u2662", - "\u2666", - "\u263a", - "\u263b", - "\u26aa", - "\u26ab", - "\u2b53", - "\u2b54", - "\u2b00", - "\u2b08", - "\u2780", - "\u278a", - "\u267c", - "\u267d", - "\u25b2", - "\u25b3", - ) - - unicode_max = len(unicode_chars) - try: - for i in range(0, 25): - im_cropped = Image.new('RGB', (150, 150), - (random.randrange(120, 255), random.randrange(120, 255), random.randrange(120, 255))) - origwidth, origheight = im_cropped.size - - watermark = Image.new("RGBA", im_cropped.size) - waterdraw = ImageDraw.ImageDraw(watermark, "RGBA") - number_of_shapes = random.randrange(10, 15) - for step in range(0, number_of_shapes): - fillcolor = ( - random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255), - random.randrange(240, 255)) - u_char = unicode_chars[random.randrange(0, unicode_max)] - font = ImageFont.truetype("/etc/nginx/font.ttf", random.randrange(25, 30)) - waterdraw.text((random.randrange(-10, 130), random.randrange(-10, 130)), u_char, fill=fillcolor, font=font) - im_cropped.paste(watermark, None, watermark) - im_cropped.save("/tmp/background-" + str(i) + '.jpg', format="JPEG") - - except Exception as e: - print(str(e)) - -generate_background() \ No newline at end of file diff --git a/getdependencies.sh b/getdependencies.sh new file mode 100755 index 0000000..994b711 --- /dev/null +++ b/getdependencies.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +shopt -s nullglob dotglob +directory=(dependencies/*) +if [ ${#directory[@]} -gt 0 ]; then +read -p "Found Dependency Directory. Did you want to wipe? (y/n) " -n 1 -r +if [[ $REPLY =~ ^[Yy]$ ]] +then + rm -R dependencies +echo +read -p "Did you want to resync? (y/n) " -n 1 -r +if [[ $REPLY =~ ^[Yy]$ ]] +then +echo +echo "resyncing" +else +exit 0 +fi +echo +echo "starting resync" +else +echo +exit 0 +fi +echo +exit 0 +fi + +apt-get update +apt-get -y install git + +mkdir dependencies +cd dependencies + +git clone https://github.com/yorkane/socks-nginx-module.git +git clone https://github.com/nbs-system/naxsi.git +git clone https://github.com/openresty/headers-more-nginx-module.git +git clone https://github.com/openresty/echo-nginx-module.git + +#some required stuff for lua/luajit. obviously versions should be ckecked with every install/update +git clone https://github.com/openresty/lua-nginx-module +cd lua-nginx-module +git checkout v0.10.16 +cd .. +git clone https://github.com/openresty/luajit2 +cd luajit2 +git checkout v2.1-20200102 +cd .. + +git clone https://github.com/vision5/ngx_devel_kit + +git clone https://github.com/openresty/lua-resty-string + +git clone https://github.com/cloudflare/lua-resty-cookie + +git clone https://github.com/ittner/lua-gd/ + +git clone https://github.com/bungle/lua-resty-session + +cd .. \ No newline at end of file diff --git a/lua/cap.lua b/lua/cap.lua index 4bf553d..bd357e3 100644 --- a/lua/cap.lua +++ b/lua/cap.lua @@ -1,12 +1,13 @@ -- encryption key and salt must be shared across fronts. salt must be 8 chars local key = "encryption_key" -local salt = "salt1234" +local salt = "1saltkey" -- for how long the captcha is valid. 120 sec is for testing, 3600 1 hour should be production. local session_timeout = 3600 aes = require "resty.aes" str = require "resty.string" cook = require "resty.cookie" +random = require "resty.random" aes_128_cbc_sha512x1 = aes:new(key, salt, aes.cipher(128,"cbc"), aes.hash.sha512, 1) @@ -88,74 +89,111 @@ if ngx.var.request_method == "POST" and ngx.var.http_referer == nil then ngx.exit(444) end +-- check if cookie is blacklisted by rate limiter. if it is show the client a message and exit. can get creative with this. +local field, err = cookie:get("dcap") +local blocked_cookies = ngx.shared.blocked_cookies +local bct, btcflags = blocked_cookies:get(field) +if bct then + ngx.header.content_type = 'text/plain' + ngx.say("403 DDOS fliter killed your path. (You probably sent too many requests at once). Not calling you a bot, bot, but grab a new identity and try again.") + ngx.flush() + ngx.exit(200) +end + -- check cookie support similar to testcookie if ngx.var.request_method == "GET" then - local args = ngx.req.get_uri_args() - if args['tca'] == "1" then - local field, err = cookie:get("dcap") - if err or not field then - ngx.exit(403) - end --- if cookie cannot be decrypted most likely it has been messed with - local cookdata = aes_128_cbc_sha512x1:decrypt(fromhex(field)) - if not cookdata then - ngx.header.content_type = 'text/plain' - ngx.say("403 DDOS fliter killed your path. (You probably sent too many requests at once). Not calling you a bot, bot, but grab a new identity and try again.") - ngx.flush() - ngx.exit(200) - end - cooktest = split(cookdata, "|")[1] - if cooktest ~= "cap_not_solved" and cooktest ~= "captcha_solved" then - ngx.exit(403) - end - end - --- try to set cookie. max-age is irrelevant as it can be faked and check is done against cookie content anyway. should be set to a large value otherwise it will annoy users local field, err = cookie:get("dcap") if err then - local tstamp = ngx.now() - local plaintext = "cap_not_solved|" .. tstamp .. "|1" + --local tstamp = ngx.now() + slidingscalefunction + local tstamp = ngx.now() + 10 + local plaintext = "queue|" .. tstamp .. "|1|" .. random.token(random.number(10,20)) local ciphertext = tohex(aes_128_cbc_sha512x1:encrypt(plaintext)) local ok, err = cookie:set({ key = "dcap", value = ciphertext, path = "/", domain = ngx.var.host, httponly = true, - max_age = 21600, - samesite = "Strict" + max_age = session_timeout, + samesite = "Lax" }) if not ok then ngx.log(ngx.ERR, err) return end - ngx.header.content_type = 'text/html' - ngx.say(" \ - \ - One moment...

") + ngx.header.content_type = 'text/html' + local file = io.open("/etc/nginx/queue.html") + local queue, err = file:read("*a") + file:close() + ngx.say(queue) ngx.flush() ngx.exit(200) + else + plaintext = aes_128_cbc_sha512x1:decrypt(fromhex(field)) + if not plaintext then + ngx.header.content_type = 'text/plain' + ngx.say("403 DDOS fliter killed your path. (You probably sent too many requests at once). Not calling you a bot, bot, but grab a new identity and try again.") + ngx.flush() + ngx.exit(200) + end + cookdata = split(plaintext,"|") + local expired = nil + if (cookdata[1] == "queue") then + --if (tonumber(cookdata[2])) > ngx.now() or (tonumber(cookdata[2])) > tonumber(cookdata[2]) + slidingscalefunction then + if (tonumber(cookdata[2])) > ngx.now() or (tonumber(cookdata[2])) > ngx.now() + 40 then + if pa ~= "no_proxy" then + local ok, err = ngx.timer.at(0, kill_circuit, ngx.var.remote_addr, ngx.var.proxy_protocol_addr) + if not ok then + ngx.log(ngx.ERR, "failed to create timer: ", err) + return + end + end + local blocked_cookies = ngx.shared.blocked_cookies + blocked_cookies:set(field, 1, 3600) + ngx.exit(444) + end + + require "caphtml_d" + + local expired = nil + + displaycap(session_timeout) + ngx.flush() + ngx.exit(200) + + elseif (cookdata[1] == "cap_not_solved") then + if (tonumber(cookdata[2]) + 60) > ngx.now() then + if pa ~= "no_proxy" then + local ok, err = ngx.timer.at(0, kill_circuit, ngx.var.remote_addr, ngx.var.proxy_protocol_addr) + if not ok then + ngx.log(ngx.ERR, "failed to create timer: ", err) + return + end + end + ngx.header.content_type = 'text/html' + ngx.say("

THINK OF WHAT YOU HAVE DONE!

") + ngx.say("

That captcha was generated just for you. And look at what you did. Ignoring the captcha... not even giving an incorrect answer to his meaningless existence. You couldn't even give him false hope. Shame on you.

") + ngx.say("

Don't immedately refresh for a new captcha! Try and fail. You must now wait about a minute for a new captcha to load.

") + ngx.flush() + ngx.exit(200) + end + + -- captcha generator functions + require "caphtml_d" + + local expired = nil + + if (tonumber(cookdata[2]) + session_timeout) < ngx.now() then + expired = true + caperror = "Session expired" + end + + if cookdata[1] ~= "captcha_solved" or expired then + displaycap(session_timeout) + ngx.flush() + ngx.exit(200) + end + end end end --- captcha generator functions -require "caphtml_d" - -local field, err = cookie:get("dcap") -if not field or field == nil then - displaycap() - ngx.flush() - ngx.exit(200) -end - --- check if cookie is blacklisted by rate limiter. if it is show the client a message and exit. can get creative with this. -local blocked_cookies = ngx.shared.blocked_cookies -local bct, btcflags = blocked_cookies:get(field) -if bct then - ngx.log(ngx.ERR, "Cookie " .. field .. " blacklisted.") - ngx.header.content_type = 'text/plain' - ngx.say("403 DDOS fliter killed your path. (You probably sent too many requests at once). Not calling you a bot, bot, but grab a new identity and try again.") - ngx.flush() - ngx.exit(200) -end - if ngx.var.request_method == "POST" then local field, err = cookie:get("dcap") if err then @@ -172,24 +210,28 @@ if ngx.var.request_method == "POST" then end cookdata = split(plaintext,"|") local expired = nil - if (tonumber(cookdata[2]) + session_timeout) < ngx.now() then - expired = true - caperror = "Session expired" - displaycap() - ngx.flush() - ngx.exit(200) - end - if cookdata[1] == "captcha_solved" and not expired then + if (cookdata[1] == "cap_not_solved") then + if (tonumber(cookdata[2]) + session_timeout) < ngx.now() then + expired = true + require "caphtml_d" + caperror = "Session expired" + displaycap(session_timeout) + ngx.flush() + ngx.exit(200) + end + elseif (cookdata[1] == "captcha_solved") then return end end + require "caphtml_d" + -- resty has a library for parsing POST data but it's not really needed ngx.req.read_body() local dataraw = ngx.req.get_body_data() if dataraw == nil then caperror = "You didn't submit anything. Try again." - displaycap() + displaycap(session_timeout) ngx.flush() ngx.exit(200) end @@ -213,24 +255,25 @@ if ngx.var.request_method == "POST" then if (tonumber(cookdata[2]) + 60) < ngx.now() then caperror = "Captcha expired" - displaycap() + displaycap(session_timeout) ngx.flush() ngx.exit(200) end - if sentcap == cookdata[3] then + if string.lower(sentcap) == string.lower(cookdata[3]) then local newcookdata = "" cookdata[1] = "captcha_solved" for k,v in pairs(cookdata) do newcookdata = newcookdata .. "|" .. v end + newcookdata = newcookdata .. "|" .. random.token(random.number(10,20)) local tstamp = ngx.now() local ciphertext = tohex(aes_128_cbc_sha512x1:encrypt(newcookdata)) local ok, err = cookie:set({ key = "dcap", value = ciphertext, path = "/", domain = ngx.var.host, httponly = true, - max_age = 21600, - samesite = "Strict" + max_age = session_timeout, + samesite = "Lax" }) if not ok then ngx.say("cookie error") @@ -244,39 +287,8 @@ if ngx.var.request_method == "POST" then else caperror = "You Got That Wrong. Try again" end - - else - caperror = "Session invalid or expired" - displaycap() + displaycap(session_timeout) ngx.flush() ngx.exit(200) end -end - -plaintext = aes_128_cbc_sha512x1:decrypt(fromhex(field)) -if not plaintext then - ngx.header.content_type = 'text/plain' - ngx.say("403 DDOS fliter killed your path. (You probably sent too many requests at once). Not calling you a bot, bot, but grab a new identity and try again.") - ngx.flush() - ngx.exit(200) -end -cookdata = split(plaintext,"|") - -if not cookdata then - displaycap() - ngx.flush() - ngx.exit(200) -end - -local expired = nil -if (tonumber(cookdata[2]) + session_timeout) < ngx.now() then - expired = true - caperror = "Session expired" -end - -if cookdata[1] ~= "captcha_solved" or expired then - displaycap() - ngx.flush() - ngx.exit(200) -end - +end \ No newline at end of file diff --git a/naxsi_core.rules b/naxsi_core.rules index 6870a54..a6a5cb3 100644 --- a/naxsi_core.rules +++ b/naxsi_core.rules @@ -1,3 +1,5 @@ + + ################################## ## INTERNAL RULES IDS:1-999 ## ################################## @@ -16,30 +18,30 @@ ################################## ## SQL Injections IDs:1000-1099 ## ################################## -MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop" "msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000; -MainRule "str:\"" "msg:double quote" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8" id:1001; -MainRule "str:0x" "msg:0x, possible hex encoding" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:2" id:1002; +#MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop" "msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000; +#MainRule "str:\"" "msg:double quote" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8" id:1001; +MainRule "str:0x" "msg:0x, possible hex encoding" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:2" id:1002; ## Hardcore rules -MainRule "str:/*" "msg:mysql comment (/*)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003; -MainRule "str:*/" "msg:mysql comment (*/)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004; -MainRule "str:|" "msg:mysql keyword (|)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005; -MainRule "str:&&" "msg:mysql keyword (&&)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006; +MainRule "str:/*" "msg:mysql comment (/*)" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003; +MainRule "str:*/" "msg:mysql comment (*/)" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004; +MainRule "str:|" "msg:mysql keyword (|)" "mz:URL|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005; +MainRule "str:&&" "msg:mysql keyword (&&)" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006; ## end of hardcore rules -MainRule "str:--" "msg:mysql comment (--)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007; -MainRule "str:;" "msg:semicolon" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008; -MainRule "str:=" "msg:equal sign in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009; -MainRule "str:(" "msg:open parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010; -MainRule "str:)" "msg:close parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011; -MainRule "str:'" "msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013; -MainRule "str:," "msg:comma" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015; -MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016; -MainRule "str:@@" "msg:double arobase (@@)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1017; +MainRule "str:--" "msg:mysql comment (--)" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007; +#MainRule "str:;" "msg:; in stuff" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008; +#MainRule "str:=" "msg:equal in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009; +MainRule "str:(" "msg:parenthesis, probable sql/xss" "mz:URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010; +MainRule "str:)" "msg:parenthesis, probable sql/xss" "mz:URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011; +MainRule "str:'" "msg:simple quote" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013; +#MainRule "str:," "msg:, in stuff" "mz:URL|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015; +#MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016; +MainRule "str:@@" "msg:double @@" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1017; ############################### ## OBVIOUS RFI IDs:1100-1199 ## ############################### -MainRule "str:http://" "msg:http:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1100; -MainRule "str:https://" "msg:https:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1101; +#MainRule "str:http://" "msg:http:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1100; +#MainRule "str:https://" "msg:https:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1101; MainRule "str:ftp://" "msg:ftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1102; MainRule "str:php://" "msg:php:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1103; MainRule "str:sftp://" "msg:sftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1104; @@ -48,41 +50,37 @@ MainRule "str:data://" "msg:data:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" " MainRule "str:glob://" "msg:glob:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1107; MainRule "str:phar://" "msg:phar:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1108; MainRule "str:file://" "msg:file:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1109; -MainRule "str:gopher://" "msg:gopher:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1110; +MainRule "str:gopher://" "msg:file:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1110; ####################################### ## Directory traversal IDs:1200-1299 ## -####################################### -MainRule "str:.." "msg:double dot" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1200; +####################################### +MainRule "str:.." "msg:double dot" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1200; MainRule "str:/etc/passwd" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1202; MainRule "str:c:\\" "msg:obvious windows path" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1203; MainRule "str:cmd.exe" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1204; -MainRule "str:\\" "msg:backslash" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1205; +MainRule "str:\\" "msg:backslash" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1205; #MainRule "str:/" "msg:slash in args" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:2" id:1206; ######################################## ## Cross Site Scripting IDs:1300-1399 ## ######################################## -MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302; -MainRule "str:>" "msg:html close tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1303; -MainRule "str:[" "msg:open square backet ([), possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1310; -MainRule "str:]" "msg:close square bracket (]), possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1311; -MainRule "str:~" "msg:tilde (~) character" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1312; -MainRule "str:`" "msg:grave accent (`)" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1314; -MainRule "rx:%[2|3]." "msg:double encoding" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1315; +MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302; +MainRule "str:>" "msg:html close tag" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1303; +#MainRule "str:[" "msg:[, possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1310; +#MainRule "str:]" "msg:], possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1311; +MainRule "str:~" "msg:~ character" "mz:URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1312; +MainRule "str:`" "msg:grave accent !" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1314; +#MainRule "rx:%[2|3]." "msg:double encoding !" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1315; #################################### ## Evading tricks IDs: 1400-1500 ## #################################### -MainRule "str:&#" "msg:utf7/8 encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1400; -MainRule "str:%U" "msg:M$ encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1401; +MainRule "str:&#" "msg: utf7/8 encoding" "mz:ARGS|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1400; +MainRule "str:%U" "msg: M$ encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1401; ############################# ## File uploads: 1500-1600 ## ############################# -MainRule "rx:\.ph|\.asp|\.ht" "msg:asp/php file upload" "mz:FILE_EXT" "s:$UPLOAD:8" id:1500; +MainRule "rx:\.ph|\.asp|\.ht*" "msg:asp/php file upload!" "mz:FILE_EXT" "s:$UPLOAD:8" id:1500; -MainRule "str:/public/uploads/" "msg:Access to uploads" "mz:URL" "s:$UWA:8" id:42000400; -MainRule "str:/public/image/" "msg:Access to image folder" "mz:URL" "s:$UWA:8" id:42000401; -MainRule "str:/public/" "msg:Access to public folder" "mz:URL" "s:$UWA:8" id:42000402; -MainRule "str:/system/" "msg:Access to system folder" "mz:URL" "s:$UWA:8" id:42000403; \ No newline at end of file diff --git a/naxsi_whitelist.rules b/naxsi_whitelist.rules index 58aa7bb..ccc8a38 100644 --- a/naxsi_whitelist.rules +++ b/naxsi_whitelist.rules @@ -1,4 +1,7 @@ BasicRule wl:10; BasicRule wl:20; BasicRule wl:16; -BasicRule wl:12; \ No newline at end of file +BasicRule wl:12; +BasicRule wl:13; +BasicRule wl:1310; +BasicRule wl:1311; \ No newline at end of file diff --git a/nginx-update.sh b/nginx-update.sh index 92fc50f..fe01bf0 100644 --- a/nginx-update.sh +++ b/nginx-update.sh @@ -70,18 +70,14 @@ cd .. git clone https://github.com/bungle/lua-resty-session cp -a lua-resty-session/lib/resty/session* /usr/local/lib/lua/resty/ -git clone https://github.com/ittner/lua-gd/ -cd lua-gd -gcc -o gd.so -DGD_XPM -DGD_JPEG -DGD_FONTCONFIG -DGD_FREETYPE -DGD_PNG -DGD_GIF -O2 -Wall -fPIC -fomit-frame-pointer -I/usr/local/include/luajit-2.1 -DVERSION=\"2.0.33r3\" -shared -lgd luagd.c -mv gd.so /usr/local/lib/lua/5.1/gd.so -cd .. - wget -O /usr/local/lib/lua/resty/aes_functions.lua https://github.com/c64bob/lua-resty-aes/raw/master/lib/resty/aes_functions.lua #include seems to be a bit mssed up with luajit mkdir /etc/nginx/resty ln -s /usr/local/lib/lua/resty/ /etc/nginx/resty/ +wget -O /usr/local/lib/lua/resty/random.lua https://raw.githubusercontent.com/bungle/lua-resty-random/master/lib/resty/random.lua + make -j16 modules cp -r objs modules diff --git a/nginx.conf b/nginx.conf index e5144cb..54e4e2f 100644 --- a/nginx.conf +++ b/nginx.conf @@ -2,6 +2,7 @@ user www-data; worker_processes auto; worker_priority -5; worker_rlimit_nofile 1024000; +timer_resolution 10000ms; pid /run/nginx.pid; load_module modules/modules/ngx_http_headers_more_filter_module.so; load_module modules/modules/ngx_http_naxsi_module.so; @@ -11,7 +12,9 @@ load_module modules/modules/ndk_http_module.so; load_module modules/modules/ngx_http_lua_module.so; events { - worker_connections 4096; + worker_connections 8096; + use epoll; + multi_accept on; } http { @@ -28,18 +31,19 @@ http { reset_timedout_connection on; - lua_shared_dict blocked_cookies 100M; + lua_shared_dict blocked_cookies 100M; # Timeouts - client_body_timeout 10s; - client_header_timeout 10s; + client_body_timeout 30s; + client_header_timeout 30s; keepalive_timeout 240s; + keepalive_requests 200000; send_timeout 120s; client_max_body_size 10m; client_body_buffer_size 10m; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 30s; + proxy_connect_timeout 120s; + proxy_send_timeout 120s; + proxy_read_timeout 120s; log_format detailed escape=json '{' @@ -57,7 +61,6 @@ http { '"http_user_agent": "$http_user_agent"' '}'; #access_log /var/log/site.access.log detailed; - proxy_redirect off; # Gzipping Content @@ -75,7 +78,7 @@ http { include /etc/nginx/naxsi_core.rules; add_header X-Content-Type-Options "nosniff"; - add_header X-Frame-Options "DENY"; + add_header X-Frame-Options "SAMEORIGIN"; add_header X-Xss-Protection "1; mode=block"; ## diff --git a/queue.html b/queue.html new file mode 100644 index 0000000..5e289c6 --- /dev/null +++ b/queue.html @@ -0,0 +1 @@ +dread Access Queue

You have been placed in a queue, awaiting forwarding to the platform.

Your estimated wait time is <2 minutes

Please do not refresh the page, you will be automatically redirected.

diff --git a/random.lua b/random.lua new file mode 100644 index 0000000..f36ec6f --- /dev/null +++ b/random.lua @@ -0,0 +1,86 @@ +local require = require +local ffi = require "ffi" +local ffi_cdef = ffi.cdef +local ffi_new = ffi.new +local ffi_str = ffi.string +local ffi_typeof = ffi.typeof +local C = ffi.C +local type = type +local random = math.random +local randomseed = math.randomseed +local concat = table.concat +local tostring = tostring +local pcall = pcall + +ffi_cdef[[ +typedef unsigned char u_char; +u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); +int RAND_bytes(u_char *buf, int num); +]] + +local ok, new_tab = pcall(require, "table.new") +if not ok then + new_tab = function () return {} end +end + +local alnum = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9' +} + +local t = ffi_typeof "uint8_t[?]" + +local function bytes(len, format) + local s = ffi_new(t, len) + C.RAND_bytes(s, len) + if not s then return nil end + if format == "hex" then + local b = ffi_new(t, len * 2) + C.ngx_hex_dump(b, s, len) + return ffi_str(b, len * 2), true + else + return ffi_str(s, len), true + end +end + +local function seed() + local a,b,c,d = bytes(4):byte(1, 4) + return randomseed(a * 0x1000000 + b * 0x10000 + c * 0x100 + d) +end + +local function number(min, max, reseed) + if reseed then seed() end + if min and max then return random(min, max) + elseif min then return random(min) + else return random() end +end + +local function token(len, chars, sep) + chars = chars or alnum + local count + local token = new_tab(len, 0) + if type(chars) ~= "table" then + chars = tostring(chars) + count = #chars + local n + for i=1,len do + n = number(1, count) + token[i] = chars:sub(n, n) + end + else + count = #chars + for i=1,len do token[i] = chars[number(1, count)] end + end + return concat(token, sep) +end + +seed() + +return { + bytes = bytes, + number = number, + token = token +} diff --git a/resty/aes_functions.lua b/resty/aes_functions.lua new file mode 100644 index 0000000..ad3de34 --- /dev/null +++ b/resty/aes_functions.lua @@ -0,0 +1,225 @@ +-- Copyright (C) by Yichun Zhang (agentzh) + + +local ffi = require "ffi" +local ffi_new = ffi.new +local ffi_gc = ffi.gc +local ffi_str = ffi.string +local ffi_copy = ffi.copy +local C = ffi.C +local setmetatable = setmetatable +local type = type + + +local _M = { _VERSION = '0.12' } + +local mt = { __index = _M } + + +ffi.cdef[[ +typedef struct engine_st ENGINE; + +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; + +typedef struct env_md_ctx_st EVP_MD_CTX; +typedef struct env_md_st EVP_MD; + +const EVP_MD *EVP_md5(void); +const EVP_MD *EVP_sha(void); +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); + +const EVP_CIPHER *EVP_aes_128_ecb(void); +const EVP_CIPHER *EVP_aes_128_cbc(void); +const EVP_CIPHER *EVP_aes_128_cfb1(void); +const EVP_CIPHER *EVP_aes_128_cfb8(void); +const EVP_CIPHER *EVP_aes_128_cfb128(void); +const EVP_CIPHER *EVP_aes_128_ofb(void); +const EVP_CIPHER *EVP_aes_128_ctr(void); +const EVP_CIPHER *EVP_aes_192_ecb(void); +const EVP_CIPHER *EVP_aes_192_cbc(void); +const EVP_CIPHER *EVP_aes_192_cfb1(void); +const EVP_CIPHER *EVP_aes_192_cfb8(void); +const EVP_CIPHER *EVP_aes_192_cfb128(void); +const EVP_CIPHER *EVP_aes_192_ofb(void); +const EVP_CIPHER *EVP_aes_192_ctr(void); +const EVP_CIPHER *EVP_aes_256_ecb(void); +const EVP_CIPHER *EVP_aes_256_cbc(void); +const EVP_CIPHER *EVP_aes_256_cfb1(void); +const EVP_CIPHER *EVP_aes_256_cfb8(void); +const EVP_CIPHER *EVP_aes_256_cfb128(void); +const EVP_CIPHER *EVP_aes_256_ofb(void); +const EVP_CIPHER *EVP_aes_256_ctr(void); + +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(); +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a); + +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, + ENGINE *impl, unsigned char *key, const unsigned char *iv); + +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); + +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, + ENGINE *impl, unsigned char *key, const unsigned char *iv); + +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); + +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); + +int EVP_BytesToKey(const EVP_CIPHER *type,const EVP_MD *md, + const unsigned char *salt, const unsigned char *data, int datal, + int count, unsigned char *key,unsigned char *iv); +]] + +local hash +hash = { + md5 = C.EVP_md5(), + sha1 = C.EVP_sha1(), + sha224 = C.EVP_sha224(), + sha256 = C.EVP_sha256(), + sha384 = C.EVP_sha384(), + sha512 = C.EVP_sha512() +} +_M.hash = hash + +local cipher +cipher = function (size, _cipher) + local _size = size or 128 + local _cipher = _cipher or "cbc" + local func = "EVP_aes_" .. _size .. "_" .. _cipher + if C[func] then + return { size=_size, cipher=_cipher, method=C[func]()} + else + return nil + end +end +_M.cipher = cipher + +function _M.new(self, key, salt, _cipher, _hash, hash_rounds) + local encrypt_ctx = C.EVP_CIPHER_CTX_new() + if encrypt_ctx == nil then + return nil, "no memory" + end + + ffi_gc(encrypt_ctx, C.EVP_CIPHER_CTX_free) + + local decrypt_ctx = C.EVP_CIPHER_CTX_new() + if decrypt_ctx == nil then + return nil, "no memory" + end + + ffi_gc(decrypt_ctx, C.EVP_CIPHER_CTX_free) + + local _cipher = _cipher or cipher() + local _hash = _hash or hash.md5 + local hash_rounds = hash_rounds or 1 + local _cipherLength = _cipher.size/8 + local gen_key = ffi_new("unsigned char[?]",_cipherLength) + local gen_iv = ffi_new("unsigned char[?]",_cipherLength) + + if type(_hash) == "table" then + if not _hash.iv or #_hash.iv ~= 16 then + return nil, "bad iv" + end + + if _hash.method then + local tmp_key = _hash.method(key) + + if #tmp_key ~= _cipherLength then + return nil, "bad key length" + end + + ffi_copy(gen_key, tmp_key, _cipherLength) + + elseif #key ~= _cipherLength then + return nil, "bad key length" + + else + ffi_copy(gen_key, key, _cipherLength) + end + + ffi_copy(gen_iv, _hash.iv, 16) + + else + if salt and #salt ~= 8 then + return nil, "salt must be 8 characters or nil" + end + + if C.EVP_BytesToKey(_cipher.method, _hash, salt, key, #key, + hash_rounds, gen_key, gen_iv) + ~= _cipherLength + then + return nil + end + end + + if C.EVP_EncryptInit_ex(encrypt_ctx, _cipher.method, nil, + gen_key, gen_iv) == 0 or + C.EVP_DecryptInit_ex(decrypt_ctx, _cipher.method, nil, + gen_key, gen_iv) == 0 then + return nil + end + + return setmetatable({ + _encrypt_ctx = encrypt_ctx, + _decrypt_ctx = decrypt_ctx + }, mt) +end + + +function _M.encrypt(self, s) + local s_len = #s + local max_len = s_len + 16 + local buf = ffi_new("unsigned char[?]", max_len) + local out_len = ffi_new("int[1]") + local tmp_len = ffi_new("int[1]") + local ctx = self._encrypt_ctx + + if C.EVP_EncryptInit_ex(ctx, nil, nil, nil, nil) == 0 then + return nil + end + + if C.EVP_EncryptUpdate(ctx, buf, out_len, s, s_len) == 0 then + return nil + end + + if C.EVP_EncryptFinal_ex(ctx, buf + out_len[0], tmp_len) == 0 then + return nil + end + + return ffi_str(buf, out_len[0] + tmp_len[0]) +end + + +function _M.decrypt(self, s) + local s_len = #s + local buf = ffi_new("unsigned char[?]", s_len) + local out_len = ffi_new("int[1]") + local tmp_len = ffi_new("int[1]") + local ctx = self._decrypt_ctx + + if C.EVP_DecryptInit_ex(ctx, nil, nil, nil, nil) == 0 then + return nil + end + + if C.EVP_DecryptUpdate(ctx, buf, out_len, s, s_len) == 0 then + return nil + end + + if C.EVP_DecryptFinal_ex(ctx, buf + out_len[0], tmp_len) == 0 then + return nil + end + + return ffi_str(buf, out_len[0] + tmp_len[0]) +end + + +return _M diff --git a/resty/caphtml_d.lua b/resty/caphtml_d.lua index 0be2420..90abf49 100644 --- a/resty/caphtml_d.lua +++ b/resty/caphtml_d.lua @@ -1,6 +1,6 @@ local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -function base64_encode(data) +local function base64_encode(data) return ((data:gsub('.', function(x) local r,b='',x:byte() for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end @@ -13,7 +13,7 @@ function base64_encode(data) end)..({ '', '==', '=' })[#data%3+1]) end -function base64_decode(data) +local function base64_decode(data) data = string.gsub(data, '[^'..b..'=]', '') return (data:gsub('.', function(x) if (x == '=') then return '' end @@ -28,40 +28,105 @@ function base64_decode(data) end)) end -function in_array(tab, val) - for index, value in ipairs(tab) do - if value == val then - return true - end +function displaycap() + + hour = random.number(0,11) + minute = random.number(0,59) + shour = tostring(hour) + sminute = tostring(minute) + if string.len(shour) < 2 then shour = "0" .. shour end + if string.len(sminute) < 2 then sminute = "0" .. sminute end + + local gd = require("gd") + + local pickedtime = shour .. ":" .. sminute + local radios = {} + local ctimeindex = random.number(1,10) + radios[ctimeindex] = {} + radios[ctimeindex][1] = pickedtime + radios[ctimeindex][2] = shour .. sminute + for i = 1,ctimeindex-1,1 do + fshour = tostring(random.number(0,11)) + fsminute = tostring(random.number(0,59)) + if string.len(fshour) < 2 then fshour = "0" .. fshour end + if string.len(fsminute) < 2 then fsminute = "0" .. fsminute end + local fpickedtime = fshour .. ":" .. fsminute + radios[i] = {} + radios[i][1] = fpickedtime + radios[i][2] = fshour .. fsminute end + for i = ctimeindex+1,10,1 do + fshour = tostring(random.number(0,11)) + fsminute = tostring(random.number(0,59)) + if string.len(fshour) < 2 then fshour = "0" .. fshour end + if string.len(fsminute) < 2 then fsminute = "0" .. fsminute end + local fpickedtime = fshour .. ":" .. fsminute + radios[i] = {} + radios[i][1] = fpickedtime + radios[i][2] = fshour .. fsminute + end + + + +local function createClock(size, hours, minutes) + local im = gd.createTrueColor(size, size) + + local white = im:colorAllocate(random.number(200,255), random.number(200,255), random.number(200,255)) + local gray = im:colorAllocate(random.number(100,150), random.number(100,150), random.number(100,150)) + local black = im:colorAllocate(random.number(0,10), random.number(0,10), random.number(0,10)) + + local hrhand = im:colorAllocate(random.number(0,350), random.number(0,150), random.number(0,148)) + local minhand = im:colorAllocate(random.number(0,350), random.number(0,150), random.number(0,148)) + + local cxy = size/2 + + im:filledRectangle(0, 0, size, size, white) + im:setThickness(2) + im:arc(cxy, cxy, size, size, 0, 360, black) + + local ang = 0 + local rang, gsize + while ang < 360 do + rang = math.rad(ang) + if (ang % 90) == 0 then + gsize = 0.75 + elseif (ang % 5) == 0 then + gsize = 0.85 + else + gsize = 0.90 + end + im:line( + cxy + gsize * cxy * math.sin(rang), + size - (cxy + gsize * cxy * math.cos(rang)), + cxy + cxy * 0.9 * math.sin(rang), + size - (cxy + cxy * 0.9 * math.cos(rang)), + gray) + ang = ang + 6 + end + + im:setThickness(math.max(1, size/50)) + im:line(cxy, cxy, + cxy + 0.45 * size * math.sin(math.rad(6*minutes)), + size - (cxy + 0.45 * size * math.cos(math.rad(6*minutes))), + hrhand) + + im:setThickness(math.max(1, size/25)) + rang = math.rad(30*hours + minutes/2) + im:line(cxy, cxy, + cxy + 0.25 * size * math.sin(rang), + size - (cxy + 0.25 * size * math.cos(rang)), + minhand) + + im:setThickness(1) + local sp = math.max(1, size/20) + im:filledArc(cxy, cxy, sp, sp, 0, 360, black, gd.ARC) + return im end -local gd = require("gd") +local im = createClock(190, hour, minute) +local imageraw = im:jpegStr(90) +local imageb64 = base64_encode(imageraw) -function displaycap() - math.randomseed(ngx.now()) - - local img_width = 150; - local img_height = 150; - - local capgrid = {} - - local checkmin = 1 - local checkmax = 6 - local checktotal = 0 - - local sessiondice = ""; - - while checktotal < checkmin do - for i=1,9,1 do - check = math.random(0,1) - if checktotal < checkmax and check == 1 then capgrid[i] = check else capgrid[i] = 0 end - if check == 1 then - checktotal = checktotal + 1 - sessiondice = sessiondice .. tostring(i) - end - end - end local cookie, err = cook:new() if not cookie then @@ -71,71 +136,26 @@ function displaycap() end local tstamp = ngx.now() - local newcookdata = "cap_not_solved|" .. tstamp .. "|" - newcookdata = newcookdata .. sessiondice + local newcookdata = "cap_not_solved|" .. tstamp .. "|" .. shour .. sminute + + newcookdata = newcookdata .. "|" .. random.token(random.number(10,20)) local ciphertext = tohex(aes_128_cbc_sha512x1:encrypt(newcookdata)) local ok, err = cookie:set({ key = "dcap", value = ciphertext, path = "/", domain = ngx.var.host, httponly = true, max_age = 21600, - samesite = "Strict" + samesite = "Lax" }) if not ok then ngx.say("cookie error") ngx.exit(200) end - local symbols_zero = {'○','□','♘','♢','▽','△','♖','✧','♔','♘','♕','♗','♙','♧'}; - local symbols_one = {'●','■','♞','♦','▼','▲','♜','✦','♚','♞','♛','♝','♟','♣'}; - - - local img = gd.createFromJpeg("/tmp/background-" .. math.random(0,25) .. ".jpg") - - if img == nil then - img = gd.createTrueColor(150, 150) - local white = img:colorAllocate(255, 255, 255) - img:filledRectangle(0, 0, img_width, img_height, white) - end - - img:setThickness(1) - - -- if 0 each row will be horizontal - local draw_angle = 0 - - local current_row = 1 - local capstring = "" - for i=1,9,1 do - local symbol_id = math.random(1,14) - local fillcolor = img:colorAllocate(math.random(5,255), math.random(5,255), math.random(5,255)) - if capgrid[i] == 1 then - capstring = capstring .. symbols_one[symbol_id] - else - capstring = capstring .. symbols_zero[symbol_id] - end - capstring = capstring .. " " - if i % 3 == 0 then - if draw_angle == 1 then - angle = math.rad(math.random(0,10)) - else - angle = 0 - end - if current_row == 1 then - img:stringFT(fillcolor, "/etc/nginx/font.ttf", math.random(18,22), angle, math.random(10,50), math.random(30,60), capstring) - elseif current_row == 2 then - img:stringFT(fillcolor, "/etc/nginx/font.ttf", math.random(18,22), angle, math.random(10,50), math.random(60,90), capstring) - else - img:stringFT(fillcolor, "/etc/nginx/font.ttf", math.random(18,22), angle, math.random(10,50), math.random(100,130), capstring) - end - current_row = current_row + 1 - capstring = "" - end - end - imgbase64 = base64_encode(img:pngStrEx(6)) - ngx.header.content_type = 'text/html'; -ngx.say(" \ +ngx.say(" \ + \ \ DDOS Protection \ \ @@ -166,34 +186,95 @@ if caperror ~= nil then ngx.say("

Error: " .. caperror .. "

") else -ngx.say("

Due to on-going DDOS attacks against our servers, you must complete a captcha challenge to prove you are human.

") +ngx.say("

Prove that you are human. Select the time shown on the clock image.

") end - ngx.say("
\
\ -
") -ngx.say("
\ - \ - \ - \ - \ - \ - \ - \ - \ -") -ngx.say("
\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ -
") -ngx.say("
\ -
\ - \ +
") +ngx.say(""); +ngx.say("
") +ngx.say(" : ") +ngx.say("") +--ngx.say(" : ") +--ngx.say("") +ngx.say("
"); +ngx.say("
\ +
\ +
\ +
\ +
\ + 0 \ + 5 \ + 4 \ + 3 \ + 2 \ + 1 \ + 0 \ +
\ +
\ +
\ +
\ + 0 \ + 9 \ + 8 \ + 7 \ + 6 \ + 5 \ + 4 \ + 3 \ + 2 \ + 1 \ + 0 \ +
\ +
\ +
\ +
\ +
\ +
\ + 0 \ + 9 \ + 8 \ + 7 \ + 6 \ + 5 \ + 4 \ + 3 \ + 2 \ + 1 \ + 0 \ +
\ +
\ +
\ +
\ + 0 \ + 9 \ + 8 \ + 7 \ + 6 \ + 5 \ + 4 \ + 3 \ + 2 \ + 1 \ + 0 \ +
\ +
\ +
\ +
\ +
") + +ngx.say(" \ + \
\ \ \ diff --git a/resty/core/random.lua b/resty/core/random.lua new file mode 100644 index 0000000..f36ec6f --- /dev/null +++ b/resty/core/random.lua @@ -0,0 +1,86 @@ +local require = require +local ffi = require "ffi" +local ffi_cdef = ffi.cdef +local ffi_new = ffi.new +local ffi_str = ffi.string +local ffi_typeof = ffi.typeof +local C = ffi.C +local type = type +local random = math.random +local randomseed = math.randomseed +local concat = table.concat +local tostring = tostring +local pcall = pcall + +ffi_cdef[[ +typedef unsigned char u_char; +u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); +int RAND_bytes(u_char *buf, int num); +]] + +local ok, new_tab = pcall(require, "table.new") +if not ok then + new_tab = function () return {} end +end + +local alnum = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9' +} + +local t = ffi_typeof "uint8_t[?]" + +local function bytes(len, format) + local s = ffi_new(t, len) + C.RAND_bytes(s, len) + if not s then return nil end + if format == "hex" then + local b = ffi_new(t, len * 2) + C.ngx_hex_dump(b, s, len) + return ffi_str(b, len * 2), true + else + return ffi_str(s, len), true + end +end + +local function seed() + local a,b,c,d = bytes(4):byte(1, 4) + return randomseed(a * 0x1000000 + b * 0x10000 + c * 0x100 + d) +end + +local function number(min, max, reseed) + if reseed then seed() end + if min and max then return random(min, max) + elseif min then return random(min) + else return random() end +end + +local function token(len, chars, sep) + chars = chars or alnum + local count + local token = new_tab(len, 0) + if type(chars) ~= "table" then + chars = tostring(chars) + count = #chars + local n + for i=1,len do + n = number(1, count) + token[i] = chars:sub(n, n) + end + else + count = #chars + for i=1,len do token[i] = chars[number(1, count)] end + end + return concat(token, sep) +end + +seed() + +return { + bytes = bytes, + number = number, + token = token +} diff --git a/setup.sh b/setup.sh old mode 100644 new mode 100755 index 5251680..110c18d --- a/setup.sh +++ b/setup.sh @@ -3,15 +3,22 @@ #OPTIONS! MASTERONION="dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion" -TORAUTHPASSWORD="password" +TORAUTHPASSWORD="changethispassowrd" +BACKENDONIONURL="biblemeowimkh3utujmhm6oh2oeb3ubjw2lpgeq3lahrfr2l6ev6zgyd.onion" + +#set to true if you want to setup local proxy instead of proxy over Tor +LOCALPROXY=false +PROXYPASSURL="10.10.10.10:80" #Shared Front Captcha Key. Key alphanumeric between 64-128. Salt needs to be exactly 8 chars. KEY="encryption_key" -SALT="salt1234" +SALT="1saltkey" +SESSION_LENGTH=3600 #CSS Branding HEXCOLOR="#9b59b6" +SITENAME="dread" #There is more branding you need to do in the resty/caphtml_d.lua file near the end. @@ -25,7 +32,7 @@ NC='\033[0m' # No Color printf "\r\nProvided by your lovely ${BLUE}/u/Paris${NC} from dread. \r\n" printf "with help from ${BLUE}/u/mr_white${NC} from whitehousemarket.\n" echo "For the full effects of the DDOS prevention you will need to make sure to setup v3 onionbalance." -echo "Max 6-9 backend instances for each onion. This script will help make the backend instances." +echo "Onionbalance v3 does have distinct descriptors in a forked version. Read the README.MD in the onionbalance folder for more information. " if [ ${#MASTERONION} -lt 62 ]; then echo "MASTEWRONION doesn't have the correct length. The url needs to include the .onion at the end." @@ -38,9 +45,18 @@ then exit 0 fi -sleep 5 -echo "Proceeding to do the configuration and setup. This will take awhile." +shopt -s nullglob dotglob +directory=(dependencies/*) +if [ ${#directory[@]} -gt 0 ] +then +echo "Dependency Folder Found!" +else +echo "You need to get the dependencies first. Run './getdependencies.sh'" +exit 0 +fi +echo "Proceeding to do the configuration and setup. This will take awhile." +sleep 5 ### Configuration string="s/masterbalanceonion/" @@ -49,7 +65,17 @@ string+="/g" sed -i $string site.conf string="s/torauthpassword/" -string+="$torinput" +string+="$TORAUTHPASSWORD" +string+="/g" +sed -i $string site.conf + +string="s/backendurl/" +string+="$BACKENDONIONURL" +string+="/g" +sed -i $string site.conf + +string="s/proxypassurl/" +string+="$PROXYPASSURL" string+="/g" sed -i $string site.conf @@ -63,16 +89,44 @@ string+="$SALT" string+="/g" sed -i $string lua/cap.lua +string="s/sessionconfigvalue/" +string+="$SESSION_LENGTH" +string+="/g" +sed -i $string lua/cap.lua + string="s/HEXCOLOR/" string+="$HEXCOLOR" string+="/g" sed -i $string cap_d.css +string="s/HEXCOLOR/" +string+="$HEXCOLOR" +string+="/g" +sed -i $string queue.html + +string="s/SITENAME/" +string+="$SITENAME" +string+="/g" +sed -i $string queue.html + string="s/SITENAME/" string+="$SITENAME" string+="/g" sed -i $string resty/caphtml_d.lua +if $LOCALPROXY +then +string="s/#proxy_pass/" +string+="proxy_pass" +string+="/g" +sed -i $string site.conf +else +string="s/#socks_/" +string+="socks_" +string+="/g" +sed -i $string site.conf +fi + apt-get update apt-get install -y apt-transport-https lsb-release ca-certificates dirmngr @@ -84,44 +138,49 @@ echo "deb https://nginx.org/packages/debian/ buster nginx" > /etc/apt/sources.li gpg --import A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | apt-key add - + apt-key add nginx_signing.key apt-get update apt-get install -y tor nyx nginx apt-get install -y vanguards +apt-get install -y build-essential zlib1g-dev libpcre3 libpcre3-dev uuid-dev gcc git wget curl libgd3 libgd-dev command="nginx -v" nginxv=$( ${command} 2>&1 ) NGINXVERSION=$(echo $nginxv | grep -o '[0-9.]*$') + NGINXOPENSSL="1.1.1d" wget https://nginx.org/download/nginx-$NGINXVERSION.tar.gz tar -xzvf nginx-$NGINXVERSION.tar.gz + +cp -R dependencies/* nginx-$NGINXVERSION/ + cd nginx-$NGINXVERSION -apt-get install -y build-essential zlib1g-dev libpcre3 libpcre3-dev uuid-dev gcc git wget curl libgd3 libgd-dev - -git clone https://github.com/yorkane/socks-nginx-module.git -git clone https://github.com/nbs-system/naxsi.git wget https://www.openssl.org/source/openssl-$NGINXOPENSSL.tar.gz tar -xzvf openssl-$NGINXOPENSSL.tar.gz -git clone https://github.com/openresty/headers-more-nginx-module.git -git clone https://github.com/openresty/echo-nginx-module.git -#some required stuff for lua/luajit. obviously versions should be ckecked with every install/update -git clone https://github.com/openresty/lua-nginx-module -cd lua-nginx-module -git checkout v0.10.16 -cd .. -git clone https://github.com/openresty/luajit2 -cd luajit2 -git checkout v2.1-20200102 -cd .. -git clone https://github.com/vision5/ngx_devel_kit cd luajit2 make -j8 && make install cd .. +cd lua-resty-string +make install +cd .. + +cd lua-resty-cookie +make install +cd .. + +cd lua-gd +gcc -o gd.so -DGD_XPM -DGD_JPEG -DGD_FONTCONFIG -DGD_FREETYPE -DGD_PNG -DGD_GIF -O2 -Wall -fPIC -fomit-frame-pointer -I/usr/local/include/luajit-2.1 -DVERSION=\"2.0.33r3\" -shared -lgd luagd.c +mv gd.so /usr/local/lib/lua/5.1/gd.so +cd .. + +cp -a lua-resty-session/lib/resty/session* /usr/local/lib/lua/resty/ + export LUAJIT_LIB=/usr/local/lib export LUAJIT_INC=/usr/local/include/luajit-2.1 ./configure --with-cc-opt='-Wno-stringop-overflow -Wno-stringop-truncation -Wno-cast-function-type' \ @@ -135,67 +194,66 @@ export LUAJIT_INC=/usr/local/include/luajit-2.1 --add-dynamic-module=ngx_devel_kit \ --add-dynamic-module=lua-nginx-module -git clone https://github.com/openresty/lua-resty-string -cd lua-resty-string -make install -cd .. - -git clone https://github.com/cloudflare/lua-resty-cookie -cd lua-resty-cookie -make install -cd .. - -git clone https://github.com/bungle/lua-resty-session -cp -a lua-resty-session/lib/resty/session* /usr/local/lib/lua/resty/ - -git clone https://github.com/ittner/lua-gd/ -cd lua-gd -gcc -o gd.so -DGD_XPM -DGD_JPEG -DGD_FONTCONFIG -DGD_FREETYPE -DGD_PNG -DGD_GIF -O2 -Wall -fPIC -fomit-frame-pointer -I/usr/local/include/luajit-2.1 -DVERSION=\"2.0.33r3\" -shared -lgd luagd.c -mv gd.so /usr/local/lib/lua/5.1/gd.so -cd .. - -wget -O /usr/local/lib/lua/resty/aes_functions.lua https://github.com/c64bob/lua-resty-aes/raw/master/lib/resty/aes_functions.lua +#https://github.com/c64bob/lua-resty-aes/raw/master/lib/resty/aes_functions.lua +mv resty/aes_functions.lua /usr/local/lib/lua/resty/aes_functions.lua +mkdir /etc/nginx/resty/ #include seems to be a bit mssed up with luajit -mkdir /etc/nginx/resty ln -s /usr/local/lib/lua/resty/ /etc/nginx/resty/ make -j16 modules cp -r objs modules +rm -R /etc/nginx/modules +mkdir /etc/nginx/modules mv modules /etc/nginx/modules cd .. +rm /etc/nginx/nginx.conf mv nginx.conf /etc/nginx/nginx.conf +rm /etc/nginx/naxsi_core.rules mv naxsi_core.rules /etc/nginx/naxsi_core.rules +rm /etc/nginx/naxsi_whitelist.rules mv naxsi_whitelist.rules /etc/nginx/naxsi_whitelist.rules +rm -R /etc/nginx/lua/ mv lua /etc/nginx/ mv resty/* /etc/nginx/resty/resty/ +rm /etc/nginx/resty/caphtml_d.lua mv /etc/nginx/resty/resty/caphtml_d.lua /etc/nginx/resty/caphtml_d.lua +rm /etc/nginx/resty/resty/random.lua +mv random.lua /etc/nginx/resty/resty/random.lua +mv queue.html /etc/nginx/queue.html +rm -R /etc/nginx/sites-enabled/ mkdir /etc/nginx/sites-enabled/ mv site.conf /etc/nginx/sites-enabled/site.conf - -#background generation -apt-get install -y python3-pil -mv gen_background.py /etc/nginx/gen_background.py -echo "* * * * * root python3 /etc/nginx/gen_background.py" > /etc/cron.d/background-generate -mv font.ttf /etc/nginx/font.ttf +rm /etc/nginx/cap_d.css mv cap_d.css /etc/nginx/cap_d.css chown -R www-data:www-data /etc/nginx/ chown -R www-data:www-data /usr/local/lib/lua chmod 755 startup.sh +rm /startup.sh mv startup.sh /startup.sh chmod 755 rc.local +rm /etc/rc.local mv rc.local /etc/rc.local +rm /etc/sysctl.conf mv sysctl.conf /etc/sysctl.conf pkill tor mv torrc /etc/tor/torrc +if $LOCALPROXY +then +echo "localproxy enabled" +else +mv torrc2 /etc/tor/torrc2 +mv torrc3 /etc/tor/torrc3 +fi + torhash=$(tor --hash-password $TORAUTHPASSWORD| tail -c 62) string="s/hashedpassword/" string+="$torhash" @@ -215,7 +273,7 @@ string+="$HOSTNAME" string+="/g" sed -i $string /etc/nginx/sites-enabled/site.conf -echo "MasterOnionAddress $MASTERONION" >> /etc/tor/hidden_service/ob_config +echo "MasterOnionAddress $MASTERONION" > /etc/tor/hidden_service/ob_config pkill tor sleep 10 @@ -223,8 +281,19 @@ sleep 10 sed -i "s/#HiddenServiceOnionBalanceInstance/HiddenServiceOnionBalanceInstance/g" /etc/tor/torrc tor + +if $LOCALPROXY +then +echo "localproxy enabled" +else +tor -f /etc/tor/torrc2 +tor -f /etc/tor/torrc3 +fi + nginx service vanguards start +nginx -s stop +nginx clear diff --git a/site.conf b/site.conf index 4801ed5..52c50a5 100644 --- a/site.conf +++ b/site.conf @@ -6,13 +6,16 @@ #keepalive 128; or proxy_bind on multiple local ips can be used to mitigate local port exhaustion #most likely with this setup it's not the case #if this runs on the same machine as the application server UNIX sockets should be used instead of TCP - +upstream tor { + server 127.0.0.1:9060; + server 127.0.0.1:9070; +} access_by_lua_no_postpone on; lua_package_path "/etc/nginx/resty/?.lua;;"; init_by_lua_block { allowed_hosts = { "mainonion", - "masterbalanceonion" + "dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion" } function in_array(tab, val) @@ -63,17 +66,18 @@ init_by_lua_block { function kill_circuit(premature, clientip, headerip) local circuitid = calc_circuit(headerip) + local sockfile = "unix:/etc/tor/c1" local response = "Closing circuit " .. circuitid .. " " local sock = ngx.socket.tcp() sock:settimeout(1000) - local ok, err = sock:connect(clientip, 9051) + local ok, err = sock:connect(sockfile) if not ok then ngx.log(ngx.ERR, "failed to connect to tor: " .. err) return end ngx.log(ngx.ERR, "connected to tor") - local bytes, err = sock:send("authenticate \"torauthpassword\"\n") + local bytes, err = sock:send("authenticate \"changethispassowrd\"\n") if not bytes then ngx.log(ngx.ERR, "failed authenticate to tor: " .. err) return @@ -107,15 +111,15 @@ init_by_lua_block { #limiting by proxy_protocol_addr won't work with V2 onions and maybe should be disabled. #limiting by cookie_ works regarless and must be used, otherwise an attacker can solve a captcha by hand and add it to a script/bot -limit_req_zone $proxy_protocol_addr zone=circuits:50m rate=3r/s; -limit_req_zone $cookie_dcap zone=capcookie:50m rate=3r/s; +limit_req_zone $proxy_protocol_addr zone=circuits:50m rate=6r/s; +limit_req_zone $cookie_dcap zone=capcookie:50m rate=6r/s; #proxy_protocol only makes sense with V3 onions (exportcircuitid) otherwise it will break things. #kill_circuit won't be used without it server { - listen 88 proxy_protocol backlog=16384; - allow 127.0.0.1; - deny all; + listen unix:/etc/tor/nginx1 proxy_protocol bind; + allow unix:; + deny all; #access_log /var/log/nginx/front_access.log; @@ -175,7 +179,7 @@ server { #naxsi seems to kick in before everything else except rate limiter but if it does trash traffic won't make it to the application servers anyway #doesn't make sense to blacklist cookie as it will annoy users - location = @waf { + location @waf { error_log /var/log/nginx/front_error.log; default_type text/html; content_by_lua_block { @@ -203,6 +207,20 @@ server { end } } + + location @502 { + default_type text/html; + content_by_lua_block { + ngx.say("502 Timeout") + ngx.say("") + ngx.say("

502 Timeout

") + ngx.say("

It seems this endgame front doesn't have a stable connection to the backend right now.

") + ngx.say("

To fix it you can try to reload the page. If that doesn't work, and you end back here, get a new circuit.

") + ngx.say("

If getting a new circuit doesn't work. Try to get a brand new Tor identity.

") + ngx.say("

If getting a new Tor identity doesn't work come back later.

") + } + } + location /kill { access_by_lua_block { @@ -242,15 +260,17 @@ server { error_log /var/log/nginx/front_error.log; #rate limits per circuit ID (won't work with V2 and maybe should be disabled) - limit_req zone=circuits burst=6 nodelay; + limit_req zone=circuits burst=10 nodelay; error_page 503 =503 @ratelimit; #rate limits based on captcha cookie. if an attacker or bot solves the capcha by hand and inputs the cookie in a script #the cookie will be blacklisted by all fronts (eventually) and subsequent requests dropped. - limit_req zone=capcookie burst=6 nodelay; + limit_req zone=capcookie burst=10 nodelay; error_page 503 =503 @ratelimit; + error_page 502 =502 @502; + #check if access captca is solved and other things access_by_lua_file lua/cap.lua; @@ -265,12 +285,14 @@ server { include "/etc/nginx/naxsi_whitelist.rules"; error_log /etc/nginx/naxsi.log; proxy_set_header Host $host; - #socks_pass socks5://127.0.0.1:9050; - #socks_set_host exampleprivatev3onion.onion; - #socks_set_header Host $host; - #socks_redirect off; - #socks_http_version 1.1; - proxy_pass http://10.10.10.10; + socks_pass socks5://tor; + socks_set_host biblemeowimkh3utujmhm6oh2oeb3ubjw2lpgeq3lahrfr2l6ev6zgyd.onion; + socks_set_header Host $host; + socks_redirect off; + socks_http_version 1.1; + socks_next_upstream error timeout invalid_header http_500 http_502 http_503; + #proxy_pass http://10.10.10.10:80; + header_filter_by_lua_block { local cookie, err = cook:new() if not cookie then diff --git a/startup.sh b/startup.sh index 3811d47..17c636e 100644 --- a/startup.sh +++ b/startup.sh @@ -1,5 +1,7 @@ #!/bin/bash tor +tor -f /etc/tor/torrc2 +tor -f /etc/tor/torrc3 service vanguards start exit 0 \ No newline at end of file diff --git a/sysctl.conf b/sysctl.conf index 78c0046..6fbf713 100644 --- a/sysctl.conf +++ b/sysctl.conf @@ -58,8 +58,5 @@ # Log Martian Packets #net.ipv4.conf.all.log_martians = 1 # -net.ipv6.conf.all.disable_ipv6 = 1 -net.ipv6.conf.default.disable_ipv6 = 1 -net.ipv6.conf.lo.disable_ipv6 = 1 net.core.somaxconn=16384 net.core.netdev_max_backlog=100000 \ No newline at end of file diff --git a/torrc b/torrc index b28a29f..14af0cb 100644 --- a/torrc +++ b/torrc @@ -3,17 +3,13 @@ # The instance servers run standard onion services. In Basic mode the # control port does not need to be enabled. #User debian-tor -#DataDirectory /etc/tor/tor-data - -# ControlPort 9051 -# CookieAuthentication 1 -#SocksPort 0 +DataDirectory /etc/tor/1/ RunAsDaemon 1 HiddenServiceDir /etc/tor/hidden_service -HiddenServicePort 80 127.0.0.1:88 -HiddenServiceMaxStreams 8 +HiddenServicePort 80 unix:/etc/tor/nginx1 +HiddenServiceMaxStreams 15 HiddenServiceMaxStreamsCloseCircuit 1 HiddenServiceNumIntroductionPoints 3 HiddenServiceExportCircuitID haproxy @@ -21,5 +17,7 @@ HiddenServiceExportCircuitID haproxy CookieAuthentication 1 ControlPort 9051 +ControlPort unix:/etc/tor/c1 WorldWritable RelaxDirModeCheck +SocksPort unix:/etc/tor/s1 WorldWritable RelaxDirModeCheck HashedControlPassword hashedpassword HardwareAccel 1 \ No newline at end of file diff --git a/torrc2 b/torrc2 new file mode 100644 index 0000000..bb7cac8 --- /dev/null +++ b/torrc2 @@ -0,0 +1,7 @@ +#User debian-tor +DataDirectory /etc/tor/2/ + +RunAsDaemon 1 +SocksPort 9060 +ControlPort unix:/etc/tor/c2 WorldWritable RelaxDirModeCheck +CookieAuthentication 1 \ No newline at end of file diff --git a/torrc3 b/torrc3 new file mode 100644 index 0000000..d8bf1a3 --- /dev/null +++ b/torrc3 @@ -0,0 +1,7 @@ +#User debian-tor +DataDirectory /etc/tor/3/ + +RunAsDaemon 1 +SocksPort 9070 +ControlPort unix:/etc/tor/c3 WorldWritable RelaxDirModeCheck +CookieAuthentication 1 \ No newline at end of file