diff --git a/htdocs/.gitignore b/htdocs/.gitignore index ed222e1..f94f394 100644 --- a/htdocs/.gitignore +++ b/htdocs/.gitignore @@ -1 +1,6 @@ lg_config.php +!lg_logo.gif +*.gif +*.jpg +*.jpeg +*.png diff --git a/htdocs/backend.php b/htdocs/backend.php new file mode 100644 index 0000000..1b1f9a7 --- /dev/null +++ b/htdocs/backend.php @@ -0,0 +1,122 @@ + 503, + "response" => json_decode(curl_error($ch), true) + ); + } + curl_close($ch); + if(! empty($status)){ + if($status < 400){ + return array( + "status" => $status, + "response" => json_decode($data, true) + ); + } else { + return array( + "status" => $status, + "response" => json_decode($data, true) + ); + } + } else { + return array( + "status" => $status, + "response" => json_decode($data, true) + ); + } + } elseif($action == "post"){ + $encodedPostData = http_build_query($postdata); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_SSLVERSION, 6); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedPostData); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, "3"); + curl_setopt($ch, CURLOPT_TIMEOUT, "3"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_VERBOSE, true); + $data = curl_exec($ch); + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if(curl_error($ch)){ + return array( + "status" => 503, + "response" => json_decode(curl_error($ch), true) + ); + } + curl_close($ch); + if(! empty($status)){ + if($status < 400){ + return array( + "status" => $status, + "response" => json_decode($data, true) + ); + } else { + return array( + "status" => $status, + "response" => json_decode($data, true) + ); + } + } else { + return array( + "status" => $status, + "response" => json_decode($data, true) + ); + } + } else { + return array( + "status" => 400, + "response" => null + ); + } +} + +function verifyToken($token){ + global $_CONFIG; + $url = $_CONFIG['recaptchaBackendVerifyURL']; + $headers = array( + "Content-Type: application/x-www-form-urlencoded" + ); + return curlCall($url, $headers, "post", [ + "secret" => $_CONFIG['recaptchaSiteSecret'], + "response" => $token + ]); +} + +$request = json_decode(file_get_contents('php://input'), true); +$token = ""; + +if(isset($request['token'])){ + $token = $request['token']; +} + +$response = verifyToken($token); + +if($response){ + echo json_encode($response, JSON_PRETTY_PRINT); +} else { + var_dump($response); +} + + + +?> \ No newline at end of file diff --git a/htdocs/forbidden.php b/htdocs/forbidden.php new file mode 100644 index 0000000..90a8346 --- /dev/null +++ b/htdocs/forbidden.php @@ -0,0 +1,17 @@ + + +
+ +reCAPTCHA was unsuccessful or expired, redirecting...
+ + + + \ No newline at end of file diff --git a/htdocs/index.php b/htdocs/index.php index 3392394..4bd9a1b 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -59,6 +59,13 @@ 'company' => 'My Company Name', 'logo' => 'lg_logo.gif', 'color' => '#E48559', + 'recaptchaEnabled' => false, + 'recaptchaFrontendURL' => 'https://www.google.com/recaptcha/api.js?render=', + 'recaptchaBackendVerifyURL' => 'https://www.google.com/recaptcha/api/siteverify', + 'recaptchaSiteKey' => "", + 'recaptchaSiteSecret' => "", + 'showpeerinfo' => 'TRUE', + 'safesubnet' => '', 'sshauthtype' => 'password', 'sshprivatekeypath' => '', 'sshpwdcommand' => 'plink', @@ -81,6 +88,8 @@ $protocol = isset($_REQUEST['protocol']) ? trim($_REQUEST['protocol']) : FALSE; $command = isset($_REQUEST['command']) ? trim($_REQUEST['command']) : FALSE; $query = isset($_REQUEST['query']) ? trim($_REQUEST['query']) : FALSE; +$token = isset($_REQUEST['token']) ? trim($_REQUEST['token']) : FALSE; + if ($command != 'graph' OR !isset($_REQUEST['render']) OR !isset($_CONFIG['routers'][$router])) { @@ -127,10 +136,25 @@ function load() { } //--> + + + + + - +shell_exec not enabled
popen not working
Summary not permitted.
Router: '.$_CONFIG['routers'][$router]['description'].'
Command: '.$exec.'
';
+ print 'Router: '.$_CONFIG['routers'][$router]['description'].'
';
+ if($ipsafe OR (isset($_CONFIG['routers'][$router]) AND isset($_CONFIG['routers'][$router]['showpeerinfo']) AND $_CONFIG['routers'][$router]['showpeerinfo'] == "TRUE") OR (isset($_CONFIG['showpeerinfo']) AND $_CONFIG['showpeerinfo'] == "TRUE" AND !isset($_CONFIG['routers'][$router]['showpeerinfo']))){
+ print 'Command: '.$exec.'
';
+ } else {
+ print '';
+ }
flush();
process($url, $exec);
@@ -543,7 +638,7 @@ function load() {
// HTML form
?>
-
@@ -588,7 +690,7 @@ function load() {
?>
- Information: RIPEstat he.net robtex.com PeeringDB
+ Information: RIPEstat RADb he.net robtex.com PeeringDB
Copyright ©
@@ -602,7 +704,7 @@ function load() {
*/
function process($url, $exec, $return_buffer = FALSE)
{
- global $_CONFIG, $router, $protocol, $os, $command, $query, $ros;
+ global $_SERVER, $_CONFIG, $router, $protocol, $os, $command, $query, $ros, $token;
$sshauthtype = null;
$buffer = '';
@@ -610,6 +712,19 @@ function process($url, $exec, $return_buffer = FALSE)
$index = 0;
$str_in = array();
+ $urlProtocol = isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ? 'https' : 'http';
+ $curlUrl = $urlProtocol . "://" . $_SERVER['SERVER_NAME'] . "/backend.php";
+
+ if($_CONFIG['recaptchaEnabled'] === true) {
+ $result = verifyToken($curlUrl, $token);
+ if($result == false) {
+ echo "";
+ exit;
+ }
+ }
+
+// do processing for the $response
+
switch ($url['scheme'])
{
case 'ssh':
@@ -707,7 +822,14 @@ function process($url, $exec, $return_buffer = FALSE)
{
$instance_list = parse_list($instance);
- print 'BGP router identifier '.$instance_list['router-id'].', local AS number '.link_as($instance_list['as'])."\n";
+ if(! empty($instance_list['confederation']))
+ {
+ print 'BGP router identifier '.$instance_list['router-id'].', sub ' . link_as($instance_list['as'], true) . " within confederation " . link_as($instance_list['confederation'], true) . "\n";
+ }
+ else
+ {
+ print 'BGP router identifier '.$instance_list['router-id'].', local '.link_as($instance_list['as'])."\n";
+ }
}
}
@@ -736,7 +858,7 @@ function process($url, $exec, $return_buffer = FALSE)
{
@shell_exec('echo n | '.$ssh_path.' '.implode(' ', $params).' screen-length 0 temporary');
}*/
-
+
if ($fp = @popen('echo n | '.$ssh_path.' '.implode(' ', $params).' '.$exec, 'r'))
{
while (!feof($fp))
@@ -970,15 +1092,61 @@ function process($url, $exec, $return_buffer = FALSE)
flush();
}
+function verifyToken($url, $token){
+ $headers = array(
+ "Content-Type: application/json"
+ );
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["token" => $token]));
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, "1");
+ curl_setopt($ch, CURLOPT_TIMEOUT, "3");
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_VERBOSE, true);
+
+ $data = curl_exec($ch);
+ $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ if(curl_error($ch)){
+ #var_dump(curl_error($ch)); exit;
+ return false;
+ }
+ curl_close($ch);
+
+ if($status > 300){
+ #var_dump($status) . var_dump($data); exit;
+ return false;
+ }
+ if(!$data){
+ #var_dump($status) . var_dump($data); exit;
+ return false;
+ }
+ $decodedData = json_decode($data, true);
+ if($decodedData['status'] !== 200){
+ #var_dump($decodedData); exit;
+ return false;
+ }
+ if(!$decodedData['response']){
+ #var_dump($decodedData); exit;
+ return false;
+ }
+ if($decodedData['response']['success'] !== true){
+ #var_dump($decodedData); exit;
+ return false;
+ }
+ return true;
+}
+
/**
* Parse output contents
*/
function parse_out($output, $check = FALSE)
{
- global $_CONFIG, $router, $protocol, $os, $command, $exec, $query, $index, $lastip, $best, $count, $str_in, $ros;
+ global $_CONFIG, $router, $protocol, $os, $command, $exec, $query, $index, $lastip, $best, $count, $str_in, $ros, $ipsafe;
$output = str_replace("\r\n", "\n", $output);
-
+
// MikroTik
if (preg_match("/^\/(ip|ipv6) route print detail/i", $exec) AND $os == 'mikrotik')
{
@@ -1002,13 +1170,33 @@ function parse_out($output, $check = FALSE)
{
$data_exp = explode(' ', trim($summary_part), 3);
- $summary_part = preg_replace_callback(
- "/bgp-as-path=\"([^\"]+)\"/x",
- function ($matches) {
- return stripslashes('bgp-as-path=\"'.link_as($matches[1]).'\"');
- },
- $summary_part
- );
+ if(!$ipsafe){
+ $summary_part = preg_replace("/\svia\s\s?\S+/x", "", $summary_part);
+ }
+ $matches = null;
+ preg_match('/bgp-as-path\=\"([^\"]+)\"/', $summary_part, $matches);
+ if(! empty($matches[1])){
+ $aspathmatches = array();
+ $aspathOriginal = $matches[0];
+ $aspathOriginal = str_replace('"', '\"', $aspathOriginal);
+ $summary_part = str_replace($matches[0], $aspathOriginal, $summary_part);
+ $aspath = $aspathOriginal;
+ preg_match_all("/((?:\d+)+)/", $aspath, $matches);
+ $asns = null;
+ $asns = $matches[1];
+ $matchCount = 0;
+ if(! empty($asns)){
+ foreach($matches[1] as $m){
+ if(empty($aspathmatches[$m])){
+ $aspathmatches[$m] = link_as($m);
+ }
+ }
+ if(!empty($aspathmatches)){
+ $aspath = str_replace(array_keys($aspathmatches), array_values($aspathmatches), $aspath);
+ $summary_part = str_replace($aspathOriginal, stripslashes($aspath), $summary_part);
+ }
+ }
+ }
if (strpos($data_exp[1], 'A') !== FALSE)
{
@@ -1175,7 +1363,7 @@ function ($matches) {
return 'traceroute to '.$query.' ('.get_ptr($query).'), 64 hops max, 60 byte packets'."\n";
}
-
+
if ($index > 0)
{
$exp = explode(' ', preg_replace('/[\s\t]+/', ' ', trim($output)));
@@ -1195,11 +1383,12 @@ function ($matches) {
}
else
{
- $radb = get_radb($exp[1]);
-
+ #$radb = get_radb($exp[1]);
+ $asn = get_as($exp[1], "15835");
$new_exp[1] = get_ptr($exp[1]);
$new_exp[2] = '('.$exp[1].')';
- $new_exp[3] = '['.(isset($radb['origin']) ? 'AS '.link_as($radb['origin']) : '').']';
+ #$new_exp[3] = '['.(isset($radb['origin']) ? 'AS '.link_as($radb['origin']) : '').']';
+ $new_exp[3] = $asn;
$new_exp[4] = $exp[5].'ms';
$new_exp[5] = $exp[6].'ms';
$new_exp[6] = $exp[7].'ms';
@@ -2068,7 +2257,7 @@ function ($matches) {
if (preg_match("/^trace/", $exec))
{
$output = preg_replace("/\[AS0\]\s(.*)/", "\\1", $output);
-
+
// IPv4
$output = preg_replace_callback(
"/(\[AS)(\d+)(\])\s(.*)(\))(.*)/",
@@ -2404,14 +2593,44 @@ function link_community($line)
/**
* Link to AS whois
*/
-function link_as($line, $word = FALSE)
+function link_as($line, $word = FALSE, $type = null)
{
global $_CONFIG;
- //print_r($line);
-
- return preg_replace("/(?:AS)?([\d]+)/is",
- "".($word ? 'AS' : '')."\\1", $line);
+ $asn = intval(preg_replace("/(?:AS)?([\d]+)/is",
+ "$1", $line));
+
+ $url = null;
+ $publicasn = false;
+ if(($asn >= 1 AND $asn <= 23455) OR ($asn >= 23457 AND $asn <= 64495) OR ($asn >= 131072 AND $asn <= 4199999999)){
+ $publicasn = true;
+ }
+
+ if($word)
+ {
+ $asnword = "AS" . $asn;
+ }
+ else
+ {
+ $asnword = $asn;
+ }
+
+ if($publicasn AND $type == "url")
+ {
+ return htmlspecialchars($_CONFIG['aswhois']) . "AS" . $asn;
+ }
+ elseif($publicasn)
+ {
+ return '' . $asnword . '';
+ }
+ elseif($type == "url")
+ {
+ return null;
+ }
+ else
+ {
+ return $asnword;
+ }
}
function get_as($ip, $original_as)
@@ -2570,10 +2789,9 @@ function get_path_graph($router, $query, $as_pathes, $as_best_path, $format = 's
$color = isset($as_peer_list[$as_id]) ? ($as_peer_list[$as_id] ? '#CCFFCC' : '#CCCCFF') : 'white';
$asinfo = get_asinfo($as_id);
-
$graph->addNode($as_id, array
(
- 'URL' => $_CONFIG['aswhois'].$as_id,
+ 'URL' => link_as($as_id, false, "url"),
'target' => '_blank',
'label' => isset($asinfo['description']) ? $as_id."\n".$asinfo['description'] : $as_id,
'style' => 'filled',
@@ -2718,16 +2936,23 @@ function get_asinfo($request)
}
$segments = array_map('trim', explode('|', $dns[0]['txt'], 5));
-
+
if (sizeof($segments) != 5)
{
return FALSE;
}
-
- list($segments[4], $segments[5]) = explode(' ', $segments[4], 2);
-
+ if(strpos(explode(',', $segments[4], 2)[0], " "))
+ {
+ list($segments[4], $segments[5]) = explode(' ', $segments[4], 2);
+ }
+ else
+ {
+ $segments[5] = $segments[4];
+ $segments[4] = explode(',', $segments[4], 2)[0];
+ }
+
$segments[5] = str_replace('_', '"', $segments[5]);
-
+
return array
(
'asn' => $segments[0],
@@ -2865,6 +3090,31 @@ function group_routers($array)
return $return;
}
+function checkIP($ip, $cidr)
+{
+ if (strpos($cidr, "/") !== false)
+ {
+ list($net, $mask) = explode("/", $cidr);
+
+ $ip_net = ip2long ($net);
+ $ip_mask = ~((1 << (32 - $mask)) - 1);
+
+ $ip_ip = ip2long ($ip);
+
+ $ip_ip_net = $ip_ip & $ip_mask;
+
+ return ($ip_ip_net == $ip_net);
+ }
+ elseif (filter_var(trim($cidr), FILTER_VALIDATE_IP) == true AND $ip === $cidr)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
// ------------------------------------------------------------------------
/**
diff --git a/htdocs/lg_config.php.example b/htdocs/lg_config.php.example
index 40afe22..7896a03 100644
--- a/htdocs/lg_config.php.example
+++ b/htdocs/lg_config.php.example
@@ -24,6 +24,43 @@ $_CONFIG['logo'] = 'lg_logo.gif';
*/
$_CONFIG['color'] = '#E48559';
+/*
+ * Enable reCAPTCHA v3
+ */
+$_CONFIG['recaptchaEnabled'] = false;
+
+/*
+ * reCAPTCHA v3 Frontend URL
+ */
+$_CONFIG['recaptchaFrontendURL'] = 'https://www.google.com/recaptcha/api.js?render=';
+
+/*
+ * reCAPTCHA v3 Backend Verify URL
+ */
+$_CONFIG['recaptchaBackendVerifyURL'] = 'https://www.google.com/recaptcha/api/siteverify';
+
+/*
+ * reCAPTCHA v3 Site Key
+ */
+$_CONFIG['recaptchaSiteKey'] = '';
+
+/*
+ * reCAPTCHA v3 Site Secret
+ */
+$_CONFIG['recaptchaSiteSecret'] = '';
+
+/*
+ * Should the LG show BGP peer information?
+ */
+$_CONFIG['showpeerinfo'] = 'TRUE';
+
+/*
+ * If 'showpeerinfo' above is TRUE, and you would like to show BGP peer information to visitors from a specific IPv4 address or subnet, add the IPv4 address or subnet (in CIDR format) to the array below
+ */
+$_CONFIG['safesubnets'] = array(
+ ''
+);
+
/*
* SSH authentication type (`password` or `privatekey`)
*/
@@ -57,12 +94,12 @@ $_CONFIG['ssh'] = '/usr/bin/sshpass';
/*
* URL address of the IP whois service
*/
-$_CONFIG['ipwhois'] = 'http://noc.hsdn.org/whois/';
+$_CONFIG['ipwhois'] = 'https://www.radb.net/query?keywords=';
/*
* URL address of the AS whois service
*/
-$_CONFIG['aswhois'] = 'http://noc.hsdn.org/aswhois/';
+$_CONFIG['aswhois'] = 'https://www.radb.net/query?keywords=';
/**
* Router nodes
@@ -74,6 +111,7 @@ $_CONFIG['aswhois'] = 'http://noc.hsdn.org/aswhois/';
* pingtraceurl - URL address for ping and traceroute tools (or FALSE)
* description - Node description
* group - Node group name (of FALSE)
+ * showpeerinfo - Should the LG show peer information? (TRUE / FALSE)
* ipv6 - Node supports IPv6 (TRUE/FALSE)
* os - Node OS (ios, mikrotik, quagga, junos)
*/
@@ -85,6 +123,7 @@ $_CONFIG['routers'] = array
'pingtraceurl' => FALSE,
'description' => 'Example Router 1',
'group' => 'AS12345',
+ 'showpeerinfo' => TRUE,
'ipv6' => TRUE,
'os' => 'ios',
),
@@ -95,6 +134,7 @@ $_CONFIG['routers'] = array
'pingtraceurl' => FALSE,
'description' => 'Example Router 2',
'group' => 'AS12345',
+ 'showpeerinfo' => FALSE,
'ipv6' => TRUE,
'os' => 'ios',
),
@@ -105,6 +145,7 @@ $_CONFIG['routers'] = array
'pingtraceurl' => FALSE,
'description' => 'Example Router 3',
'group' => 'AS12345',
+ 'showpeerinfo' => TRUE,
'ipv6' => TRUE,
'os' => 'mikrotik',
),
@@ -116,6 +157,7 @@ $_CONFIG['routers'] = array
'pingtraceurl' => FALSE,
'description' => 'Example Router 4',
'group' => 'AS12345',
+ 'showpeerinfo' => FALSE,
'ipv6' => TRUE,
'os' => 'mikrotik',
),
diff --git a/keys/.gitignore b/keys/.gitignore
deleted file mode 100644
index c96a04f..0000000
--- a/keys/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
\ No newline at end of file