diff --git a/.idea/endgame.iml b/.idea/endgame.iml deleted file mode 100644 index c956989..0000000 --- a/.idea/endgame.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 38a2e28..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 550d3f1..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/LOOKHERE-scripts/onionbalance/README.MD b/LOOKHERE-scripts/onionbalance/README.MD index afa3ca9..fe62ee7 100644 --- a/LOOKHERE-scripts/onionbalance/README.MD +++ b/LOOKHERE-scripts/onionbalance/README.MD @@ -19,6 +19,14 @@ 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 +and then you can setup the configuration with your front's URLs. -**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 +To run onionbalance cd into the onionbalance directory and run: + +nohup onionbalance -v info -c config/config.yaml & + +This will start onionbalance detacted from the terminal and then put it in the background. Afterwards you can run + +tail -f nohup.out + +and see the status of it. You want to see distinct descriptors being pushed. \ No newline at end of file diff --git a/README.MD b/README.MD index e2fc3cf..425b25c 100644 --- a/README.MD +++ b/README.MD @@ -82,7 +82,7 @@ The main configuration can be found at the top of the `setup.sh` file. It custom 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) -* KEY - Alphanumeric Key for the shared front session key. Random between 64-128 would do fine. (example: isthis64charactorsalreadyicantbelieveitwowsocoolwaitnotyetohdarn) +* KEY - Alphanumeric Key for the shared front session key. Random alphanumberic 64 or 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) diff --git a/cap_d.css b/cap_d.css index a83d768..7ced9f9 100644 --- a/cap_d.css +++ b/cap_d.css @@ -8,10 +8,10 @@ font-family:roboto, helvetica, sans-serif, arial, verdana, tahoma;font-size:16px .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>.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:#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;} +.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%;} diff --git a/lua/cap.lua b/lua/cap.lua index bd357e3..932503e 100644 --- a/lua/cap.lua +++ b/lua/cap.lua @@ -1,15 +1,15 @@ -- encryption key and salt must be shared across fronts. salt must be 8 chars local key = "encryption_key" -local salt = "1saltkey" +local salt = "salt1234" -- for how long the captcha is valid. 120 sec is for testing, 3600 1 hour should be production. -local session_timeout = 3600 +local session_timeout = sessionconfigvalue 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) +aes_128_cbc_sha512x1 = aes:new(key, salt, aes.cipher(128, "cbc"), aes.hash.sha512, 1) local cookie, err = cook:new() if not cookie then @@ -18,15 +18,21 @@ if not cookie then end function fromhex(str) - return (str:gsub('..', function (cc) - return string.char(tonumber(cc, 16)) - end)) + return (str:gsub( + "..", + function(cc) + return string.char(tonumber(cc, 16)) + end + )) end function tohex(str) - return (str:gsub('.', function (c) - return string.format('%02X', string.byte(c)) - end)) + return (str:gsub( + ".", + function(c) + return string.format("%02X", string.byte(c)) + end + )) end caperror = nil @@ -43,21 +49,21 @@ if in_array(allowed_hosts, ngx.var.http_host) == nil 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 + ngx.log(ngx.ERR, "failed to create timer: ", err) + return end end ngx.exit(444) end --- only GET and POST requests are allowed the others are not used. HEAD for recon checker -if ngx.var.request_method ~= "POST" and ngx.var.request_method ~= "GET" and ngx.var.request_method ~= "HEAD" then +-- only GET and POST requests are allowed the others are not used. +if ngx.var.request_method ~= "POST" and ngx.var.request_method ~= "GET" then ngx.log(ngx.ERR, "Wrong request (" .. ngx.var.request_method .. ") " .. ngx.var.remote_addr .. "|" .. pa) 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 + ngx.log(ngx.ERR, "failed to create timer: ", err) + return end end ngx.exit(444) @@ -69,8 +75,8 @@ if ngx.var.http_user_agent == nil 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 + ngx.log(ngx.ERR, "failed to create timer: ", err) + return end end ngx.exit(444) @@ -82,8 +88,8 @@ if ngx.var.request_method == "POST" and ngx.var.http_referer == nil 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 + ngx.log(ngx.ERR, "failed to create timer: ", err) + return end end ngx.exit(444) @@ -94,32 +100,40 @@ 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.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) + ngx.exit(200) end -- check cookie support similar to testcookie if ngx.var.request_method == "GET" then local field, err = cookie:get("dcap") - if err then - --local tstamp = ngx.now() + slidingscalefunction - local tstamp = ngx.now() + 10 - local plaintext = "queue|" .. tstamp .. "|1|" .. random.token(random.number(10,20)) + if err or not field then + local tstamp = ngx.now() + 5 + 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 = session_timeout, - samesite = "Lax" - }) + local ok, err = + cookie:set( + { + key = "dcap", + value = ciphertext, + path = "/", + domain = ngx.var.host, + httponly = true, + max_age = 120, + samesite = "Lax" + } + ) if not ok then ngx.log(ngx.ERR, err) return end - ngx.header.content_type = 'text/html' + ngx.header.content_type = "text/html" local file = io.open("/etc/nginx/queue.html") + if not file then + ngx.exit(500) + end local queue, err = file:read("*a") file:close() ngx.say(queue) @@ -128,16 +142,15 @@ if ngx.var.request_method == "GET" then else plaintext = aes_128_cbc_sha512x1:decrypt(fromhex(field)) if not plaintext then - ngx.header.content_type = 'text/plain' + 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,"|") + 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 (tonumber(cookdata[2])) > ngx.now() or (tonumber(cookdata[2])) > ngx.now() + 15 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 @@ -150,6 +163,7 @@ if ngx.var.request_method == "GET" then ngx.exit(444) end + -- captcha generator functions require "caphtml_d" local expired = nil @@ -157,7 +171,6 @@ if ngx.var.request_method == "GET" then 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 @@ -167,29 +180,39 @@ if ngx.var.request_method == "GET" then return end end - ngx.header.content_type = 'text/html' + 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 - + require "caphtml_d" + displaycap(session_timeout) + ngx.flush() + ngx.exit(200) + elseif (cookdata[1] == "captcha_solved") then if (tonumber(cookdata[2]) + session_timeout) < ngx.now() then - expired = true - caperror = "Session expired" - end - - if cookdata[1] ~= "captcha_solved" or expired then + require "caphtml_d" + local expired = true + caperror = "Session expired" displaycap(session_timeout) ngx.flush() ngx.exit(200) - end + end + else + 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 + local blocked_cookies = ngx.shared.blocked_cookies + blocked_cookies:set(field, 1, 3600) + ngx.header.content_type = "text/plain" + ngx.say("That isn't going to work here") + ngx.flush() + ngx.exit(200) end end end @@ -197,18 +220,18 @@ end if ngx.var.request_method == "POST" then local field, err = cookie:get("dcap") if err then - ngx.exit(403) + ngx.exit(403) end if field then plaintext = aes_128_cbc_sha512x1:decrypt(fromhex(field)) if not plaintext then - ngx.header.content_type = 'text/plain' + 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,"|") + cookdata = split(plaintext, "|") local expired = nil if (cookdata[1] == "cap_not_solved") then if (tonumber(cookdata[2]) + session_timeout) < ngx.now() then @@ -219,14 +242,14 @@ if ngx.var.request_method == "POST" then ngx.flush() ngx.exit(200) end - elseif (cookdata[1] == "captcha_solved") then + elseif (cookdata[1] == "captcha_solved") then return - end + end end require "caphtml_d" --- resty has a library for parsing POST data but it's not really needed + -- 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 @@ -240,18 +263,18 @@ if ngx.var.request_method == "POST" then data = split(data, "&") local sentcap = "" for index, value in ipairs(data) do - sentcap = sentcap .. split(value,"=")[2] + sentcap = sentcap .. split(value, "=")[2] end if field then plaintext = aes_128_cbc_sha512x1:decrypt(fromhex(field)) if not plaintext then - ngx.header.content_type = 'text/plain' + 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,"|") + cookdata = split(plaintext, "|") if (tonumber(cookdata[2]) + 60) < ngx.now() then caperror = "Captcha expired" @@ -263,23 +286,29 @@ if ngx.var.request_method == "POST" then if string.lower(sentcap) == string.lower(cookdata[3]) then local newcookdata = "" cookdata[1] = "captcha_solved" - for k,v in pairs(cookdata) do + cookdata[2] = ngx.now() + for k, v in pairs(cookdata) do newcookdata = newcookdata .. "|" .. v end - newcookdata = newcookdata .. "|" .. random.token(random.number(10,20)) - local tstamp = ngx.now() + 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 = session_timeout, - samesite = "Lax" - }) + local ok, err = + cookie:set( + { + key = "dcap", + value = ciphertext, + path = "/", + domain = ngx.var.host, + httponly = true, + max_age = session_timeout, + samesite = "Lax" + } + ) if not ok then ngx.say("cookie error") return - end - local redirect_to = ngx.var.uri + end + local redirect_to = ngx.var.uri if ngx.var.query_string ~= nil then redirect_to = redirect_to .. "?" .. ngx.var.query_string end @@ -289,6 +318,6 @@ if ngx.var.request_method == "POST" then end displaycap(session_timeout) ngx.flush() - ngx.exit(200) + ngx.exit(200) end -end \ No newline at end of file +end diff --git a/nginx-update.sh b/nginx-update.sh index fe01bf0..36ba0af 100644 --- a/nginx-update.sh +++ b/nginx-update.sh @@ -1,85 +1,40 @@ -#!/bin/bash - -apt-get update -apt-get -y upgrade - -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 -cd nginx-$NGINXVERSION - -apt-get install -y build-essential zlib1g-dev libpcre3 libpcre3-dev unzip uuid-dev gcc git wget curl libgd3 libgd-dev - -wget https://github.com/apache/incubator-pagespeed-ngx/archive/latest-beta.tar.gz -tar -xzvf latest-beta.tar.gz -cd incubator-pagespeed-ngx-latest-beta -wget https://dl.google.com/dl/page-speed/psol/1.13.35.2-x64.tar.gz -tar -xzvf 1.13.35.2-x64.tar.gz -cd .. - -git clone https://github.com/yorkane/socks-nginx-module -git clone https://github.com/nbs-system/naxsi.git -git clone https://github.com/kyprizel/testcookie-nginx-module.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 .. - -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' \ ---with-ld-opt="-Wl,-rpath,/usr/local/lib" \ ---with-compat --with-openssl=openssl-$NGINXOPENSSL \ ---with-http_ssl_module \ ---add-dynamic-module=incubator-pagespeed-ngx-latest-beta \ ---add-dynamic-module=naxsi/naxsi_src --add-dynamic-module=testcookie-nginx-module \ ---add-dynamic-module=headers-more-nginx-module \ ---add-dynamic-module=socks-nginx-module \ ---add-dynamic-module=echo-nginx-module \ - --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/ - -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 -rm -R /etc/nginx/modules/modules +#!/bin/bash + +apt-get update +apt-get -y upgrade + +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 + +wget https://www.openssl.org/source/openssl-$NGINXOPENSSL.tar.gz +tar -xzvf openssl-$NGINXOPENSSL.tar.gz + +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' \ +--with-ld-opt="-Wl,-rpath,/usr/local/lib" \ +--with-compat --with-openssl=openssl-$NGINXOPENSSL \ +--with-http_ssl_module \ +--add-dynamic-module=naxsi/naxsi_src \ +--add-dynamic-module=headers-more-nginx-module \ +--add-dynamic-module=socks-nginx-module \ +--add-dynamic-module=echo-nginx-module \ + --add-dynamic-module=ngx_devel_kit \ +--add-dynamic-module=lua-nginx-module + +make -j16 modules + +cp -r objs modules +rm -R /etc/nginx/modules +mkdir /etc/nginx/modules mv modules /etc/nginx/modules \ No newline at end of file diff --git a/queue.html b/queue.html index 5e289c6..0e9b244 100644 --- a/queue.html +++ b/queue.html @@ -1 +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.

