get rid of bot protection as well
All checks were successful
Build and publish the docker image / build (push) Successful in 10s

Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
ngn 2025-01-19 07:31:43 +03:00
parent 9868c6c7a5
commit 4be33b2da1
Signed by: ngn
GPG Key ID: A3654DF5AD9F641D
9 changed files with 553 additions and 1342 deletions

View File

@ -5,9 +5,6 @@ header("Access-Control-Allow-Origin: *");
include "data/config.php";
$real_requests = apcu_fetch("real_requests");
$bot_requests = apcu_fetch("captcha_gen");
echo json_encode(
[
"status" => "ok",
@ -16,8 +13,8 @@ echo json_encode(
"name" => config::SERVER_NAME,
"description" => config::SERVER_LONG_DESCRIPTION,
"bot_protection" => config::BOT_PROTECTION,
"real_requests" => $real_requests === false ? 0 : $real_requests,
"bot_requests" => $bot_requests === false ? 0 : $bot_requests,
"real_requests" => 0,
"bot_requests" => 0,
"api_enabled" => false,
"alt_addresses" => config::ALT_ADDRESSES,
"version" => config::VERSION

View File

@ -12,12 +12,6 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
include "lib/bot_protection.php";
new bot_protection($frontend, $get, $filters, "images", true);
$payload = [
"timetaken" => microtime(true),
"images" => "",

View File

@ -1,281 +0,0 @@
<?php
class bot_protection{
public function __construct($frontend, $get, $filters, $page, $output){
// check if we want captcha
if(config::BOT_PROTECTION !== 1){
apcu_inc("real_requests");
if($output === true){
$frontend->loadheader(
$get,
$filters,
$page
);
}
return;
}
/*
Validate cookie, if it exists
*/
if(isset($_COOKIE["pass"])){
if(
// check if key is not malformed
preg_match(
'/^k[0-9]+\.[A-Za-z0-9_]{20}$/',
$_COOKIE["pass"]
) &&
// does key exist
apcu_exists($_COOKIE["pass"])
){
// exists, increment counter
$inc = apcu_inc($_COOKIE["pass"]);
// we start counting from 1
// when it has been incremented to 102, it has reached
// 100 reqs
if($inc >= config::MAX_SEARCHES + 2){
// reached limit, delete and give captcha
apcu_delete($_COOKIE["pass"]);
}else{
// the cookie is OK! dont die() and give results
apcu_inc("real_requests");
if($output === true){
$frontend->loadheader(
$get,
$filters,
$page
);
}
return;
}
}
}
if($output === false){
http_response_code(401); // forbidden
echo json_encode([
"status" => "The \"pass\" token in your cookies is missing or has expired!!"
]);
die();
}
/*
Validate form data
*/
$lines =
explode(
"\r\n",
file_get_contents("php://input")
);
$invalid = false;
$answers = [];
$key = false;
$error = "";
foreach($lines as $line){
$line = explode("=", $line, 2);
if(count($line) !== 2){
$invalid = true;
break;
}
preg_match(
'/^c\[([0-9]+)\]$/',
$line[0],
$regex
);
if(
$line[1] != "on" ||
!isset($regex[0][1])
){
// check if its the v key
if(
$line[0] == "v" &&
preg_match(
'/^c[0-9]+\.[A-Za-z0-9_]{20}$/',
$line[1]
)
){
$key = apcu_fetch($line[1]);
apcu_delete($line[1]);
}
break;
}
$regex = (int)$regex[1];
if(
$regex >= 16 ||
$regex <= -1
){
$invalid = true;
break;
}
$answers[] = $regex;
}
if(
!$invalid &&
$key !== false // has captcha been gen'd?
){
$check = count($key);
// validate answer
for($i=0; $i<count($answers); $i++){
if(in_array($answers[$i], $key)){
$check--;
}else{
$check = -1;
break;
}
}
if($check === 0){
// we passed the captcha
// set cookie
$inc = apcu_inc("cookie");
$key = "k" . $inc . "." . $this->randomchars();
apcu_inc($key, 1, $stupid, 86400);
apcu_inc("real_requests");
setcookie(
"pass",
$key,
[
"expires" => time() + 86400, // expires in 24 hours
"samesite" => "Lax",
"path" => "/"
]
);
$frontend->loadheader(
$get,
$filters,
$page
);
return;
}else{
$error = "<div class=\"quote\">You were <a href=\"https://www.youtube.com/watch?v=e1d7fkQx2rk\" target=\"_BLANK\" rel=\"noreferrer nofollow\">kicked out of Mensa.</a> Please try again.</div>";
}
}
$key = "c" . apcu_inc("captcha_gen", 1) . "." . $this->randomchars();
$payload = [
"timetaken" => microtime(true),
"class" => "",
"right-left" => "",
"right-right" => "",
"left" =>
'<div class="infobox">' .
'<h1>IQ test</h1>' .
'IQ test has been enabled due to bot abuse on the network.<br>' .
'Solving this IQ test will let you make 100 searches today. I will add an invite system to bypass this soon...' .
$error .
'<form method="POST" enctype="text/plain" autocomplete="off">' .
'<div class="captcha-wrapper">' .
'<div class="captcha">' .
'<img src="captcha?v=' . $key . '" alt="Captcha image">' .
'<div class="captcha-controls">' .
'<input type="checkbox" name="c[0]" id="c0">' .
'<label for="c0"></label>' .
'<input type="checkbox" name="c[1]" id="c1">' .
'<label for="c1"></label>' .
'<input type="checkbox" name="c[2]" id="c2">' .
'<label for="c2"></label>' .
'<input type="checkbox" name="c[3]" id="c3">' .
'<label for="c3"></label>' .
'<input type="checkbox" name="c[4]" id="c4">' .
'<label for="c4"></label>' .
'<input type="checkbox" name="c[5]" id="c5">' .
'<label for="c5"></label>' .
'<input type="checkbox" name="c[6]" id="c6">' .
'<label for="c6"></label>' .
'<input type="checkbox" name="c[7]" id="c7">' .
'<label for="c7"></label>' .
'<input type="checkbox" name="c[8]" id="c8">' .
'<label for="c8"></label>' .
'<input type="checkbox" name="c[9]" id="c9">' .
'<label for="c9"></label>' .
'<input type="checkbox" name="c[10]" id="c10">' .
'<label for="c10"></label>' .
'<input type="checkbox" name="c[11]" id="c11">' .
'<label for="c11"></label>' .
'<input type="checkbox" name="c[12]" id="c12">' .
'<label for="c12"></label>' .
'<input type="checkbox" name="c[13]" id="c13">' .
'<label for="c13"></label>' .
'<input type="checkbox" name="c[14]" id="c14">' .
'<label for="c14"></label>' .
'<input type="checkbox" name="c[15]" id="c15">' .
'<label for="c15"></label>' .
'</div>' .
'</div>' .
'</div>' .
'<input type="hidden" name="v" value="' . $key . '">' .
'<input type="submit" value="Check IQ" class="captcha-submit">' .
'</form>' .
'</div>'
];
$frontend->loadheader(
$get,
$filters,
$page
);
echo $frontend->load("search.html", $payload);
die();
}
private function randomchars(){
$chars =
array_merge(
range("A", "Z"),
range("a", "z"),
range(0, 9)
);
$chars[] = "_";
$c = count($chars) - 1;
$key = "";
for($i=0; $i<20; $i++){
$key .= $chars[random_int(0, $c)];
}
return $key;
}
}

View File

@ -131,11 +131,9 @@ class frontend{
){
// bot detected !!
apcu_inc("captcha_gen");
$this->drawerror(
"Tshh, blocked!",
'Your browser, IP or IP range has been blocked from this 4get instance. If this is an error, please <a href="/about">contact the administrator</a>.'
'Your browser, IP or IP range has been blocked from this 4get instance.'
);
die();
}

View File

@ -12,12 +12,6 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
include "lib/bot_protection.php";
new bot_protection($frontend, $get, $filters, "music", true);
$payload = [
"timetaken" => microtime(true),
"class" => "",

View File

@ -12,12 +12,6 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
include "lib/bot_protection.php";
new bot_protection($frontend, $get, $filters, "news", true);
$payload = [
"timetaken" => microtime(true),
"class" => "",

View File

@ -1,473 +0,0 @@
function htmlspecialchars(str){
if(str === null){
return "<i>&lt;Empty&gt;</i>";
}
var map = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#039;'
}
return str.replace(/[&<>"']/g, function(m){return map[m];});
}
// initialize garbage
var list = [];
var pinged_list = [];
var reqs = 0;
var errors = 0;
var sort = 6; // highest version first
// check for instance redirect stuff
var redir = [];
var target = "/web?";
new URL(window.location.href)
.searchParams
.forEach(
function(value, key){
if(key == "target"){
target = "/" + encodeURIComponent(value) + "?";
return;
}
if(key == "npt"){ return; }
redir.push(encodeURIComponent(key) + "=" + encodeURIComponent(value))
}
);
if(redir.length !== 0){
redir = target + redir.join("&");
}else{
redir = "";
}
var quote = document.createElement("div");
quote.className = "quote";
quote.innerHTML = 'Pinged <b>0</b> servers (<b>0</b> failed requests)';
var [div_servercount, div_failedreqs] =
quote.getElementsByTagName("b");
var noscript = document.getElementsByTagName("noscript")[0];
document.body.insertBefore(quote, noscript.nextSibling);
// create table
var table = document.createElement("table");
table.innerHTML =
'<thead>' +
'<tr>' +
'<th class="extend">Server</th>' +
'<th>Address</th>' +
'<th>Bot protection</th>' +
'<th title="Amount of legit requests processed since the last APCU cache clear (usually happens at midnight)">Real reqs (?)</th>' +
'<th title="Amount of filtered requests processed since the last APCU cache clear (usually happens at midnight)">Bot reqs (?)</th>' +
'<th>API</th>' +
'<th><div class="arrow up"></div>Version</th>' +
'</tr>' +
'</thead>' +
'<tbody></tbody>';
document.body.insertBefore(table, quote.nextSibling);
// handle sorting clicks
var tbody = table.getElementsByTagName("tbody")[0];
var th = table.getElementsByTagName("th");
for(var i=0; i<th.length; i++){
th[i].addEventListener("click", function(event){
if(event.target.className.includes("arrow")){
var div = event.target.parentElement;
}else{
var div = event.target;
}
var arrow = div.getElementsByClassName("arrow");
var orientation = 0; // up
if(arrow.length === 0){
// delete arrow and add new one
arrow = document.getElementsByClassName("arrow");
arrow[0].remove();
arrow = document.createElement("div");
arrow.className = "arrow up";
div.insertBefore(arrow, event.target.firstChild);
}else{
// switch arrow position
if(arrow[0].className == "arrow down"){
arrow[0].className = "arrow up";
}else{
arrow[0].className = "arrow down";
orientation = 1;
}
}
switch(div.textContent.toLowerCase()){
case "server": sort = 0 + orientation; break;
case "address": sort = 2 + orientation; break;
case "bot protection": sort = 4 + orientation; break;
case "real reqs (?)": sort = 6 + orientation; break;
case "bot reqs (?)": sort = 8 + orientation; break;
case "api": sort = 10 + orientation; break;
case "version": sort = 12 + orientation; break;
}
render_list();
});
}
function validate_url(url, allow_http = false){
try{
url = new URL(url);
if(
url.protocol == "https:" ||
(
(
allow_http === true ||
window.location.protocol == "http:"
) &&
url.protocol == "http:"
)
){
return true;
}
}catch(error){} // do nothing
return false;
}
function number_format(int){
return new Intl.NumberFormat().format(int);
}
// parse initial server list
fetch_server(window.location.origin);
async function fetch_server(server){
if(!validate_url(server)){
console.warn("Invalid server URL: " + server);
return;
}
// make sure baseURL is origin
server = new URL(server).origin;
// prevent multiple fetches
for(var i=0; i<list.length; i++){
if(list[i] == server){
// serber was already fetched
return;
}
}
// prevent future fetches
list.push(server);
var data = null;
try{
var payload = await fetch(server + "/ami4get");
if(payload.status !== 200){
// endpoint is not available
errors++;
div_failedreqs.textContent = number_format(errors);
console.warn(server + ": Invalid HTTP code " + payload.status);
return;
}
data = await payload.json();
}catch(error){
errors++;
div_failedreqs.textContent = number_format(errors);
console.warn(server + ": Could not fetch or decode JSON");
return;
}
// sanitize data
if(
typeof data.status != "string" ||
data.status != "ok" ||
typeof data.server != "object" ||
!(
typeof data.server.name == "string" ||
(
typeof data.server.name == "object" &&
data.server.name === null
)
) ||
typeof data.service != "string" ||
data.service != "4get" ||
(
typeof data.server.description != "string" &&
data.server.description !== null
) ||
typeof data.server.bot_protection != "number" ||
typeof data.server.real_requests != "number" ||
typeof data.server.bot_requests != "number" ||
typeof data.server.api_enabled != "boolean" ||
typeof data.server.alt_addresses != "object" ||
typeof data.server.version != "number" ||
typeof data.instances != "object"
){
errors++;
div_failedreqs.textContent = number_format(errors);
console.warn(server + ": Malformed JSON");
return;
}
data.server.ip = server;
reqs++;
div_servercount.textContent = number_format(reqs);
var total = pinged_list.push(data) - 1;
pinged_list[total].index = total;
render_list();
// get more serbers
for(var i=0; i<data.instances.length; i++){
fetch_server(data.instances[i]);
}
}
function sorta(object, element, order){
return object.slice().sort(
function(a, b){
if(order){
return a.server[element] - b.server[element];
}
return b.server[element] - a.server[element];
}
);
}
function textsort(object, element, order){
var sort = object.slice().sort(
function(a, b){
return a.server[element].localeCompare(b.server[element]);
}
);
if(!order){
return sort.reverse();
}
return sort;
}
function render_list(){
var sorted_list = [];
// sort
var filter = Boolean(sort % 2);
switch(sort){
case 0:
case 1:
sorted_list = textsort(pinged_list, "name", filter === true ? false : true);
break;
case 2:
case 3:
sorted_list = textsort(pinged_list, "ip", filter === true ? false : true);
break;
case 4:
case 5:
sorted_list = sorta(pinged_list, "bot_protection", filter === true ? false : true);
break;
case 6:
case 7:
sorted_list = sorta(pinged_list, "real_requests", filter);
break;
case 8:
case 9:
sorted_list = sorta(pinged_list, "bot_requests", filter);
break;
case 10:
case 11:
sorted_list = sorta(pinged_list, "api_enabled", filter);
break;
case 12:
case 13:
sorted_list = sorta(pinged_list, "version", filter);
break;
}
// render tabloid
var html = "";
for(var k=0; k<sorted_list.length; k++){
html += '<tr onclick="show_server(' + sorted_list[k].index + ');">';
for(var i=0; i<7; i++){
html += '<td';
switch(i){
// server name
case 0: html += ' class="extend">' + htmlspecialchars(sorted_list[k].server.name); break;
case 1: html += '>' + htmlspecialchars(new URL(sorted_list[k].server.ip).host); break;
case 2: // bot protection
switch(sorted_list[k].server.bot_protection){
case 0:
html += '><span style="color:var(--green);">Disabled</span>';
break;
case 1:
html += '><span style="color:var(--yellow);">Image captcha</span>';
break;
case 2:
html += '><span style="color:var(--red);">Invite only</span>';
break;
default:
html += '>Unknown';
}
break;
case 3: // real reqs
html += '>' + number_format(sorted_list[k].server.real_requests);
break;
case 4: // bot reqs
html += '>' + number_format(sorted_list[k].server.bot_requests);
break;
case 5: // api enabled
if(sorted_list[k].server.api_enabled){
html += '><span style="color:var(--green);">Yes</span>';
}else{
html += '><span style="color:var(--red);">No</span>';
}
break;
// version
case 6: html += ">v" + sorted_list[k].server.version; break;
}
html += '</td>';
}
html += '</tr>';
}
console.log(html);
tbody.innerHTML = html;
}
var popup_bg = document.getElementById("popup-bg");
var popup_wrapper = document.getElementsByClassName("popup-wrapper")[0];
var popup = popup_wrapper.getElementsByClassName("popup")[0];
var popup_shown = false;
popup_bg.addEventListener("click", function(){
popup_wrapper.style.display = "none";
popup_bg.style.display = "none";
});
function show_server(serverid){
var html =
'<h2>' + htmlspecialchars(pinged_list[serverid].server.name) + '</h2>' +
'Description' +
'<div class="code">' + htmlspecialchars(pinged_list[serverid].server.description) + '</div>';
var url_obj = new URL(pinged_list[serverid].server.ip);
var url = htmlspecialchars(url_obj.origin);
var domain = url_obj.hostname;
html +=
'URL: <a rel="noreferer" target="_BLANK" href="' + url + redir + '">' + url + '</a> <a rel="noreferer" target="_BLANK" href="https://browserleaks.com/ip/' + encodeURIComponent(domain) + '">(IP lookup)</a>' +
'<br><br>Alt addresses:';
var len = pinged_list[serverid].server.alt_addresses.length;
if(len === 0){
html += ' <i>&lt;Empty&gt;</i>';
}else{
html += '<ul>';
for(var i=0; i<len; i++){
var url_obj = new URL(pinged_list[serverid].server.alt_addresses[i]);
var url = htmlspecialchars(url_obj.origin);
var domain = url_obj.hostname;
if(validate_url(pinged_list[serverid].server.alt_addresses[i], true)){
html += '<li><a rel="noreferer" href="' + url + redir + '" target="_BLANK">' + url + '</a> <a rel="noreferer" target="_BLANK" href="https://browserleaks.com/ip/' + encodeURIComponent(domain) + '">(IP lookup)</a></li>';
}else{
console.warn(pinged_list[serverid].server.ip + ": Invalid peer URL => " + pinged_list[serverid].server.alt_addresses[i]);
}
}
html += '</ul>';
}
popup.innerHTML = html;
popup_wrapper.style.display = "block";
popup_bg.style.display = "block";
}
function hide_server(){
popup_wrapper.style.display = "none";
popup_bg.style.display = "none";
}

View File

@ -12,12 +12,6 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
include "lib/bot_protection.php";
new bot_protection($frontend, $get, $filters, "videos", true);
$payload = [
"timetaken" => microtime(true),
"class" => "",

View File

@ -12,12 +12,6 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
include "lib/bot_protection.php";
new bot_protection($frontend, $get, $filters, "web", true);
$payload = [
"timetaken" => microtime(true),
"class" => "",