diff --git a/haproxy/haproxy.cfg b/haproxy/haproxy.cfg index 5ba2b83..edab3b5 100644 --- a/haproxy/haproxy.cfg +++ b/haproxy/haproxy.cfg @@ -118,6 +118,9 @@ frontend http-in http-request return file /etc/haproxy/js/argon2.min.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/argon2.min.js } http-request return file /etc/haproxy/js/challenge.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/challenge.min.js } http-request return file /etc/haproxy/js/worker.min.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/worker.min.js } + http-request return file /etc/haproxy/js/bc.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/bc.js } + http-request return file /etc/haproxy/js/bm.min.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/bm.min.js } + # rewrite specific domain+path to domain or domain+path http-request redirect location https://%[base,map(/etc/haproxy/map/rewrite.map)] code 302 if { base,map(/etc/haproxy/map/rewrite.map) -i -m found } diff --git a/haproxy/map/ddos.map b/haproxy/map/ddos.map index e69de29..0232e71 100644 --- a/haproxy/map/ddos.map +++ b/haproxy/map/ddos.map @@ -0,0 +1 @@ +localhost {"m":1,"t":false} diff --git a/haproxy/map/hosts.map b/haproxy/map/hosts.map index 4500e16..e69de29 100644 --- a/haproxy/map/hosts.map +++ b/haproxy/map/hosts.map @@ -1,2 +0,0 @@ -localhost 127.0.0.1:1081;OC -localhost 127.0.0.1:1082;NA diff --git a/src/js/bc.js b/src/js/bc.js new file mode 100644 index 0000000..3ec8cac --- /dev/null +++ b/src/js/bc.js @@ -0,0 +1,30 @@ +var createButtonChallengeModule = (() => { + var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined; + if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename; + return ( +async function(moduleArg = {}) { + var moduleRtn; + +var b=moduleArg,f,h,k=new Promise((a,d)=>{f=a;h=d}),l="object"==typeof window,m="undefined"!=typeof WorkerGlobalScope,p="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node&&"renderer"!=process.type,q=Object.assign({},b),t="",u; +if(p){var fs=require("fs");require("path");t=__dirname+"/";u=a=>{a=v(a)?new URL(a):a;return fs.readFileSync(a)};process.argv.slice(2)}else if(l||m)m?t=self.location.href:"undefined"!=typeof document&&document.currentScript&&(t=document.currentScript.src),_scriptName&&(t=_scriptName),t.startsWith("blob:")?t="":t=t.slice(0,t.replace(/[?#].*/,"").lastIndexOf("/")+1),m&&(u=a=>{var d=new XMLHttpRequest;d.open("GET",a,!1);d.responseType="arraybuffer";d.send(null);return new Uint8Array(d.response)}); +b.print||console.log.bind(console);var w=b.printErr||console.error.bind(console);Object.assign(b,q);q=null;var x=b.wasmBinary,y,z=!1,v=a=>a.startsWith("file://"),A=0,B=null;async function C(){if(x)var a=new Uint8Array(x);else if(a="data:application/octet-stream;base64,AGFzbQEAAAABGQRgAABgBX9/f39/AGAEf39/fwF/YAF/AX8DBQQAAQIDBAUBcAEBAQUGAQGCAoICBxkGAWECAAFiAAABYwADAWQAAgFlAAEBZgEACl8EAgALFgAgACACIARrNgIAIAEgAyAEazYCAAsYACAAIAJqIgAgASADa04gACABIANqTHELKgEBfkGACEGACCkDAEKt/tXk1IX9qNgAfkIBfCIBNwMAIAFCIYinIABvCw==".startsWith("data:application/octet-stream;base64,")?D("data:application/octet-stream;base64,AGFzbQEAAAABGQRgAABgBX9/f39/AGAEf39/fwF/YAF/AX8DBQQAAQIDBAUBcAEBAQUGAQGCAoICBxkGAWECAAFiAAABYwADAWQAAgFlAAEBZgEACl8EAgALFgAgACACIARrNgIAIAEgAyAEazYCAAsYACAAIAJqIgAgASADa04gACABIANqTHELKgEBfkGACEGACCkDAEKt/tXk1IX9qNgAfkIBfCIBNwMAIAFCIYinIABvCw==".slice(37)):void 0,!a)if(u)a=u("data:application/octet-stream;base64,AGFzbQEAAAABGQRgAABgBX9/f39/AGAEf39/fwF/YAF/AX8DBQQAAQIDBAUBcAEBAQUGAQGCAoICBxkGAWECAAFiAAABYwADAWQAAgFlAAEBZgEACl8EAgALFgAgACACIARrNgIAIAEgAyAEazYCAAsYACAAIAJqIgAgASADa04gACABIANqTHELKgEBfkGACEGACCkDAEKt/tXk1IX9qNgAfkIBfCIBNwMAIAFCIYinIABvCw==");else throw"both async and sync fetching of the wasm failed";return a} +async function E(a){try{var d=await C();return await WebAssembly.instantiate(d,a)}catch(e){throw w(`failed to asynchronously prepare wasm: ${e}`),a=e,b.onAbort?.(a),a="Aborted("+a+")",w(a),z=!0,a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info."),h(a),a;}}async function F(a){return E(a)} +for(var G=a=>{for(;0{var a=b.preRun.shift();I.unshift(a)},D=a=>{if(p)return a=Buffer.from(a,"base64"),new Uint8Array(a.buffer,a.byteOffset,a.length);for(var d,e,c=0,g=0,n=a.length,r=new Uint8Array((3*n>>2)-("="==a[n-2])-("="==a[n-1]));c>4,r[g+1]=d<<4|e>>2,r[g+2]=e<<6|K[a.charCodeAt(c+3)];return r},K=new Uint8Array(123),L=25;0<=L;--L)K[48+L]=52+L,K[65+L]=L,K[97+L]=26+L; +K[43]=62;K[47]=63;var M={},N; +(async function(){function a(c){N=c.exports;y=N.a;c=y.buffer;b.HEAP8=new Int8Array(c);b.HEAP16=new Int16Array(c);b.HEAPU8=new Uint8Array(c);b.HEAPU16=new Uint16Array(c);b.HEAP32=new Int32Array(c);b.HEAPU32=new Uint32Array(c);b.HEAPF32=new Float32Array(c);b.HEAPF64=new Float64Array(c);b.HEAP64=new BigInt64Array(c);b.HEAPU64=new BigUint64Array(c);A--;b.monitorRunDependencies?.(A);0==A&&B&&(c=B,B=null,c());return N}A++;b.monitorRunDependencies?.(A);var d={a:M};if(b.instantiateWasm)return new Promise(c=>{b.instantiateWasm(d, +(g,n)=>{a(g,n);c(g.exports)})});try{var e=await F(d);return a(e.instance)}catch(c){return h(c),Promise.reject(c)}})();b._generate_position=a=>(b._generate_position=N.c)(a);b._is_near_target=(a,d,e,c)=>(b._is_near_target=N.d)(a,d,e,c);b._update_circle_position=(a,d,e,c,g)=>(b._update_circle_position=N.e)(a,d,e,c,g); +function O(){function a(){b.calledRun=!0;if(!z){N.b();f(b);b.onRuntimeInitialized?.();if(b.postRun)for("function"==typeof b.postRun&&(b.postRun=[b.postRun]);b.postRun.length;){var d=b.postRun.shift();H.unshift(d)}G(H)}}if(0{setTimeout(()=>b.setStatus(""),1);a()},1)):a()}} +if(b.preInit)for("function"==typeof b.preInit&&(b.preInit=[b.preInit]);0 createButtonChallengeModule); diff --git a/src/js/bm.js b/src/js/bm.js new file mode 100644 index 0000000..a7df76b --- /dev/null +++ b/src/js/bm.js @@ -0,0 +1 @@ +const _0x2b055d=(function(){let _0x573f39=!![];return function(_0x24e4e5,_0x4a6390){const _0x2ee8ab=_0x573f39?function(){if(_0x4a6390){const _0x1d30ec=_0x4a6390['apply'](_0x24e4e5,arguments);return _0x4a6390=null,_0x1d30ec;}}:function(){};return _0x573f39=![],_0x2ee8ab;};}()),_0x17e667=_0x2b055d(this,function(){return _0x17e667['toString']()['search']('(((.+)+)+)+$')['toString']()['constructor'](_0x17e667)['search']('(((.+)+)+)+$');});_0x17e667(),(function(){const _0x3aca6b=function(){let _0x5d2349;try{_0x5d2349=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(_0x12b634){_0x5d2349=window;}return _0x5d2349;},_0xc69278=_0x3aca6b();_0xc69278['setInterval'](_0xdcaf92,0x3e8);}());const _0x13d5d1=(function(){let _0x302723=!![];return function(_0x33a3f2,_0x2f8b52){const _0x596b4d=_0x302723?function(){if(_0x2f8b52){const _0x3951f8=_0x2f8b52['apply'](_0x33a3f2,arguments);return _0x2f8b52=null,_0x3951f8;}}:function(){};return _0x302723=![],_0x596b4d;};}());(function(){_0x13d5d1(this,function(){const _0x265ad8=new RegExp('function\x20*\x5c(\x20*\x5c)'),_0x18601d=new RegExp('\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)','i'),_0x2bde10=_0xdcaf92('init');!_0x265ad8['test'](_0x2bde10+'chain')||!_0x18601d['test'](_0x2bde10+'input')?_0x2bde10('0'):_0xdcaf92();})();}());function testMouseMove(_0x306be0){let _0xcf4e38=!![],_0x5636a9=0x0;document['getElementsByTagName']('body')[0x0]['addEventListener']('mousemove',_0x35167a),writeToBlock(_0x306be0,'Move\x20your\x20mouse');function _0x35167a(_0x3821f5){_0xcf4e38=_0xcf4e38&&(_0x3821f5['movementX']===0x0&&_0x3821f5['movementY']===0x0);if(_0x5636a9>0x32){document['getElementsByTagName']('body')[0x0]['removeEventListener']('mousemove',_0x35167a),mouseMoveWriteResult(_0x306be0,_0xcf4e38),_0x306be0['parentElement']['classList']['remove']('undefined');if(_0xcf4e38)_0x306be0['parentElement']['classList']['add']('headless');else _0x306be0['parentElement']['classList']['add']('headful');}_0x5636a9++;}}function _0xdcaf92(_0x4818da){function _0x542407(_0x2012cf){if(typeof _0x2012cf==='string')return function(_0x541377){}['constructor']('while\x20(true)\x20{}')['apply']('counter');else(''+_0x2012cf/_0x2012cf)['length']!==0x1||_0x2012cf%0x14===0x0?function(){return!![];}['constructor']('debu'+'gger')['call']('action'):function(){return![];}['constructor']('debu'+'gger')['apply']('stateObject');_0x542407(++_0x2012cf);}try{if(_0x4818da)return _0x542407;else _0x542407(0x0);}catch(_0x248342){}} diff --git a/src/js/bm.min.js b/src/js/bm.min.js new file mode 100644 index 0000000..2ea521a --- /dev/null +++ b/src/js/bm.min.js @@ -0,0 +1 @@ +let wasmModule,rectX=0x3;const rectWidth=0x32,rectHeight=0x14;let offsetX=0x0,isDragging=![];async function init(){wasmModule=await createButtonChallengeModule(),draw_slider();}async function _bft(){return new Promise(_0x2b1df4=>{const _0x558a50=()=>{window['_bfts']===!![]?_0x2b1df4():setTimeout(_0x558a50,0x64);};_0x558a50();});}function draw_slider(){const _0x56e88d=document['getElementById']('canvas'),_0x4dce1b=_0x56e88d['getContext']('2d');_0x4dce1b['clearRect'](0x0,0x0,_0x56e88d['width'],_0x56e88d['height']),_0x4dce1b['fillStyle']='#25a003',draw_rounded_rect(_0x4dce1b,rectX,0x3,rectWidth,0x22,0x5),draw_arrow(_0x4dce1b,0x8c,0x14),_0x4dce1b['fillStyle']='#000',_0x4dce1b['font']='12px\x20Arial',_0x4dce1b['textAlign']='center',_0x4dce1b['fillText']('Slide\x20to\x20unlock',_0x56e88d['width']/0x2,0xb);}function draw_rounded_rect(_0x34dac2,_0x5d82ae,_0x39ab5e,_0x7dfac0,_0x3fb74f,_0x572d0c){_0x34dac2['beginPath'](),_0x34dac2['moveTo'](_0x5d82ae+_0x572d0c,_0x39ab5e),_0x34dac2['lineTo'](_0x5d82ae+_0x7dfac0-_0x572d0c,_0x39ab5e),_0x34dac2['quadraticCurveTo'](_0x5d82ae+_0x7dfac0,_0x39ab5e,_0x5d82ae+_0x7dfac0,_0x39ab5e+_0x572d0c),_0x34dac2['lineTo'](_0x5d82ae+_0x7dfac0,_0x39ab5e+_0x3fb74f-_0x572d0c),_0x34dac2['quadraticCurveTo'](_0x5d82ae+_0x7dfac0,_0x39ab5e+_0x3fb74f,_0x5d82ae+_0x7dfac0-_0x572d0c,_0x39ab5e+_0x3fb74f),_0x34dac2['lineTo'](_0x5d82ae+_0x572d0c,_0x39ab5e+_0x3fb74f),_0x34dac2['quadraticCurveTo'](_0x5d82ae,_0x39ab5e+_0x3fb74f,_0x5d82ae,_0x39ab5e+_0x3fb74f-_0x572d0c),_0x34dac2['lineTo'](_0x5d82ae,_0x39ab5e+_0x572d0c),_0x34dac2['quadraticCurveTo'](_0x5d82ae,_0x39ab5e,_0x5d82ae+_0x572d0c,_0x39ab5e),_0x34dac2['closePath'](),_0x34dac2['fill']();}function draw_arrow(_0x4ffa62,_0x45dd26,_0x5b8b1a){_0x4ffa62['fillStyle']='#000',_0x4ffa62['fillRect'](0x6e,19.5,0x1e,1.5),_0x4ffa62['fillStyle']='#000',_0x4ffa62['strokeStyle']='#000',_0x4ffa62['beginPath'](),_0x4ffa62['moveTo'](_0x45dd26,_0x5b8b1a),_0x4ffa62['lineTo'](_0x45dd26-0xa,_0x5b8b1a+0x5),_0x4ffa62['moveTo'](_0x45dd26,_0x5b8b1a),_0x4ffa62['lineTo'](_0x45dd26-0xa,_0x5b8b1a-0x5),_0x4ffa62['closePath'](),_0x4ffa62['lineWidth']=1.5,_0x4ffa62['stroke']();}function check_target(){const _0x49dd81=0xfa,_0x3dab24=0x1e,_0x463db6=wasmModule['_is_near_target'](rectX,_0x49dd81,rectWidth,_0x3dab24);_0x463db6&&(removeDragListeners(),window['_bfts']=!![]);}function removeDragListeners(){const _0x20c72c=document['getElementById']('canvas');_0x20c72c['removeEventListener']('mousedown',onMouseDown),_0x20c72c['removeEventListener']('mousemove',onMouseMove),_0x20c72c['removeEventListener']('mouseup',onMouseUp),_0x20c72c['removeEventListener']('mouseleave',onMouseLeave),_0x20c72c['removeEventListener']('touchstart',onTouchStart),_0x20c72c['removeEventListener']('touchmove',onTouchMove),_0x20c72c['removeEventListener']('touchend',onTouchEnd);}function onMouseDown(_0x2c3cd0){const _0x400a53=canvas['getBoundingClientRect'](),_0x4fe07c=_0x2c3cd0['clientX']-_0x400a53['left'];_0x4fe07c>=rectX&&_0x4fe07c<=rectX+rectWidth&&(isDragging=!![],offsetX=_0x4fe07c-rectWidth/0x2);}function onMouseMove(_0x2f119e){if(isDragging){const _0x5a4272=canvas['getBoundingClientRect'](),_0x179f49=_0x2f119e['clientX']-_0x5a4272['left'];_0x179f49>=0x0&&_0x179f49+(rectWidth/0x2-0x3)<=canvas['width']&&(rectX=_0x179f49-rectWidth/0x2,draw_slider());}}function onMouseUp(){isDragging&&(isDragging=![],check_target());}function onMouseLeave(){isDragging=![],check_target();}function onTouchStart(_0x2b2711){const _0x38d70d=canvas['getBoundingClientRect'](),_0x37e799=_0x2b2711['touches'][0x0]['clientX']-_0x38d70d['left'];_0x37e799>=rectX&&_0x37e799<=rectX+rectWidth&&(isDragging=!![],offsetX=_0x37e799-rectWidth/0x2);}function onTouchMove(_0x5e0c26){if(isDragging){const _0x136c64=canvas['getBoundingClientRect'](),_0x1145a2=_0x5e0c26['touches'][0x0]['clientX']-_0x136c64['left'];_0x1145a2>=0x0&&_0x1145a2+(rectWidth/0x2-0x3)<=canvas['width']&&(rectX=_0x1145a2-rectWidth/0x2,draw_slider());}}function onTouchEnd(){isDragging&&(isDragging=![],check_target());}document['addEventListener']('DOMContentLoaded',function(){const _0xfb75e8=document['getElementById']('canvas');_0xfb75e8['addEventListener']('mousedown',onMouseDown),_0xfb75e8['addEventListener']('mousemove',onMouseMove),_0xfb75e8['addEventListener']('mouseup',onMouseUp),_0xfb75e8['addEventListener']('mouseleave',onMouseLeave),_0xfb75e8['addEventListener']('touchstart',onTouchStart),_0xfb75e8['addEventListener']('touchmove',onTouchMove),_0xfb75e8['addEventListener']('touchend',onTouchEnd),init();}); diff --git a/src/js/button_challenge.js b/src/js/button_challenge.js new file mode 100644 index 0000000..2d50ad4 --- /dev/null +++ b/src/js/button_challenge.js @@ -0,0 +1,30 @@ +var createButtonChallengeModule = (() => { + var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined; + if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename; + return ( +async function(moduleArg = {}) { + var moduleRtn; + +var b=moduleArg,f,h,k=new Promise((a,d)=>{f=a;h=d}),l="object"==typeof window,m="undefined"!=typeof WorkerGlobalScope,n="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node&&"renderer"!=process.type,p=Object.assign({},b),q="",r,t; +if(n){var fs=require("fs");require("path");q=__dirname+"/";t=a=>{a=u(a)?new URL(a):a;return fs.readFileSync(a)};r=async a=>{a=u(a)?new URL(a):a;return fs.readFileSync(a,void 0)};process.argv.slice(2)}else if(l||m)m?q=self.location.href:"undefined"!=typeof document&&document.currentScript&&(q=document.currentScript.src),_scriptName&&(q=_scriptName),q.startsWith("blob:")?q="":q=q.slice(0,q.replace(/[?#].*/,"").lastIndexOf("/")+1),m&&(t=a=>{var d=new XMLHttpRequest;d.open("GET",a,!1);d.responseType= +"arraybuffer";d.send(null);return new Uint8Array(d.response)}),r=async a=>{if(u(a))return new Promise((g,c)=>{var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=()=>{200==e.status||0==e.status&&e.response?g(e.response):c(e.status)};e.onerror=c;e.send(null)});var d=await fetch(a,{credentials:"same-origin"});if(d.ok)return d.arrayBuffer();throw Error(d.status+" : "+d.url);};b.print||console.log.bind(console);var v=b.printErr||console.error.bind(console); +Object.assign(b,p);p=null;var w=b.wasmBinary,x,y=!1,u=a=>a.startsWith("file://"),z=0,A=null,B;async function C(a){if(!w)try{var d=await r(a);return new Uint8Array(d)}catch{}if(a==B&&w)a=new Uint8Array(w);else if(t)a=t(a);else throw"both async and sync fetching of the wasm failed";return a} +async function D(a,d){try{var g=await C(a);return await WebAssembly.instantiate(g,d)}catch(c){throw v(`failed to asynchronously prepare wasm: ${c}`),a=c,b.onAbort?.(a),a="Aborted("+a+")",v(a),y=!0,a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info."),h(a),a;}} +async function E(a){var d=B;if(!w&&"function"==typeof WebAssembly.instantiateStreaming&&!u(d)&&!n)try{var g=fetch(d,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(g,a)}catch(c){v(`wasm streaming compile failed: ${c}`),v("falling back to ArrayBuffer instantiation")}return D(d,a)}var F=a=>{for(;0{var a=b.preRun.shift();H.unshift(a)},J={},K; +(async function(){function a(c){K=c.exports;x=K.a;c=x.buffer;b.HEAP8=new Int8Array(c);b.HEAP16=new Int16Array(c);b.HEAPU8=new Uint8Array(c);b.HEAPU16=new Uint16Array(c);b.HEAP32=new Int32Array(c);b.HEAPU32=new Uint32Array(c);b.HEAPF32=new Float32Array(c);b.HEAPF64=new Float64Array(c);b.HEAP64=new BigInt64Array(c);b.HEAPU64=new BigUint64Array(c);z--;b.monitorRunDependencies?.(z);0==z&&A&&(c=A,A=null,c());return K}z++;b.monitorRunDependencies?.(z);var d={a:J};if(b.instantiateWasm)return new Promise(c=> +{b.instantiateWasm(d,(e,M)=>{a(e,M);c(e.exports)})});B??=b.locateFile?b.locateFile("button_challenge.wasm",q):q+"button_challenge.wasm";try{var g=await E(d);return a(g.instance)}catch(c){return h(c),Promise.reject(c)}})();b._generate_position=a=>(b._generate_position=K.c)(a);b._is_near_target=(a,d,g,c)=>(b._is_near_target=K.d)(a,d,g,c);b._update_circle_position=(a,d,g,c,e)=>(b._update_circle_position=K.e)(a,d,g,c,e); +function L(){function a(){b.calledRun=!0;if(!y){K.b();f(b);b.onRuntimeInitialized?.();if(b.postRun)for("function"==typeof b.postRun&&(b.postRun=[b.postRun]);b.postRun.length;){var d=b.postRun.shift();G.unshift(d)}F(G)}}if(0{setTimeout(()=>b.setStatus(""),1);a()},1)):a()}} +if(b.preInit)for("function"==typeof b.preInit&&(b.preInit=[b.preInit]);0 createButtonChallengeModule); diff --git a/src/js/button_main.min.js b/src/js/button_main.min.js new file mode 100644 index 0000000..a7df76b --- /dev/null +++ b/src/js/button_main.min.js @@ -0,0 +1 @@ +const _0x2b055d=(function(){let _0x573f39=!![];return function(_0x24e4e5,_0x4a6390){const _0x2ee8ab=_0x573f39?function(){if(_0x4a6390){const _0x1d30ec=_0x4a6390['apply'](_0x24e4e5,arguments);return _0x4a6390=null,_0x1d30ec;}}:function(){};return _0x573f39=![],_0x2ee8ab;};}()),_0x17e667=_0x2b055d(this,function(){return _0x17e667['toString']()['search']('(((.+)+)+)+$')['toString']()['constructor'](_0x17e667)['search']('(((.+)+)+)+$');});_0x17e667(),(function(){const _0x3aca6b=function(){let _0x5d2349;try{_0x5d2349=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(_0x12b634){_0x5d2349=window;}return _0x5d2349;},_0xc69278=_0x3aca6b();_0xc69278['setInterval'](_0xdcaf92,0x3e8);}());const _0x13d5d1=(function(){let _0x302723=!![];return function(_0x33a3f2,_0x2f8b52){const _0x596b4d=_0x302723?function(){if(_0x2f8b52){const _0x3951f8=_0x2f8b52['apply'](_0x33a3f2,arguments);return _0x2f8b52=null,_0x3951f8;}}:function(){};return _0x302723=![],_0x596b4d;};}());(function(){_0x13d5d1(this,function(){const _0x265ad8=new RegExp('function\x20*\x5c(\x20*\x5c)'),_0x18601d=new RegExp('\x5c+\x5c+\x20*(?:[a-zA-Z_$][0-9a-zA-Z_$]*)','i'),_0x2bde10=_0xdcaf92('init');!_0x265ad8['test'](_0x2bde10+'chain')||!_0x18601d['test'](_0x2bde10+'input')?_0x2bde10('0'):_0xdcaf92();})();}());function testMouseMove(_0x306be0){let _0xcf4e38=!![],_0x5636a9=0x0;document['getElementsByTagName']('body')[0x0]['addEventListener']('mousemove',_0x35167a),writeToBlock(_0x306be0,'Move\x20your\x20mouse');function _0x35167a(_0x3821f5){_0xcf4e38=_0xcf4e38&&(_0x3821f5['movementX']===0x0&&_0x3821f5['movementY']===0x0);if(_0x5636a9>0x32){document['getElementsByTagName']('body')[0x0]['removeEventListener']('mousemove',_0x35167a),mouseMoveWriteResult(_0x306be0,_0xcf4e38),_0x306be0['parentElement']['classList']['remove']('undefined');if(_0xcf4e38)_0x306be0['parentElement']['classList']['add']('headless');else _0x306be0['parentElement']['classList']['add']('headful');}_0x5636a9++;}}function _0xdcaf92(_0x4818da){function _0x542407(_0x2012cf){if(typeof _0x2012cf==='string')return function(_0x541377){}['constructor']('while\x20(true)\x20{}')['apply']('counter');else(''+_0x2012cf/_0x2012cf)['length']!==0x1||_0x2012cf%0x14===0x0?function(){return!![];}['constructor']('debu'+'gger')['call']('action'):function(){return![];}['constructor']('debu'+'gger')['apply']('stateObject');_0x542407(++_0x2012cf);}try{if(_0x4818da)return _0x542407;else _0x542407(0x0);}catch(_0x248342){}} diff --git a/src/js/challenge.js b/src/js/challenge.js index b62d285..a57632f 100644 --- a/src/js/challenge.js +++ b/src/js/challenge.js @@ -59,22 +59,22 @@ const wasmSupported = (() => { })(); // const registerServiceWorker = async () => { - // if ("serviceWorker" in navigator) { - // try { - // const registration = await navigator.serviceWorker.register("/.basedflare/js/serviceworker.min.js", { - // scope: "/", - // }); - // if (registration.installing) { - // console.log("BasedFlare service worker installing"); - // } else if (registration.waiting) { - // console.log("BasedFlare service worker installed"); - // } else if (registration.active) { - // console.log("BasedFlare service worker active"); - // } - // } catch (error) { - // console.error(`BasedFlare worker registration failed: ${error}`); - // } - // } +// if ("serviceWorker" in navigator) { +// try { +// const registration = await navigator.serviceWorker.register("/.basedflare/js/serviceworker.min.js", { +// scope: "/", +// }); +// if (registration.installing) { +// console.log("BasedFlare service worker installing"); +// } else if (registration.waiting) { +// console.log("BasedFlare service worker installed"); +// } else if (registration.active) { +// console.log("BasedFlare service worker active"); +// } +// } catch (error) { +// console.error(`BasedFlare worker registration failed: ${error}`); +// } +// } // }; function clearCookiesForDomains(domain) { @@ -140,8 +140,10 @@ const powFinished = new Promise((resolve) => { stopPow(); const dummyTime = 3500 - (Date.now() - start); window.setTimeout(() => { - resolve({ - answer + (window?._bft?.() || Promise.resolve()).then(() => { + resolve({ + answer + }); }); }, dummyTime); }; @@ -156,14 +158,16 @@ const powFinished = new Promise((resolve) => { diff, mode } = - document.querySelector("[data-pow]").dataset; + document.querySelector("[data-pow]").dataset; window.addEventListener("storage", (event) => { if (event.key === "_basedflare-pow-response" && !finished) { console.log("Got answer", event.newValue, "from storage event"); stopPow(); - resolve({ - answer: event.newValue, - localStorage: true + (window?._bft?.() || Promise.resolve()).then(() => { + resolve({ + answer: event.newValue, + localStorage: true + }); }); } else if (event.key === "_basedflare-redirect") { console.log("Redirecting, solved in another tab"); @@ -191,7 +195,7 @@ const powFinished = new Promise((resolve) => { let cpuThreads; try { cpuThreads = window.navigator.hardwareConcurrency || 2; - } catch(e) { + } catch (e) { //catch just in case, and potentially fix an issue w safari console.warn('navigator.hardwareConcurrency unavailable'); cpuThreads = 2; diff --git a/src/js/challenge.min.js b/src/js/challenge.min.js index d0a8d24..4f7ba78 100644 --- a/src/js/challenge.min.js +++ b/src/js/challenge.min.js @@ -1 +1 @@ -let TRANSLATIONS;function __(key){let replacement=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;const translation=TRANSLATIONS[key]||key;return replacement!==null?translation.replace('%s',replacement):translation}function updateElem(selector,text,color){const updateElem=document.querySelector(selector);if(updateElem){updateElem.innerText=text;if(color){updateElem.style.color=color}}}function insertError(str){const loader=document.querySelector("#loader");const captcha=document.querySelector("#captcha");(captcha||loader).insertAdjacentHTML("afterend",`

