From 57b62994403c53615c6ab9951e7da794b3c38802 Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 6 Jun 2022 17:57:49 +0000 Subject: [PATCH] push recent updates Signed-off-by: r4sas --- checker.php | 6 +++--- config.php.dist | 5 +++-- fetch.php | 6 +++++- lib/bob.php | 9 +++++++-- lib/checker.php | 6 +++++- lib/utils.php | 9 +++++++-- public/index.php | 4 ++++ templates/add.twig | 2 ++ templates/alive.twig | 2 +- templates/all.twig | 2 +- templates/hidden.twig | 2 +- templates/latest.twig | 2 +- templates/search.twig | 2 +- views/add.php | 42 ++++++++++++++++++++++++++++++++++++------ views/api.php | 30 ++++++++++++++++++++++++++++++ 15 files changed, 107 insertions(+), 22 deletions(-) create mode 100644 views/api.php diff --git a/checker.php b/checker.php index 64cf572..483cc72 100644 --- a/checker.php +++ b/checker.php @@ -14,7 +14,7 @@ $pdo = (new DB($options))->pdo; $results = []; -/* Fetch hosts for check from database */ +echo "[DB] Fetching hosts to check from database" . PHP_EOL; if ((($options['fullhour'] >= 0) && ($options['fullhour'] <= 23)) && date('H') == $options['fullhour']) { // check all hosts at full check hour $STH = $pdo->query("SELECT `host`, `base32` FROM `hosts`"); } else { @@ -22,7 +22,7 @@ if ((($options['fullhour'] >= 0) && ($options['fullhour'] <= 23)) && date('H') = } $hosts = $STH->fetchAll(PDO::FETCH_KEY_PAIR); -/* Start temporary BOB tunnel for checking */ +echo "[BOB] Starting session for checking" . PHP_EOL; $bob = new BOB($options); $bob->setnick(); $bob->options(); @@ -31,7 +31,7 @@ $bob->intun(); $bob->start(); /* Sleep 10 seconds awaitng tunnels get built */ -echo "BOB session started, awaiting 10 seconds for tunnels" . PHP_EOL; +echo "[BOB] Session started, awaiting 10 seconds for tunnels" . PHP_EOL; sleep(10); /* Start async checker tasks */ diff --git a/config.php.dist b/config.php.dist index 57e3977..81d74cd 100644 --- a/config.php.dist +++ b/config.php.dist @@ -14,9 +14,10 @@ $options = [ /* I2P settings */ 'bob_host' => '127.0.0.1', 'bob_port' => '2827', - 'bob_options' => 'inbound.quantity=3 outbound.quantity=3 inbound.length=1 outbound.length=1 i2cp.leaseSetType=3', + 'bob_options' => 'inbound.quantity=3 outbound.quantity=3 inbound.length=1 outbound.length=1 i2cp.leaseSetType=3 i2cp.dontPublishLeaseSet=true', 'bob_nick' => 'hostchecker', - 'check_tries' => 1, + 'check_tries' => 2, // lookup tries + 'retry_delay' => 3, // delay in seconds between tries 'http_proxy' => 'tcp://127.0.0.1:4444', // this is HTTP proxy, which must be specified as tcp protocol because we using stream context /* Service settings */ diff --git a/fetch.php b/fetch.php index 1d856f5..a3a5059 100644 --- a/fetch.php +++ b/fetch.php @@ -58,7 +58,11 @@ foreach ($lists as $list) { $domain = ""; $record = $util->parseHostRecord($buffer); - if (!$util->isValidDomain($record['host'], $error)) { + if (!isset($record['host'])) { + echo "Error while validating record " . $buffer . ": No host is found." . PHP_EOL; + continue; + + } else if (!$util->isValidDomain($record['host'], $error)) { echo "Error while validating " . $record['host'] . ": " . $error . PHP_EOL; continue; diff --git a/lib/bob.php b/lib/bob.php index 7b2811d..f10dbc0 100644 --- a/lib/bob.php +++ b/lib/bob.php @@ -25,6 +25,9 @@ class BOB { } else { + socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 10, 'usec' => 10 * 1000]); + socket_set_option($this->sock, SOL_SOCKET, SO_SNDTIMEO, ['sec' => 10, 'usec' => 10 * 1000]); + $result = socket_connect($this->sock, $this->options["bob_host"], $this->options["bob_port"]); if ($result === false) { @@ -33,11 +36,13 @@ class BOB { /* Reading BOB greeting */ $response = socket_read($this->sock, 1024); - if(!preg_match('/OK/', $response)) { - throw new \ErrorException("BOB returned incorrect response on connect"); + throw new \ErrorException("BOB returned incorrect response on connect or timed out"); } + + /* Post-init timeouts setting */ + socket_set_option($this->sock, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 180, 'usec' => 180 * 1000]); } } diff --git a/lib/checker.php b/lib/checker.php index fb6ffea..d7285ac 100644 --- a/lib/checker.php +++ b/lib/checker.php @@ -30,7 +30,7 @@ class Checker implements Task $bob->getnick(); $result = false; - for ($i = 0, $tries = $this->options['check_tries']; $i < $tries; ++$i) { + for ($i = 0, $tries = $this->options['check_tries'], $sleep = $this->options['retry_delay']; $i < $tries; ++$i) { $result = $bob->lookuplocal($this->base32 . ".b32.i2p"); if(!$result) { $result = $bob->lookup($this->base32 . ".b32.i2p"); @@ -39,6 +39,10 @@ class Checker implements Task if ($result) { break; } + + // sleep before next try if we must do more that 1 tries to lookup destination + if($tries > 1 && $i < $tries) // do not sleep if that is last try + sleep($sleep); } $bob = null; diff --git a/lib/utils.php b/lib/utils.php index 0d53477..6b2f0de 100644 --- a/lib/utils.php +++ b/lib/utils.php @@ -212,7 +212,7 @@ class Utils { { $record = []; - /* Return empty array if no data provided */ + /* Return empty array if no data provided */ if(!strlen($data)) return $record; @@ -223,6 +223,11 @@ class Utils { /* Parse host record */ $host = preg_split("/\=/", $tmp[0], 2); + + /* Return empty array if host or b64 is not set */ + if(!isset($host[0]) || !isset($host[1])) + return $record; + $record["host"] = $host[0]; $record["b64"] = $host[1]; @@ -234,7 +239,7 @@ class Utils { $cmdlist = preg_split("/#/", $tmp[1]); foreach($cmdlist as $i) { - list($name,$value) = explode('=', $i, 2); + list($name, $value) = explode('=', $i, 2); $cmds[$name] = $value; } diff --git a/public/index.php b/public/index.php index 81ee6f3..650757d 100644 --- a/public/index.php +++ b/public/index.php @@ -23,6 +23,10 @@ $r->addRoute('^/all/?([0-9]+)?/?', function($url, $page = 1) { require __DIR__ . '/../views/all.php'; }); +$r->addRoute('^/api/?(all|status)?/?([^\?/]*)?/?(?:\?|$)', function($url, $command, $query = "") { + require __DIR__ . '/../views/api.php'; +}); + $r->addRoute('^/jump/?([^\?/]*)/?(?:\?|$)', function($url, $query = "") { require __DIR__ . '/../views/jump.php'; }); diff --git a/templates/add.twig b/templates/add.twig index cce7e26..8d73326 100644 --- a/templates/add.twig +++ b/templates/add.twig @@ -19,6 +19,8 @@

Subdomain successfuly added

{% elseif result.command == 'changedest' %}

Domain destination successfuly changed

+ {% elseif result.reregister %} +

Domain successfuly re-registered

{% else %}

Domain successfuly added

{% endif %} diff --git a/templates/alive.twig b/templates/alive.twig index 9cce899..b434a7b 100644 --- a/templates/alive.twig +++ b/templates/alive.twig @@ -15,7 +15,7 @@ AH B32 Full Base32 - Last seen + Last seen (UTC) diff --git a/templates/all.twig b/templates/all.twig index 2790b35..defd076 100644 --- a/templates/all.twig +++ b/templates/all.twig @@ -16,7 +16,7 @@ AH B32 Full Base32 - Last seen + Last seen (UTC) diff --git a/templates/hidden.twig b/templates/hidden.twig index fee3b31..c88fd34 100644 --- a/templates/hidden.twig +++ b/templates/hidden.twig @@ -15,7 +15,7 @@ AH B32 Full Base32 - Last seen + Last seen (UTC) diff --git a/templates/latest.twig b/templates/latest.twig index b6c07e0..4a15abc 100644 --- a/templates/latest.twig +++ b/templates/latest.twig @@ -16,7 +16,7 @@ AH B32 Full Base32 - Added + Added (UTC) diff --git a/templates/search.twig b/templates/search.twig index 032034e..dd0eeb5 100644 --- a/templates/search.twig +++ b/templates/search.twig @@ -24,7 +24,7 @@ AH B32 Full Base32 - Last seen + Last seen (UTC) diff --git a/views/add.php b/views/add.php index 3c915ef..c2802a6 100644 --- a/views/add.php +++ b/views/add.php @@ -32,11 +32,16 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) { $parsed = $util->parseHostRecord($record); - if (!$util->isValidDomain($parsed['host'], $error)) { + if (!isset($parsed['host'])) { + $result["error"] = "Error while validating: Incorrect Auth string"; + + } else if (!$util->isValidDomain($parsed['host'], $error)) { $result["error"] = "Error while validating: " . $error; + } else { if ($util->isPunycodeDomain($parsed['host'])) { $domain = idn_to_utf8($parsed['host'], 0, INTL_IDNA_VARIANT_UTS46); + } else { $domain = $parsed['host']; } @@ -48,10 +53,10 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) { $result["error"] = "Error while validating: " . $error[0]; } else { - /* Check if such domain name already registered */ - $STH = $pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1"); - if (isset($parsed["commands"]["action"])) { + /* Check if such domain name already registered */ + $STH = $pdo->query("SELECT COUNT(*) FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1"); + switch ($parsed["commands"]["action"]) { case 'addsubdomain': if ($STH->fetchColumn() == 1) { @@ -125,7 +130,7 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) { /* Getting domain level (2LD, 3LD and etc.) and validating that domain at higher level is registered (2LD if registering 3LD). */ } else if (sizeof(explode(".", $domain)) > 2) { - $result["error"] = "Error while validating: you can't register subdomain (sub.example.i2p) as domain alias using addname action."; + $result["error"] = "Error while validating: you can't register subdomain (sub.example.i2p) as domain alias using addname action."; } else if (!isset($parsed["commands"]["oldname"])) { $result["error"] = "Error while validating: required fields not found. Re-check your registration string."; @@ -161,9 +166,16 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) { } } else { - if($STH->fetchColumn() == 1) { + /* Check if such domain name already registered */ + $STH = $pdo->query("SELECT `host`, `base32`, `base64`, `initial`, `disabled` FROM `hosts` WHERE `host` = '" . $domain . "' LIMIT 1"); + $row = $STH->fetch(PDO::FETCH_ASSOC); + + if(count($row) && !$row['disabled']) { $result["error"] = "Error while validating: That domain is already registered."; + } else if(count($row) && $row['disabled'] && $row['initial']) { + $result["error"] = "Error while validating: That domain is reserved and can't be re-registered automatically. Please contact service support team."; + } else { if (isset($parsed["commands"]["oldname"]) || isset($parsed["commands"]["olddest"]) || isset($parsed["commands"]["oldsig"])) { $result["error"] = "Error while validating: unexpected fields found."; @@ -172,6 +184,24 @@ if (isset($_POST["record"]) && !empty($_POST["record"])) { $result["error"] = "Error while validating: you can't register subdomain without specific action field."; } else { + $result["reregister"] = false; + if(count($row) && $row['disabled']) { /* processing disabled domain */ + $log = "[" . date("d-M-Y H:i:s e") . "] Re-registering attempt for " . $row['host'] . "! Next records will be deleted:" . PHP_EOL; + + /* print all records, which will be deleted*/ + $STH = $pdo->query("SELECT `host`, `base32`, `base64` FROM `hosts` WHERE `host` = '" . $domain . "' OR `host` LIKE '%." . $domain . "'"); + $hosts = $STH->fetchAll(PDO::FETCH_ASSOC); + foreach ($hosts as $host) { + $log .= "Host: " . $host['host'] . PHP_EOL . "Base32: " . $host['base32'] . PHP_EOL . "Base64: " . $host['base64'] . PHP_EOL; + } + + file_put_contents(__DIR__ . '/../logs/reg.log', $log, FILE_APPEND); + + /* remove domain and subdomains if any found */ + $pdo->exec("DELETE FROM `hosts` WHERE `host` = '" . $domain . "' OR `host` LIKE '%." . $domain . "'"); + $result["reregister"] = true; + } + $base32 = $util->b32from64($parsed["b64"]); /* Adding to database 2LD domain */ diff --git a/views/api.php b/views/api.php new file mode 100644 index 0000000..da637c6 --- /dev/null +++ b/views/api.php @@ -0,0 +1,30 @@ +pdo; + +header('Content-Type: application/json'); + +if (isset($_GET["all"])) + $all = true; + +if(!$command || !in_array($command, ['all', 'status'])) + exit(json_encode(["status" => "error", "message" => "Incorrect request"])); + +if($command == "all") { + $STH = $pdo->query ("SELECT `base32`, UNIX_TIMESTAMP(`last_seen`) as `last_seen` FROM `hosts` " . + "WHERE `approved` = 1 AND `disabled` = 0" . + ($all ? " " : " AND `blacklisted` = 0 ")); + $STH->setFetchMode(PDO::FETCH_ASSOC); + $rows = $STH->fetchAll(); + + $data = []; + foreach($rows as $row) { + $data[$row["base32"] . ".b32.i2p"] = $row["last_seen"]; + } + + exit(json_encode($data, JSON_PRETTY_PRINT)); +}