+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/resty/caphtml_d.lua b/resty/caphtml_d.lua index 90abf49..fafefb7 100644 --- a/resty/caphtml_d.lua +++ b/resty/caphtml_d.lua @@ -1,4 +1,4 @@ -local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" local function base64_encode(data) return ((data:gsub('.', function(x) @@ -29,105 +29,7 @@ local function base64_decode(data) 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 im = createClock(190, hour, minute) -local imageraw = im:jpegStr(90) -local imageb64 = base64_encode(imageraw) - - + ngx.header.content_type = "text/html" local cookie, err = cook:new() if not cookie then ngx.log(ngx.ERR, err) @@ -135,150 +37,341 @@ local imageb64 = base64_encode(imageraw) ngx.exit(200) end - local tstamp = ngx.now() - 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 = "Lax" - }) - if not ok then - ngx.say("cookie error") - ngx.exit(200) + local field, err = cookie:get("dcap") + plaintext = aes_128_cbc_sha512x1:decrypt(fromhex(field)) + local blocked_cookies = ngx.shared.blocked_cookies + blocked_cookies:set(field, 1, 3600) + cookdata = split(plaintext, "|") + if (cookdata[1] == "cap_not_solved") then + if (cookdata[5] == "3") then + ngx.say("You failed the captcha too many times. Get a new identity and try again.") + ngx.exit(200) + end end + 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 -ngx.header.content_type = 'text/html'; -ngx.say(" \ + 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) + + im:setThickness(random.number(2, 3)) + fillcolor = im:colorAllocate(random.number(5, 255), random.number(5, 255), random.number(5, 255)) + x = random.number(40, 120) + y = random.number(40, 120) + im:arc(x, y, random.number(30, 90), random.number(30, 90), 0, 360, fillcolor) + + fillcolor = im:colorAllocate(random.number(5, 255), random.number(5, 255), random.number(5, 255)) + x = random.number(40, 120) + y = random.number(40, 120) + im:rectangle(x, y, x + random.number(30, 90), y + random.number(30, 90), fillcolor) + + x = random.number(40, 100) + y = random.number(x + 40, 180) + fillcolor = im:colorAllocate(random.number(5, 255), random.number(5, 255), random.number(5, 255)) + im:polygon( + { + {cxy, cxy}, + {random.number(10, 150), random.number(10, 150)}, + {random.number(10, 150), random.number(10, 150)} + }, + fillcolor + ) + return im + end + + local im = createClock(190, hour, minute) + local imageraw = im:jpegStr(80) + local imageb64 = base64_encode(imageraw) + + hour = tostring(hour) + minute = tostring(minute) + if string.len(hour) < 2 then + hour = "0" .. hour + end + if string.len(minute) < 2 then + minute = "0" .. minute + end + + if (cookdata[1] == "queue") then + local tstamp = ngx.now() + local newcookdata = "cap_not_solved|" .. tstamp .. "|" .. hour .. minute + + newcookdata = newcookdata .. "|" .. random.token(random.number(10, 20)) .. "|1" + + 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 = 120, + samesite = "Lax" + } + ) + if not ok then + ngx.say("cookie error") + ngx.exit(200) + end + else + local tstamp = ngx.now() + local tries = tonumber(cookdata[5] + 1) + local newcookdata = "cap_not_solved|" .. tstamp .. "|" .. hour .. minute + + newcookdata = newcookdata .. "|" .. random.token(random.number(10, 20)) .. "|" .. tries + + 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 = 120, + samesite = "Lax" + } + ) + if not ok then + ngx.say("cookie error") + ngx.exit(200) + end + end + + ngx.say(' \ \ \ DDOS Protection \ - \ - \ - \ - \ -
\ -
\ -
\ -
\ -
dread
\ -
") -if caperror ~= nil -then -ngx.say("

Error: " .. caperror .. "

") -else -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("
\ -
\ -
\ -
\ -
\ - 0 \ - 5 \ - 4 \ - 3 \ - 2 \ - 1 \ - 0 \ + ngx.say(' \ +
\ +
\ +') + + if caperror ~= nil then + ngx.say('

Error: ' .. caperror .. "

") + else + 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( + '
\ +
\ +
\ +
\ +
\ + 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 \ +
\ +
\ +
\ + 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(" \ - \ + ngx.say(' \ + \ \
\
\ \ -") - +') end + diff --git a/setup.sh b/setup.sh index 110c18d..8dd1b5d 100755 --- a/setup.sh +++ b/setup.sh @@ -17,7 +17,8 @@ SESSION_LENGTH=3600 #CSS Branding -HEXCOLOR="#9b59b6" +HEXCOLOR="9b59b6" +HEXCOLORDARK="6d3d82" SITENAME="dread" #There is more branding you need to do in the resty/caphtml_d.lua file near the end. @@ -32,7 +33,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 "Onionbalance v3 does have distinct descriptors in a forked version. Read the README.MD in the onionbalance folder for more information. " +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." @@ -104,6 +105,11 @@ string+="$HEXCOLOR" string+="/g" sed -i $string queue.html +string="s/HEXCOLORDARK/" +string+="$HEXCOLORDARK" +string+="/g" +sed -i $string queue.html + string="s/SITENAME/" string+="$SITENAME" string+="/g" diff --git a/site.conf b/site.conf index 52c50a5..1398a27 100644 --- a/site.conf +++ b/site.conf @@ -15,7 +15,7 @@ lua_package_path "/etc/nginx/resty/?.lua;;"; init_by_lua_block { allowed_hosts = { "mainonion", - "dreadytofatroptsdj6io7l3xptbet6onoyno2yv7jicoxknyazubrad.onion" + "masterbalanceonion" } function in_array(tab, val) @@ -77,7 +77,7 @@ init_by_lua_block { end ngx.log(ngx.ERR, "connected to tor") - local bytes, err = sock:send("authenticate \"changethispassowrd\"\n") + local bytes, err = sock:send("authenticate \"torauthpassword\"\n") if not bytes then ngx.log(ngx.ERR, "failed authenticate to tor: " .. err) return @@ -286,12 +286,12 @@ server { error_log /etc/nginx/naxsi.log; proxy_set_header Host $host; socks_pass socks5://tor; - socks_set_host biblemeowimkh3utujmhm6oh2oeb3ubjw2lpgeq3lahrfr2l6ev6zgyd.onion; + socks_set_host backendurl; 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; + #proxy_pass http://proxypassurl; header_filter_by_lua_block { local cookie, err = cook:new() @@ -328,4 +328,4 @@ server { end } } -} \ No newline at end of file +}