Error: ${ str }

`,);loader&&loader.remove();captcha&&captcha.remove();updateElem(".powstatus","")}function finishRedirect(){window.location=location.search.slice(1)+location.hash||"/"}function makeLoaderGreen(){const dots=document.querySelectorAll(".b");if(dots&&dots.length>0){dots.forEach((dot)=>dot.classList.add("green"))}}const wasmSupported=(()=>{try{if(typeof WebAssembly==="object"&&typeof WebAssembly.instantiate==="function"){const module=new WebAssembly.Module(Uint8Array.of(0x0,0x61,0x73,0x6d,0x01,0x00,0x00,0x00),);if(module instanceof WebAssembly.Module){return new WebAssembly.Instance(module)instanceof WebAssembly.Instance}}}catch(e){console.error(e)}return false})();function clearCookiesForDomains(domain){const parts=['www',...domain.split('.')];for(let i=0;i{const s=res.status;if(s>=400&&s<500){clearCookiesForDomains(location.hostname);return insertError(__("Server rejected your submission."))}else if(s>=500){return insertError(__("Server encountered an error."))}window.localStorage.setItem("_basedflare-redirect",Math.random());finishRedirect()}).catch(()=>{clearCookiesForDomains(location.hostname);insertError(__("Failed to send request to server."))})}const powFinished=new Promise((resolve)=>{let start=Date.now();const workers=[];let finished=false;const stopPow=()=>{finished=true;const hasCaptcha=document.getElementById("captcha");if(hasCaptcha){}else{makeLoaderGreen()}workers.forEach((w)=>w.terminate())};const submitPow=(answer)=>{window.localStorage.setItem("_basedflare-pow-response",answer);stopPow();const dummyTime=3500-(Date.now()-start);window.setTimeout(()=>{resolve({answer})},dummyTime)};window.addEventListener("DOMContentLoaded",async()=>{TRANSLATIONS=JSON.parse(document.head.dataset.langjson);const{time,kb,pow,diff,mode}=document.querySelector("[data-pow]").dataset;window.addEventListener("storage",(event)=>{if(event.key==="_basedflare-pow-response"&&!finished){console.log("Got answer",event.newValue,"from storage event");stopPow();resolve({answer:event.newValue,localStorage:true})}else if(event.key==="_basedflare-redirect"){console.log("Redirecting, solved in another tab");finishRedirect()}});if(mode==="argon2"&&!wasmSupported){return insertError(__("Browser does not support WebAssembly."))}const powOpts={time:time,mem:kb,hashLen:32,parallelism:1,type:argon2?argon2.ArgonType.Argon2id:null,mode:mode};console.log("Got pow",pow,"with difficulty",diff);const eHashes=Math.pow(16,Math.floor(diff/8))*(((diff%8)*2)||1);const diffString="0".repeat(Math.floor(diff/8));const[userkey,challenge]=pow.split("#");if(window.Worker){let cpuThreads;try{cpuThreads=window.navigator.hardwareConcurrency||2}catch(e){console.warn('navigator.hardwareConcurrency unavailable');cpuThreads=2}const isTor=location.hostname.endsWith(".onion");const workerThreads=(isTor||cpuThreads===2)?cpuThreads:Math.max(Math.ceil(cpuThreads/2),cpuThreads-1);const messageHandler=(e)=>{if(e.data.length===1){const totalHashes=e.data[0];const elapsedSec=Math.floor((Date.now()-start)/1000);const hps=Math.floor(totalHashes/elapsedSec);const requiredSec=Math.floor(eHashes/hps)*1.5;const remainingSec=Math.max(0,Math.floor(requiredSec-elapsedSec),);return console.log(`${ hps }H/s, ≈${ remainingSec }s remaining`);}if(finished){return}const[workerId,answer]=e.data;console.log("Worker",workerId,"returned answer",answer,"in",Date.now()-start+"ms",);submitPow(`${ pow }#${ answer }`)};for(let i=0;isetTimeout(res,10));workers[i].postMessage([userkey,challenge,diff,diffString,powOpts,i,workerThreads])}}else{return insertError(__("Browser does not support Web Workers."))}})}).then((powResponse)=>{const hasCaptchaForm=document.getElementById("captcha");if(!hasCaptchaForm&&!powResponse.localStorage){postResponse(powResponse.answer)}return powResponse.answer}).catch((e)=>{console.error(e)});function onCaptchaSubmit(captchaResponse){const captchaElem=document.querySelector("[data-sitekey]");captchaElem.insertAdjacentHTML("afterend",`
`,);captchaElem.remove();powFinished.then((powResponse)=>{updateElem(".powstatus",__("Submitting..."),"#31cc31");makeLoaderGreen();postResponse(powResponse,captchaResponse)})} +let TRANSLATIONS;function __(key){let replacement=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;const translation=TRANSLATIONS[key]||key;return replacement!==null?translation.replace('%s',replacement):translation}function updateElem(selector,text,color){const updateElem=document.querySelector(selector);if(updateElem){updateElem.innerText=text;if(color){updateElem.style.color=color}}}function insertError(str){const loader=document.querySelector("#loader");const captcha=document.querySelector("#captcha");(captcha||loader).insertAdjacentHTML("afterend",`

