Merge pull request #22 from hybula/main

New release
This commit is contained in:
Tamer 2023-06-26 16:10:56 +02:00 committed by GitHub
commit d613015aad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 219 additions and 83 deletions

View file

@ -6,10 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## 1.2.0 - 2023-06-26
### Fixed
- PR https://github.com/hybula/lookingglass/pull/21 thanks to @JKJameson.
- Issue #20 thanks to @amirgilan for reporting.
### Added
- Latency feature (by default disabled).
## 1.1.3 - 2023-03-01 ## 1.1.3 - 2023-03-01
### Fixed ### Fixed
- Issue #12 with https://github.com/hybula/lookingglass/pull/14 thanks to @MarcHagen - Issue #12 with https://github.com/hybula/lookingglass/pull/14 thanks to @MarcHagen.
- Issue #13 with https://github.com/hybula/lookingglass/pull/15 thanks to @MarcHagen - Issue #13 with https://github.com/hybula/lookingglass/pull/15 thanks to @MarcHagen.
## 1.1.2 - 2023-01-05 ## 1.1.2 - 2023-01-05
### Fixed ### Fixed

View file

@ -1,4 +1,6 @@
<?php declare(strict_types=1); <?php
declare(strict_types=1);
/** /**
* Hybula Looking Glass * Hybula Looking Glass
* *
@ -10,6 +12,7 @@
* @since File available since release 0.1 * @since File available since release 0.1
* @link https://github.com/hybula/lookingglass * @link https://github.com/hybula/lookingglass
*/ */
namespace Hybula; namespace Hybula;
class LookingGlass class LookingGlass
@ -41,31 +44,84 @@ class LookingGlass
public static function validateConfig(): void public static function validateConfig(): void
{ {
//@formatter:off //@formatter:off
if (!defined('LG_TITLE')) die('LG_TITLE not found in config.php'); if (!defined('LG_TITLE')) {
if (!defined('LG_LOGO')) die('LG_LOGO not found in config.php'); die('LG_TITLE not found in config.php');
if (!defined('LG_LOGO_URL')) die('LG_LOGO_URL not found in config.php'); }
if (!defined('LG_CSS_OVERRIDES')) die('LG_CSS_OVERRIDES not found in config.php'); if (!defined('LG_LOGO')) {
if (!defined('LG_BLOCK_NETWORK')) die('LG_BLOCK_NETWORK not found in config.php'); die('LG_LOGO not found in config.php');
if (!defined('LG_BLOCK_LOOKINGGLAS')) die('LG_BLOCK_LOOKINGGLAS not found in config.php'); }
if (!defined('LG_BLOCK_SPEEDTEST')) die('LG_BLOCK_SPEEDTEST not found in config.php'); if (!defined('LG_LOGO_URL')) {
if (!defined('LG_BLOCK_CUSTOM')) die('LG_BLOCK_CUSTOM not found in config.php'); die('LG_LOGO_URL not found in config.php');
if (!defined('LG_CUSTOM_HTML')) die('LG_CUSTOM_HTML not found in config.php'); }
if (!defined('LG_CUSTOM_PHP')) die('LG_CUSTOM_PHP not found in config.php'); if (!defined('LG_CSS_OVERRIDES')) {
if (!defined('LG_LOCATION')) die('LG_LOCATION not found in config.php'); die('LG_CSS_OVERRIDES not found in config.php');
if (!defined('LG_MAPS_QUERY')) die('LG_MAPS_QUERY not found in config.php'); }
if (!defined('LG_FACILITY')) die('LG_FACILITY not found in config.php'); if (!defined('LG_BLOCK_NETWORK')) {
if (!defined('LG_FACILITY_URL')) die('LG_FACILITY_URL not found in config.php'); die('LG_BLOCK_NETWORK not found in config.php');
if (!defined('LG_IPV4')) die('LG_IPV4 not found in config.php'); }
if (!defined('LG_IPV6')) die('LG_IPV6 not found in config.php'); if (!defined('LG_BLOCK_LOOKINGGLAS')) {
if (!defined('LG_METHODS')) die('LG_METHODS not found in config.php'); die('LG_BLOCK_LOOKINGGLAS not found in config.php');
if (!defined('LG_LOCATIONS')) die('LG_LOCATIONSnot found in config.php'); }
if (!defined('LG_SPEEDTEST_IPERF')) die('LG_SPEEDTEST_IPERF not found in config.php'); if (!defined('LG_BLOCK_SPEEDTEST')) {
if (!defined('LG_SPEEDTEST_LABEL_INCOMING')) die('LG_SPEEDTEST_LABEL_INCOMING not found in config.php'); die('LG_BLOCK_SPEEDTEST not found in config.php');
if (!defined('LG_SPEEDTEST_CMD_INCOMING')) die('LG_SPEEDTEST_CMD_INCOMING not found in config.php'); }
if (!defined('LG_SPEEDTEST_LABEL_OUTGOING')) die('LG_SPEEDTEST_LABEL_OUTGOING not found in config.php'); if (!defined('LG_BLOCK_CUSTOM')) {
if (!defined('LG_SPEEDTEST_CMD_OUTGOING')) die('LG_SPEEDTEST_CMD_OUTGOING not found in config.php'); die('LG_BLOCK_CUSTOM not found in config.php');
if (!defined('LG_SPEEDTEST_FILES')) die('LG_SPEEDTEST_FILES not found in config.php'); }
if (!defined('LG_TERMS')) die('LG_TERMS not found in config.php'); if (!defined('LG_CUSTOM_HTML')) {
die('LG_CUSTOM_HTML not found in config.php');
}
if (!defined('LG_CUSTOM_PHP')) {
die('LG_CUSTOM_PHP not found in config.php');
}
if (!defined('LG_LOCATION')) {
die('LG_LOCATION not found in config.php');
}
if (!defined('LG_MAPS_QUERY')) {
die('LG_MAPS_QUERY not found in config.php');
}
if (!defined('LG_FACILITY')) {
die('LG_FACILITY not found in config.php');
}
if (!defined('LG_FACILITY_URL')) {
die('LG_FACILITY_URL not found in config.php');
}
if (!defined('LG_IPV4')) {
die('LG_IPV4 not found in config.php');
}
if (!defined('LG_IPV6')) {
die('LG_IPV6 not found in config.php');
}
if (!defined('LG_METHODS')) {
die('LG_METHODS not found in config.php');
}
if (!defined('LG_LOCATIONS')) {
die('LG_LOCATIONSnot found in config.php');
}
if (!defined('LG_SPEEDTEST_IPERF')) {
die('LG_SPEEDTEST_IPERF not found in config.php');
}
if (!defined('LG_SPEEDTEST_LABEL_INCOMING')) {
die('LG_SPEEDTEST_LABEL_INCOMING not found in config.php');
}
if (!defined('LG_SPEEDTEST_CMD_INCOMING')) {
die('LG_SPEEDTEST_CMD_INCOMING not found in config.php');
}
if (!defined('LG_SPEEDTEST_LABEL_OUTGOING')) {
die('LG_SPEEDTEST_LABEL_OUTGOING not found in config.php');
}
if (!defined('LG_SPEEDTEST_CMD_OUTGOING')) {
die('LG_SPEEDTEST_CMD_OUTGOING not found in config.php');
}
if (!defined('LG_SPEEDTEST_FILES')) {
die('LG_SPEEDTEST_FILES not found in config.php');
}
if (!defined('LG_TERMS')) {
die('LG_TERMS not found in config.php');
}
if (!defined('LG_CHECK_LATENCY')) {
die('LG_CHECK_LATENCY not found in config.php');
}
//@formatter:on //@formatter:on
} }
@ -292,8 +348,7 @@ class LookingGlass
@ob_flush(); @ob_flush();
flush(); flush();
continue; continue;
} } // correct output for traceroute
// correct output for traceroute
elseif ($type === 'traceroute') { elseif ($type === 'traceroute') {
if ($match < 10 && preg_match('/^[0-9] /', $str, $string)) { if ($match < 10 && preg_match('/^[0-9] /', $str, $string)) {
$str = preg_replace('/^[0-9] /', '&nbsp;'.$string[0], $str); $str = preg_replace('/^[0-9] /', '&nbsp;'.$string[0], $str);
@ -353,6 +408,66 @@ class LookingGlass
} }
return true; return true;
} }
public static function getLatency(): float
{
$getLatency = self::getLatencyFromSs(self::detectIpAddress());
if (isset($getLatency[0])) {
return round((float)$getLatency[0]['latency']);
} else {
return 0.00;
}
}
/**
* This uses the command 'ss' in order to find out latency.
* A clever way coded by @ayyylias, so please keep credits and do not just steal.
*
* @param string $ip The command to execute.
* @return array Returns an array with results.
*/
private static function getLatencyFromSs(string $ip): array
{
$lines = shell_exec('/usr/sbin/ss -Hti state established');
$ss = [];
$i = 0;
$j = 0;
foreach (explode(PHP_EOL, $lines) as $line) {
if ($i > 1) {
$i = 0;
$j++;
}
if ($line !== '') {
@$ss[$j] .= $line;
$i++;
}
}
$output = [];
foreach ($ss as $socket) {
$socket = preg_replace('!\s+!', ' ', $socket);
$explodedsocket = explode(' ', $socket);
preg_match('/\d+\.\d+\.\d+\.\d+/', $explodedsocket[2], $temp);
if (!isset($temp[0])) {
continue;
}
$sock['local'] = $temp[0];
preg_match('/\d+\.\d+\.\d+\.\d+/', $explodedsocket[3], $temp);
$sock['remote'] = $temp[0];
preg_match('/segs_out:(\d+)/', $socket, $temp);
$sock['segs_out'] = $temp[1];
preg_match('/segs_in:(\d+)/', $socket, $temp);
$sock['segs_in'] = $temp[1];
preg_match_all('/rtt:(\d+\.\d+)\/(\d+\.\d+)/', $socket, $temp);
$sock['latency'] = $temp[1][0];
$sock['jitter'] = $temp[2][0];
preg_match_all('/retrans:\d+\/(\d+)/', $socket, $temp);
$sock['retransmissions'] = (isset($temp[1][0]) ? $temp[1][0] : 0);
if ($sock['remote'] == $ip) {
$output[] = $sock;
}
}
return $output;
}
} }
class Hop class Hop
@ -434,7 +549,6 @@ class Parser
} }
foreach ($hop->timings as $time) { foreach ($hop->timings as $time) {
if ($hop->best > $time) { if ($hop->best > $time) {
$hop->best = $time; $hop->best = $time;
} }

View file

@ -19,6 +19,8 @@ use Hybula\LookingGlass;
LookingGlass::validateConfig(); LookingGlass::validateConfig();
LookingGlass::startSession(); LookingGlass::startSession();
header('X-Accel-Buffering: no');
if (isset($_SESSION[LookingGlass::SESSION_TARGET_HOST]) && if (isset($_SESSION[LookingGlass::SESSION_TARGET_HOST]) &&
isset($_SESSION[LookingGlass::SESSION_TARGET_METHOD]) && isset($_SESSION[LookingGlass::SESSION_TARGET_METHOD]) &&
isset($_SESSION[LookingGlass::SESSION_CALL_BACKEND]) isset($_SESSION[LookingGlass::SESSION_CALL_BACKEND])

View file

@ -9,6 +9,9 @@ const LG_LOGO = '<h2>Company Looking Glass</h2>';
// Define the URL where the logo points to; // Define the URL where the logo points to;
const LG_LOGO_URL = 'https://github.com/hybula/lookingglass/'; const LG_LOGO_URL = 'https://github.com/hybula/lookingglass/';
// Enable the latency check feature;
const LG_CHECK_LATENCY = false;
// Define a custom CSS file which can be used to style the LG, set false to disable, else point to the CSS file; // Define a custom CSS file which can be used to style the LG, set false to disable, else point to the CSS file;
const LG_CSS_OVERRIDES = false; const LG_CSS_OVERRIDES = false;
// Define <head> content, this could be JS, CSS or meta tags; // Define <head> content, this could be JS, CSS or meta tags;

View file

@ -11,8 +11,13 @@ const LG_LOGO_URL = 'https://github.com/hybula/lookingglass/';
// Define <head> content, this could be JS, CSS or meta tags; // Define <head> content, this could be JS, CSS or meta tags;
const LG_CUSTOM_HEAD = false; const LG_CUSTOM_HEAD = false;
// Enable the latency check feature;
const LG_CHECK_LATENCY = false;
// Define a custom CSS file which can be used to style the LG, set false to disable, else point to the CSS file; // Define a custom CSS file which can be used to style the LG, set false to disable, else point to the CSS file;
const LG_CSS_OVERRIDES = false; const LG_CSS_OVERRIDES = false;
// Define <head> content, this could be JS, CSS or meta tags;
const LG_CUSTOM_HEAD = false;
// Enable or disable blocks/parts of the LG, set false to hide a part; // Enable or disable blocks/parts of the LG, set false to hide a part;
const LG_BLOCK_NETWORK = true; const LG_BLOCK_NETWORK = true;

View file

@ -77,6 +77,10 @@ if (LG_BLOCK_CUSTOM) {
$templateData['custom_html'] = ob_get_clean(); $templateData['custom_html'] = ob_get_clean();
} }
if (LG_CHECK_LATENCY && filter_var(LookingGlass::detectIpAddress(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$templateData['latency'] = LookingGlass::getLatency();
}
$templateData['csrfToken'] = $_SESSION[LookingGlass::SESSION_CSRF] = bin2hex(random_bytes(12)); $templateData['csrfToken'] = $_SESSION[LookingGlass::SESSION_CSRF] = bin2hex(random_bytes(12));
?> ?>
<!doctype html> <!doctype html>
@ -163,7 +167,7 @@ $templateData['csrfToken'] = $_SESSION[LookingGlass::SESSION_CSRF] = bin2hex(ran
<label class="mb-2 text-muted">Your IP</label> <label class="mb-2 text-muted">Your IP</label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" value="<?php echo $templateData['user_ip'] ?>" onfocus="this.select()" readonly=""> <input type="text" class="form-control" value="<?php echo $templateData['user_ip'] ?>" onfocus="this.select()" readonly="">
<button class="btn btn-outline-secondary" onclick="copyToClipboard('<?php echo $templateData['user_ip'] ?>', this)">Copy</button> <?php if (LG_CHECK_LATENCY && filter_var(LookingGlass::detectIpAddress(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)): ?><label class="input-group-text" title="Latency between this looking glass and your connection." style="cursor: help;"><small><?php echo $templateData['latency'] ?> MS</small></label><?php endif ?>
</div> </div>
</div> </div>
</div> </div>