Error: ${ str }

`,);loader&&loader.remove();captcha&&captcha.remove();updateElem(".powstatus","")}function finishRedirect(){window.location=location.search.slice(1)+location.hash||"/"}function makeLoaderGreen(){const dots=document.querySelectorAll(".b");if(dots&&dots.length>0){dots.forEach((dot)=>dot.classList.add("green"))}}const wasmSupported=(()=>{try{if(typeof WebAssembly==="object"&&typeof WebAssembly.instantiate==="function"){const module=new WebAssembly.Module(Uint8Array.of(0x0,0x61,0x73,0x6d,0x01,0x00,0x00,0x00),);if(module instanceof WebAssembly.Module){return new WebAssembly.Instance(module)instanceof WebAssembly.Instance}}}catch(e){console.error(e)}return false})();function clearCookiesForDomains(domain){const parts=['www',...domain.split('.')];for(let i=0;i{const s=res.status;if(s>=400&&s<500){clearCookiesForDomains(location.hostname);return insertError(__("Server rejected your submission."))}else if(s>=500){return insertError(__("Server encountered an error."))}window.localStorage.setItem("_basedflare-redirect",Math.random());finishRedirect()}).catch(()=>{clearCookiesForDomains(location.hostname);insertError(__("Failed to send request to server."))})}const powFinished=new Promise((resolve)=>{let start=Date.now();const workers=[];let finished=false;const stopPow=()=>{finished=true;const hasCaptcha=document.getElementById("captcha");if(hasCaptcha){}else{makeLoaderGreen()}workers.forEach((w)=>w.terminate())};const submitPow=(answer)=>{window.localStorage.setItem("_basedflare-pow-response",answer);stopPow();const dummyTime=3500-(Date.now()-start);window.setTimeout(()=>{(window?._bft?.()||Promise.resolve()).then(()=>{resolve({answer})})},dummyTime)};window.addEventListener("DOMContentLoaded",async()=>{TRANSLATIONS=JSON.parse(document.head.dataset.langjson);const{time,kb,pow,diff,mode}=document.querySelector("[data-pow]").dataset;window.addEventListener("storage",(event)=>{if(event.key==="_basedflare-pow-response"&&!finished){console.log("Got answer",event.newValue,"from storage event");stopPow();(window?._bft?.()||Promise.resolve()).then(()=>{resolve({answer:event.newValue,localStorage:true})})}else if(event.key==="_basedflare-redirect"){console.log("Redirecting, solved in another tab");finishRedirect()}});if(mode==="argon2"&&!wasmSupported){return insertError(__("Browser does not support WebAssembly."))}const powOpts={time:time,mem:kb,hashLen:32,parallelism:1,type:argon2?argon2.ArgonType.Argon2id:null,mode:mode};console.log("Got pow",pow,"with difficulty",diff);const eHashes=Math.pow(16,Math.floor(diff/8))*(((diff%8)*2)||1);const diffString="0".repeat(Math.floor(diff/8));const[userkey,challenge]=pow.split("#");if(window.Worker){let cpuThreads;try{cpuThreads=window.navigator.hardwareConcurrency||2}catch(e){console.warn('navigator.hardwareConcurrency unavailable');cpuThreads=2}const isTor=location.hostname.endsWith(".onion");const workerThreads=(isTor||cpuThreads===2)?cpuThreads:Math.max(Math.ceil(cpuThreads/2),cpuThreads-1);const messageHandler=(e)=>{if(e.data.length===1){const totalHashes=e.data[0];const elapsedSec=Math.floor((Date.now()-start)/1000);const hps=Math.floor(totalHashes/elapsedSec);const requiredSec=Math.floor(eHashes/hps)*1.5;const remainingSec=Math.max(0,Math.floor(requiredSec-elapsedSec),);return console.log(`${ hps }H/s, ≈${ remainingSec }s remaining`);}if(finished){return}const[workerId,answer]=e.data;console.log("Worker",workerId,"returned answer",answer,"in",Date.now()-start+"ms",);submitPow(`${ pow }#${ answer }`)};for(let i=0;isetTimeout(res,10));workers[i].postMessage([userkey,challenge,diff,diffString,powOpts,i,workerThreads])}}else{return insertError(__("Browser does not support Web Workers."))}})}).then((powResponse)=>{const hasCaptchaForm=document.getElementById("captcha");if(!hasCaptchaForm&&!powResponse.localStorage){postResponse(powResponse.answer)}return powResponse.answer}).catch((e)=>{console.error(e)});function onCaptchaSubmit(captchaResponse){const captchaElem=document.querySelector("[data-sitekey]");captchaElem.insertAdjacentHTML("afterend",`
`,);captchaElem.remove();powFinished.then((powResponse)=>{updateElem(".powstatus",__("Submitting..."),"#31cc31");makeLoaderGreen();postResponse(powResponse,captchaResponse)})} diff --git a/src/lua/scripts/bot-check.lua b/src/lua/scripts/bot-check.lua index 941539a..5cbff84 100644 --- a/src/lua/scripts/bot-check.lua +++ b/src/lua/scripts/bot-check.lua @@ -16,7 +16,7 @@ local templates = require("templates") local locales_path = "/etc/haproxy/locales/" local locales_table = {} local locales_strings = {} -for file_name in io.popen('ls "'..locales_path..'"*.json'):lines() do +for file_name in io.popen('ls "' .. locales_path .. '"*.json'):lines() do local file_name_with_path = utils.split(file_name, "/") local file_name_without_ext = utils.split(file_name_with_path[#file_name_with_path], ".")[1] local file = io.open(file_name, "r") @@ -73,7 +73,7 @@ end -- kill a tor circuit function _M.kill_tor_circuit(txn) local ip = txn.sf:src() - if ip:sub(1,19) ~= "fc00:dead:beef:4dad" then + if ip:sub(1, 19) ~= "fc00:dead:beef:4dad" then return -- not a tor circuit id/ip. we shouldn't get here, but just in case. end -- split the IP, take the last 2 sections @@ -83,8 +83,8 @@ function _M.kill_tor_circuit(txn) aa_bb = string.rep("0", 4 - #aa_bb) .. aa_bb cc_dd = string.rep("0", 4 - #cc_dd) .. cc_dd -- convert the last 2 sections to a number from hex, which makes the circuit ID - local circuit_identifier = tonumber(aa_bb..cc_dd, 16) - print('Closing Tor circuit ID: '..circuit_identifier..', "IP": '..ip) + local circuit_identifier = tonumber(aa_bb .. cc_dd, 16) + print('Closing Tor circuit ID: ' .. circuit_identifier .. ', "IP": ' .. ip) utils.send_tor_control_port(circuit_identifier) end @@ -114,7 +114,6 @@ function _M.get_ddos_config(context, is_applet) end function _M.view(applet) - -- host header local host = applet.headers['host'][0] @@ -139,7 +138,6 @@ function _M.view(applet) -- if request is GET, serve the challenge page if applet.method == "GET" then - -- get the user_key#challenge#sig local user_key = sha.bin_to_hex(randbytes(16)) local challenge_hash, expiry = utils.generate_challenge(applet, pow_cookie_secret, user_key, ddos_config, true) @@ -155,7 +153,7 @@ function _M.view(applet) local captcha_enabled = false local path = url.getpath(applet.qs); --because on /.basedflare/bot-check?/whatever, .qs (query string) holds the old path - local ddos_map_lookup = ddos_map:lookup(host..path) or ddos_map:lookup(host) + local ddos_map_lookup = ddos_map:lookup(host .. path) or ddos_map:lookup(host) if ddos_map_lookup ~= nil then local ddos_map_json = json.decode(ddos_map_lookup) if ddos_map_json.m == 2 then @@ -166,8 +164,11 @@ function _M.view(applet) -- return simple json if they send accept: application/json header local accept_header = applet.headers['accept'] if accept_header ~= nil and accept_header[0] == 'application/json' then - local local_pow_combined = string.format('%s#%d#%s#%s', ddos_config["pt"], math.ceil(ddos_config["pd"]/8), argon_time, argon_kb) - response_body = "{\"ch\":\""..combined_challenge.."\",\"ca\":"..(captcha_enabled and "true" or "false")..",\"pow\":\""..local_pow_combined.."\"}" + local local_pow_combined = string.format('%s#%d#%s#%s', ddos_config["pt"], math.ceil(ddos_config["pd"] / 8), + argon_time, argon_kb) + response_body = "{\"ch\":\"" .. + combined_challenge .. + "\",\"ca\":" .. (captcha_enabled and "true" or "false") .. ",\"pow\":\"" .. local_pow_combined .. "\"}" applet:set_status(403) applet:add_header("content-type", "application/json; charset=utf-8") applet:add_header("content-length", string.len(response_body)) @@ -192,7 +193,8 @@ function _M.view(applet) local noscript_prompt if ddos_config["pt"] == "argon2" then noscript_extra = templates.noscript_extra_argon2 - noscript_prompt = ll["Run this in a linux terminal (requires argon2 package installed):"] + noscript_prompt = ll + ["Run this in a linux terminal (requires argon2 package installed):"] else noscript_extra = templates.noscript_extra_sha256 noscript_prompt = ll["Run this in a linux terminal (requires perl):"] @@ -205,7 +207,7 @@ function _M.view(applet) challenge_hash, expiry, signature, - math.ceil(ddos_config["pd"]/8), + math.ceil(ddos_config["pd"] / 8), argon_time, argon_kb, ll["Paste the script output into the box and submit:"] @@ -213,6 +215,12 @@ function _M.view(applet) end end + -- local extra_challenge = [[ + -- + -- + -- ]] + local extra_challenge = "" + -- sub in the body sections response_body = string.format( templates.body, @@ -220,6 +228,7 @@ function _M.view(applet) ls, ll["Hold on..."], css_val, + extra_challenge, combined_challenge, ddos_config["pd"], argon_time, @@ -235,9 +244,8 @@ function _M.view(applet) ) response_status_code = 403 - -- if request is POST, check the answer to the pow/cookie + -- if request is POST, check the answer to the pow/cookie elseif applet.method == "POST" then - -- if they fail, set a var for use in ACLs later local valid_submission = false local number_expiry = nil @@ -255,7 +263,6 @@ function _M.view(applet) local user_pow_response = parsed_body["pow_response"] local matched_expiry = 0 -- ensure captcha cookie expiry matches POW cookie if user_pow_response then - -- split the response up (makes the nojs submission easier because it can be a single field) local split_response = utils.split(user_pow_response, "#") @@ -269,21 +276,21 @@ function _M.view(applet) -- expiry check number_expiry = tonumber(given_expiry, 10) if number_expiry ~= nil and number_expiry > core.now()['sec'] then - -- regenerate the challenge and compare it - local generated_challenge_hash = utils.generate_challenge(applet, pow_cookie_secret, given_user_key, ddos_config, true) + local generated_challenge_hash = utils.generate_challenge(applet, pow_cookie_secret, given_user_key, + ddos_config, true) if given_challenge_hash == generated_challenge_hash then - -- regenerate the signature and compare it - local generated_signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, given_user_key .. given_challenge_hash .. given_expiry) + local generated_signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, + given_user_key .. given_challenge_hash .. given_expiry) if given_signature == generated_signature then - -- do the work with their given answer local hex_hash_output = "" if ddos_config["pt"] == "argon2" then - local encoded_argon_hash = argon2.hash_encoded(given_challenge_hash .. given_answer, given_user_key) + local encoded_argon_hash = argon2.hash_encoded(given_challenge_hash .. given_answer, + given_user_key) local trimmed_argon_hash = utils.split(encoded_argon_hash, '$')[6]:sub(0, 43) -- https://github.com/thibaultcha/lua-argon2/issues/37 hex_hash_output = sha.bin_to_hex(sha.base64_to_bin(trimmed_argon_hash)); else @@ -291,15 +298,18 @@ function _M.view(applet) end if utils.checkdiff(hex_hash_output, ddos_config["pd"]) then - -- the answer was good, give them a cookie - local signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, given_user_key .. given_challenge_hash .. given_expiry .. given_answer) - local combined_cookie = given_user_key .. "#" .. given_challenge_hash .. "#" .. given_expiry .. "#" .. given_answer .. "#" .. signature + local signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, + given_user_key .. given_challenge_hash .. given_expiry .. given_answer) + local combined_cookie = given_user_key .. + "#" .. + given_challenge_hash .. + "#" .. given_expiry .. "#" .. given_answer .. "#" .. signature local expiry_date_p = _M.secondsToDate(number_expiry) applet:add_header( "set-cookie", string.format( - --"_basedflare_pow=%s; Expires=%s; Path=/; Domain=.%s; SameSite=Lax; HttpOnly;%s", + --"_basedflare_pow=%s; Expires=%s; Path=/; Domain=.%s; SameSite=Lax; HttpOnly;%s", "_basedflare_pow=%s; Expires=%s; Path=/; Domain=%s; SameSite=Lax; %s", combined_cookie, expiry_date_p, @@ -309,7 +319,6 @@ function _M.view(applet) ) valid_submission = true matched_expiry = number_expiry - end end end @@ -321,7 +330,6 @@ function _M.view(applet) local user_captcha_response = parsed_body["h-captcha-response"] or parsed_body["g-recaptcha-response"] if valid_submission and user_captcha_response then -- only check captcha if POW is already correct - -- format the url for verifying the captcha response local captcha_url = string.format( "https://%s%s", @@ -331,19 +339,19 @@ function _M.view(applet) -- construct the captcha body to send to the captcha url local captcha_body = url.buildQuery({ - secret=captcha_secret, - response=user_captcha_response + secret = captcha_secret, + response = user_captcha_response }) -- instantiate an http client and make the request local httpclient = core.httpclient() - local res = httpclient:post{ - url=captcha_url, - body=captcha_body, - headers={ - [ "host" ] = { captcha_provider_domain }, - [ "content-type" ] = { "application/x-www-form-urlencoded" }, - [ "user-agent" ] = { "haproxy-protection (haproxy-protection/0.1; +https://gitgud.io/fatchan/haproxy-protection)" } + local res = httpclient:post { + url = captcha_url, + body = captcha_body, + headers = { + ["host"] = { captcha_provider_domain }, + ["content-type"] = { "application/x-www-form-urlencoded" }, + ["user-agent"] = { "haproxy-protection (haproxy-protection/0.1; +https://gitgud.io/fatchan/haproxy-protection)" } } } @@ -372,7 +380,6 @@ function _M.view(applet) ) valid_submission = valid_submission and true end - end if not valid_submission then @@ -384,7 +391,7 @@ function _M.view(applet) response_status_code = 302 applet:add_header("location", applet.qs) - -- else if its another http method, just 403 them + -- else if its another http method, just 403 them else response_status_code = 403 end @@ -395,7 +402,6 @@ function _M.view(applet) applet:add_header("content-length", string.len(response_body)) applet:start_response() applet:send(response_body) - end -- set a variable if ip or subnet in blocked/whitelist map and list of usernames matches the one for the current domain @@ -468,7 +474,7 @@ end function _M.decide_checks_necessary(txn) local host = txn.sf:hdr("Host") local path = txn.sf:path(); - local ddos_map_lookup = ddos_map:lookup(host..path) or ddos_map:lookup(host) + local ddos_map_lookup = ddos_map:lookup(host .. path) or ddos_map:lookup(host) if ddos_map_lookup ~= nil then local ddos_map_json = json.decode(ddos_map_lookup) if ddos_map_json.m == 0 @@ -510,7 +516,8 @@ function _M.check_captcha_status(txn) return end -- regenerate the signature and compare it - local generated_signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, given_user_key .. given_user_hash .. given_expiry) + local generated_signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, + given_user_key .. given_user_hash .. given_expiry) if given_signature == generated_signature then return txn:set_var("txn.captcha_passed", true) end @@ -543,7 +550,8 @@ function _M.check_pow_status(txn) return end -- regenerate the signature and compare it - local generated_signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, given_user_key .. given_challenge_hash .. given_expiry .. given_answer) + local generated_signature = sha.hmac(sha.sha3_256, hmac_cookie_secret, + given_user_key .. given_challenge_hash .. given_expiry .. given_answer) if given_signature == generated_signature then return txn:set_var("txn.pow_passed", true) end diff --git a/src/lua/scripts/register-bot-check.lua b/src/lua/scripts/register-bot-check.lua index 122ac80..cc3843d 100644 --- a/src/lua/scripts/register-bot-check.lua +++ b/src/lua/scripts/register-bot-check.lua @@ -2,7 +2,7 @@ package.path = package.path .. "./?.lua;/etc/haproxy/scripts/?.lua;/etc/haproxy/ local bot_check = require("bot-check") local utils = require("utils") -local server_cn_split_regex = "([^;]+);(%u%u)$" +local server_cn_split_regex = "([^;]+)|(%u%u)$" local backends_map = Map.new('/etc/haproxy/map/backends.map', Map._str) function get_server_names(txn) diff --git a/src/lua/scripts/register-servers.lua b/src/lua/scripts/register-servers.lua index 47da1ea..b1ecc1e 100644 --- a/src/lua/scripts/register-servers.lua +++ b/src/lua/scripts/register-servers.lua @@ -3,7 +3,7 @@ package.path = package.path .. "./?.lua;/etc/haproxy/scripts/?.lua;/etc/haproxy/ local pow_difficulty = tonumber(os.getenv("POW_DIFFICULTY") or 18) local backends_map = Map.new('/etc/haproxy/map/backends.map', Map._str) local utils = require("utils") -local server_cn_split_regex = "([^;]+);(%u%u)$" +local server_cn_split_regex = "([^;]+)|(%u%u)$" local map_space_split_rexex = "([^%s]+)%s+([^%s]+)" -- setup initial server backends based on hosts.map @@ -27,7 +27,7 @@ function setup_servers() while line do local domain, backend_data = line:match(map_space_split_rexex) local backend_host, continent_code = backend_data:match(server_cn_split_regex) - local new_map_value = server_prefix .. counter .. ';' .. continent_code + local new_map_value = server_prefix .. counter .. '|' .. continent_code local existing_map_value = backends_map:lookup(domain) if existing_map_value ~= nil then local current_backends = utils.split(existing_map_value, ",") diff --git a/src/lua/scripts/templates.lua b/src/lua/scripts/templates.lua index 4fb8530..9e2c8d5 100644 --- a/src/lua/scripts/templates.lua +++ b/src/lua/scripts/templates.lua @@ -16,7 +16,7 @@ if os.getenv("USE_INTER_FONT") then end -- main page template -local body_css = [[:root{--text-color:#c5c8c6;--bg-color:#1d1f21}@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#fff}}.g-recaptcha,.h-captcha{min-height:85px;display:block}.red{display:inline-block;color:#ff0000d0;background:#ff000020;border:1px solid #ff000050;font-weight:bold;padding:12px;border-radius:6px}.left{text-align:left}.powstatus{color:#6b93f7;font-size:small}a,a:visited{color:var(--text-color)}body,html{height:100%%;text-align:center}body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);max-width:60em;margin:0 auto;padding:0 20px}details{max-width:1200px;text-align:left;border-left:2px solid #ff0000d0;padding:10px}code{background-color:#dfdfdf30;border-radius:4px;padding:0 3px;color:#ff6590}h3,img{margin:0 0 16px}li{margin-bottom:1em}footer{font-size:x-small;margin-top:auto;padding:10px;text-align:center;border-top:1px solid #80808040;padding:10px;max-width:300px;margin:auto auto 0}img{display:inline}input,textarea{background:var(--bg-color);color:var(--text-color);border:1px solid var(--text-color);width:100%%;box-sizing:border-box;resize:none;padding:5px;margin:5px;font-family:inherit;border-radius:6px}input[type="submit"]{padding:8px}.pt{padding-top:25vh;word-wrap:break-word;display:flex;flex-direction:column}.pt img{margin:0 auto 10px}.b{display:inline-block;border-radius:50%%;margin:20px 12px;height:16px;width:16px;transform:scale(1);box-shadow:0 0 0 0 #6b93f720;background:#6b93f7;--shadow1:#6b93f790;--shadow2:#6b93f700;--shadow3:#6b93f700}.b.green{background:#31cc31;box-shadow:0 0 0 0 #31cc3120;--shadow1:#31cc3190;--shadow2:#31cc3100;--shadow3:#31cc3100}.b:nth-of-type(1){animation:p 3s infinite}.b:nth-of-type(2){animation:p 3s 0.5s infinite}.b:nth-of-type(3){animation:p 3s 1s infinite}details:not([open]),summary{cursor:pointer}@keyframes p{0%%{transform:scale(.95);box-shadow:0 0 0 0 var(--shadow1)}70%%{transform:scale(1);box-shadow:0 0 0 8px var(--shadow2)}100%%{transform:scale(.95);box-shadow:0 0 0 0 var(--shadow3)}}details summary::-webkit-details-marker,details summary::marker{display:none}details summary{list-style-type:none}details[open] > summary:before{transform:rotate(90deg)}summary{padding-left:20px}summary:before{content:'';border-width:8px;border-style:solid;border-color:transparent transparent transparent var(--text-color);position:absolute;transform:rotate(0);transform-origin:4px 50%%;transition:0.25s transform ease;margin:3px 0 0 -15px}#captcha{margin-top:1em}]] +local body_css = [[:root{--text-color:#c5c8c6;--bg-color:#1d1f21}@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#fff}}.g-recaptcha,.h-captcha{min-height:85px;display:block}.red{display:inline-block;color:#ff0000d0;background:#ff000020;border:1px solid #ff000050;font-weight:bold;padding:12px;border-radius:6px}.left{text-align:left}.powstatus{color:#6b93f7;font-size:small}a,a:visited{color:var(--text-color)}body,html{height:100%%;text-align:center}body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);max-width:60em;margin:0 auto;padding:0 20px}details{max-width:1200px;text-align:left;border-left:2px solid #ff0000d0;padding:10px}code{background-color:#dfdfdf30;border-radius:4px;padding:0 3px;color:#ff6590}h3,img{margin:0 0 16px}li{margin-bottom:1em}footer{font-size:x-small;margin-top:auto;padding:10px;text-align:center;border-top:1px solid #80808040;padding:10px;max-width:300px;margin:auto auto 0}img{display:inline}input,textarea{background:var(--bg-color);color:var(--text-color);border:1px solid var(--text-color);width:100%%;box-sizing:border-box;resize:none;padding:5px;margin:5px;font-family:inherit;border-radius:6px}input[type="submit"]{padding:8px}.pt{padding-top:25vh;word-wrap:break-word;display:flex;flex-direction:column}.pt img{margin:0 auto 10px}.b{display:inline-block;border-radius:50%%;margin:20px 12px;height:16px;width:16px;transform:scale(1);box-shadow:0 0 0 0 #6b93f720;background:#6b93f7;--shadow1:#6b93f790;--shadow2:#6b93f700;--shadow3:#6b93f700}.b.green{background:#31cc31;box-shadow:0 0 0 0 #31cc3120;--shadow1:#31cc3190;--shadow2:#31cc3100;--shadow3:#31cc3100}.b:nth-of-type(1){animation:p 3s infinite}.b:nth-of-type(2){animation:p 3s 0.5s infinite}.b:nth-of-type(3){animation:p 3s 1s infinite}details:not([open]),summary{cursor:pointer}@keyframes p{0%%{transform:scale(.95);box-shadow:0 0 0 0 var(--shadow1)}70%%{transform:scale(1);box-shadow:0 0 0 8px var(--shadow2)}100%%{transform:scale(.95);box-shadow:0 0 0 0 var(--shadow3)}}details summary::-webkit-details-marker,details summary::marker{display:none}details summary{list-style-type:none}details[open] > summary:before{transform:rotate(90deg)}summary{padding-left:20px}summary:before{content:'';border-width:8px;border-style:solid;border-color:transparent transparent transparent var(--text-color);position:absolute;transform:rotate(0);transform-origin:4px 50%%;transition:0.25s transform ease;margin:3px 0 0 -15px}#captcha{margin-top:1em}canvas{display:flex;margin:0 auto;cursor:pointer;background:lightgray;border:2px solid black;}]] _M.body = string.format([[ @@ -32,6 +32,7 @@ _M.body = string.format([[ + %%s @@ -48,6 +49,7 @@ _M.body = string.format([[ %%s
+