summaryrefslogtreecommitdiffstats
path: root/web-tools/bin
diff options
context:
space:
mode:
Diffstat (limited to 'web-tools/bin')
-rwxr-xr-xweb-tools/bin/bin/update24
-rw-r--r--web-tools/bin/index-test.html298
-rw-r--r--web-tools/bin/index.html298
-rwxr-xr-xweb-tools/bin/tools-test.py260
-rwxr-xr-xweb-tools/bin/tools.py260
5 files changed, 1140 insertions, 0 deletions
diff --git a/web-tools/bin/bin/update b/web-tools/bin/bin/update
new file mode 100755
index 0000000..4de2fd2
--- /dev/null
+++ b/web-tools/bin/bin/update
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ssh tools.bfh.info \
+ "cd /srv/tools.bfh.info/bin && \
+ git clean -dxf > /dev/null 2>&1 &&
+ git checkout -f HEAD &&
+ git pull --rebase"
diff --git a/web-tools/bin/index-test.html b/web-tools/bin/index-test.html
new file mode 100644
index 0000000..09861e4
--- /dev/null
+++ b/web-tools/bin/index-test.html
@@ -0,0 +1,298 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta name="author" content="bfh.info">
+ <meta name="description" content="tools.bfh.info">
+ <meta name="generator" content="bfh-linux-sysadmin@lists.bfh.science">
+
+ <title>tools.bfh.info</title>
+ <link rel="canonical" href="https://bfh.info">
+
+ <!-- Bootstrap core CSS -->
+ <link href="/_static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+
+ <!-- Custom styles for this template -->
+ <link href="/_static/dejavu-fonts/dejavu-fonts.css" rel="stylesheet">
+ <link href="/_static/fontawesome-pro/css/all.min.css" rel="stylesheet">
+
+ <link href="/_static/local/body.css" rel="stylesheet">
+ <link href="/_static/local/font.css" rel="stylesheet">
+ <link href="/_static/local/footer.css" rel="stylesheet">
+ </head>
+
+ <body>
+ <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
+ <a class="navbar-brand" href="/"><b>tools.bfh.info</b></a>
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsDefault" aria-controls="navbarsDefault" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+
+ <div class="collapse navbar-collapse" id="navbarsDefault">
+ <ul class="navbar-nav mr-auto">
+ </ul>
+ </div>
+ </nav>
+
+ <main role="main" class="container">
+
+ <div class="content">
+
+<!--
+Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org>
+
+SPDX-License-Identifier: GPL-3.0+
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<a name="top"></a>
+<h1><i class="fa-fw far fa-tools"></i> Network Tools<sup><small>TEST</small></sup> &nbsp;&nbsp;&nbsp; <small>(<a href="/api">API</a>)</small></h1>
+<div style="height: 2em"></div>
+
+<script src="/_static/jquery/jquery.min.js"></script>
+
+<script>
+ $(document).ready(function(){
+ $("[type=button]").click(function() {
+ var command = $(this).data("command");
+ var protocol = $("input[name='protocol']:checked").val();
+ var target = document.getElementById("target").value;
+ var cgi = command + "&protocol=" + protocol + "&target=" + target;
+ $.ajax({url: cgi, success: function(result){
+ $("#output").text(result);
+ document.getElementById('output-hidden').style.display = 'block';
+ $(document).scrollTop( $("#output").offset().top -125);
+ }});
+ });
+
+ $("[type=reset]").click(function() {
+ $("#dual-stack").click();
+ $('.btn-group').find('reset').removeClass('active')
+ .end().find('[type="reset"]').prop('checked', false);
+ document.getElementById('output-hidden').style.display = 'none';
+ $("#target").focus();
+ $("#target").prop('autofocus');
+ });
+ });
+</script>
+
+<style type="text/css">
+ label, [type="button"], [type="reset"], [type="text"] {
+ margin-top: 0.5em;
+ }
+</style>
+
+<form id="form">
+ <div class="form-group">
+ <div class="row">
+ <div class="col-md-6">
+ <b>Target</b>
+ <input id="target" placeholder="IP address/subnet, FQDN, ASN, Internet resources..." style="width: 100%;" type="text" autofocus />
+
+ <div style="height: 1em"></div>
+ </div>
+
+ <div class="col-md-6">
+ <b>Settings</b><br />
+ <input class="btn btn-light btn-sm" type="reset" value="Reset" />
+
+ <div class="btn-group btn-group-toggle" data-toggle="buttons">
+ <label class="btn btn-light btn-sm active">
+ <input type="radio" name="protocol" id="dual-stack" value="dual-stack" checked> Dual-stack
+ </label>
+ <label class="btn btn-light btn-sm">
+ <input type="radio" name="protocol" id="ipv4-only" value="ipv4-only"> IPv4-only
+ </label>
+ <label class="btn btn-light btn-sm">
+ <input type="radio" name="protocol" id="ipv6-only" value="ipv6-only"> IPv6-only
+ </label>
+ </div>
+
+ <div style="height: 1em"></div>
+ </div>
+ </div>
+ </div>
+</form>
+
+<hr />
+
+<div class="row">
+ <div class="col-md-6">
+ <b>Network</b><br />
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=ping">ping</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=traceroute">traceroute</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=tcptraceroute">tcptraceroute</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=whois">whois</button>
+
+ <div style="height: 1em"></div>
+
+ <b>Security</b><br />
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=nmap">nmap</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=testssl">testssl</button>
+
+ <div style="height: 1em"></div>
+
+ <b>other</b><br />
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=my-ip&target=none">My IP</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=my-browser&target=none">My browser</button>
+
+ <div style="height: 1em"></div>
+ </div>
+
+ <div class="col-md-6">
+ <b>DNS</b><br />
+ <small><b>Address-related records</b></small><br />
+ <button type="button" class="btn btn-primary" data-command="/bin/tools-test.py?command=kdig&query=ANY">ANY</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools-test.py?command=kdig&query=A">A</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools-test.py?command=kdig&query=AAAA">AAAA</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools-test.py?command=kdig&query=CNAME">CNAME</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools-test.py?command=kdig&query=DNAME">DNAME</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools-test.py?command=kdig&query=PTR">PTR</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>Informational records</b></small><br />
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=APL">APL</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=HINFO">HINFO</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=LOC">LOC</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=RP">RP</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=SOA">SOA</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=SRV">SRV</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools-test.py?command=kdig&query=TXT">TXT</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>DNSSEC records</b></small><br />
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools-test.py?command=kdig&query=CDNSKEY">CDNSKEY</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools-test.py?command=kdig&query=CDS">CDS</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools-test.py?command=kdig&query=DNSKEY">DNSKEY</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools-test.py?command=kdig&query=DS">DS</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools-test.py?command=kdig&query=RRSIG">RRSIG</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>Security-related records</b></small><br />
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=kdig&query=CAA">CAA</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=kdig&query=NSEC3">NSEC3</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=kdig&query=NSEC3PARAM">NSEC3PARAM</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=kdig&query=SSHFP">SSHFP</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools-test.py?command=kdig&query=TLSA">TLSA</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>other records and types</b></small><br />
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=kdig&query=AXFR">AXFR*</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=kdig&query=MX">MX</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools-test.py?command=kdig&query=NS">NS</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>Legacy records</b></small><br />
+ <button type="button" class="btn btn-danger" data-command="/bin/tools-test.py?command=kdig&query=NSEC">NSEC</button>
+ <button type="button" class="btn btn-danger" data-command="/bin/tools-test.py?command=kdig&query=SPF">SPF</button>
+
+ <div style="height: 1em"></div>
+ </div>
+</div>
+
+<div class="row">
+ <div class="col-md-6">
+ <small><b>Notes:</b>
+ <ul>
+ <li>testssl can take up to 5min (with currently no output until the end)</li>
+ </ul></small>
+
+ <div style="height: 1em"></div>
+ </div>
+
+ <div class="col-md-6">
+ <small><b>*</b> only available for BFH authoritative zones</small>
+
+ <div style="height: 1em"></div>
+ </div>
+</div>
+
+<hr />
+
+<div id="output-hidden" style="display: none;">
+<a name="output"></a>
+<a href="#top"><button type="button" class="btn btn-light btn-sm float-right">&uarr;</button></a><br />
+<b>Output</b><br />
+<pre>
+<textarea id="output" readonly rows="25" style="background: #f1f1f1; width: 100%;"></textarea>
+</pre>
+</div>
+
+<div style="height: 1em"></div>
+
+
+ </div>
+
+ </main><!-- /.container -->
+
+ <footer class="footer py-5">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <a href="https://www.bfh.ch"><img src="/logo.svg" style="height: 112.5px" /></a><br />
+ <br />
+ </div>
+ <div class="col-md-3">
+ <small>
+ <strong><i class="fa-fw fas fa-map-marker"></i> Address</strong><br />
+ <a class="text-muted" href="https://www.openstreetmap.org/search?query=Dammweg 3%2C 3013 Bern">Berner Fachhochschule<br />
+ IT-Services<br />
+ Team Linux &amp; Infrastructure Services<br />
+ Dammweg 3, CH-3013 Bern</a><br />
+ <br />
+ </small>
+ </div>
+ <div class="col-md-3">
+ <small>
+ <strong><i class="fa-fw fas fa-phone"></i> Phone</strong><br />
+ <a class="text-muted" href="#">+41 31 848 48 48</a><br />
+ <br />
+ <strong><i class="fa-fw fas fa-envelope"></i> Email</strong><br />
+ <a class="text-muted" href="mailto:bfh-linux-sysadmin@lists.bfh.science?subject=BFH.science:%20Feedback">bfh-linux-sysadmin@lists.bfh.science</a><br />
+ <br />
+ </small>
+ </div>
+ <div class="col-md-4">
+ <small>
+ <br />
+ <br />
+ <br />
+ <br />
+ <i class="fa-fw fas fa-copyright"></i> <a class="text-muted" href="https://bfh.science/other/legal">2021</a>
+ &nbsp; &nbsp;
+ <a style="color: inherit;" href="https://bfh.science/other/legal" title="Legal Information"><i class="fa-fw fas fa-balance-scale"></i></a> <a class="text-muted" href="https://bfh.science/other/legal" title="Legal Information">Legal Information</a>
+ &nbsp; &nbsp;
+ <a class="a-hover-red" href="https://git.bfh.info" title="Made with Love and Git"><i class="fa-fw fas fa-heart"></i></a> <a class="text-muted" href="https://git.bfh.info" title="Made with Love and Git">Source Code</a><br />
+ <br />
+ </small>
+ </div>
+ </div>
+ </div>
+ </footer>
+
+ <!-- Bootstrap core JS -->
+ <script src="/_static/popperjs/popper.min.js"></script>
+ <script src="/_static/bootstrap/js/bootstrap.min.js"></script>
+
+ <!-- Custom scripts for this template -->
+ <script src="/_static/local/table.js"></script>
+ </body>
+</html>
diff --git a/web-tools/bin/index.html b/web-tools/bin/index.html
new file mode 100644
index 0000000..c54f22f
--- /dev/null
+++ b/web-tools/bin/index.html
@@ -0,0 +1,298 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta name="author" content="bfh.info">
+ <meta name="description" content="tools.bfh.info">
+ <meta name="generator" content="bfh-linux-sysadmin@lists.bfh.science">
+
+ <title>tools.bfh.info</title>
+ <link rel="canonical" href="https://bfh.info">
+
+ <!-- Bootstrap core CSS -->
+ <link href="/_static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
+
+ <!-- Custom styles for this template -->
+ <link href="/_static/dejavu-fonts/dejavu-fonts.css" rel="stylesheet">
+ <link href="/_static/fontawesome-pro/css/all.min.css" rel="stylesheet">
+
+ <link href="/_static/local/body.css" rel="stylesheet">
+ <link href="/_static/local/font.css" rel="stylesheet">
+ <link href="/_static/local/footer.css" rel="stylesheet">
+ </head>
+
+ <body>
+ <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
+ <a class="navbar-brand" href="/"><b>tools.bfh.info</b></a>
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsDefault" aria-controls="navbarsDefault" aria-expanded="false" aria-label="Toggle navigation">
+ <span class="navbar-toggler-icon"></span>
+ </button>
+
+ <div class="collapse navbar-collapse" id="navbarsDefault">
+ <ul class="navbar-nav mr-auto">
+ </ul>
+ </div>
+ </nav>
+
+ <main role="main" class="container">
+
+ <div class="content">
+
+<!--
+Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org>
+
+SPDX-License-Identifier: GPL-3.0+
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<a name="top"></a>
+<h1><i class="fa-fw far fa-tools"></i> Network Tools<sup><small>beta</small></sup> &nbsp;&nbsp;&nbsp; <small>(<a href="/api">API</a>)</small></h1>
+<div style="height: 2em"></div>
+
+<script src="/_static/jquery/jquery.min.js"></script>
+
+<script>
+ $(document).ready(function(){
+ $("[type=button]").click(function() {
+ var command = $(this).data("command");
+ var protocol = $("input[name='protocol']:checked").val();
+ var target = document.getElementById("target").value;
+ var cgi = command + "&protocol=" + protocol + "&target=" + target;
+ $.ajax({url: cgi, success: function(result){
+ $("#output").text(result);
+ document.getElementById('output-hidden').style.display = 'block';
+ $(document).scrollTop( $("#output").offset().top -125);
+ }});
+ });
+
+ $("[type=reset]").click(function() {
+ $("#dual-stack").click();
+ $('.btn-group').find('reset').removeClass('active')
+ .end().find('[type="reset"]').prop('checked', false);
+ document.getElementById('output-hidden').style.display = 'none';
+ $("#target").focus();
+ $("#target").prop('autofocus');
+ });
+ });
+</script>
+
+<style type="text/css">
+ label, [type="button"], [type="reset"], [type="text"] {
+ margin-top: 0.5em;
+ }
+</style>
+
+<form id="form">
+ <div class="form-group">
+ <div class="row">
+ <div class="col-md-6">
+ <b>Target</b>
+ <input id="target" placeholder="IP address/subnet, FQDN, ASN, Internet resources..." style="width: 100%;" type="text" autofocus />
+
+ <div style="height: 1em"></div>
+ </div>
+
+ <div class="col-md-6">
+ <b>Settings</b><br />
+ <input class="btn btn-light btn-sm" type="reset" value="Reset" />
+
+ <div class="btn-group btn-group-toggle" data-toggle="buttons">
+ <label class="btn btn-light btn-sm active">
+ <input type="radio" name="protocol" id="dual-stack" value="dual-stack" checked> Dual-stack
+ </label>
+ <label class="btn btn-light btn-sm">
+ <input type="radio" name="protocol" id="ipv4-only" value="ipv4-only"> IPv4-only
+ </label>
+ <label class="btn btn-light btn-sm">
+ <input type="radio" name="protocol" id="ipv6-only" value="ipv6-only"> IPv6-only
+ </label>
+ </div>
+
+ <div style="height: 1em"></div>
+ </div>
+ </div>
+ </div>
+</form>
+
+<hr />
+
+<div class="row">
+ <div class="col-md-6">
+ <b>Network</b><br />
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=ping">ping</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=traceroute">traceroute</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=tcptraceroute">tcptraceroute</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=whois">whois</button>
+
+ <div style="height: 1em"></div>
+
+ <b>Security</b><br />
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=nmap">nmap</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=testssl">testssl</button>
+
+ <div style="height: 1em"></div>
+
+ <b>other</b><br />
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=my-ip&target=none">My IP</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=my-browser&target=none">My browser</button>
+
+ <div style="height: 1em"></div>
+ </div>
+
+ <div class="col-md-6">
+ <b>DNS</b><br />
+ <small><b>Address-related records</b></small><br />
+ <button type="button" class="btn btn-primary" data-command="/bin/tools.py?command=kdig&query=ANY">ANY</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools.py?command=kdig&query=A">A</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools.py?command=kdig&query=AAAA">AAAA</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools.py?command=kdig&query=CNAME">CNAME</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools.py?command=kdig&query=DNAME">DNAME</button>
+ <button type="button" class="btn btn-primary" data-command="/bin/tools.py?command=kdig&query=PTR">PTR</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>Informational records</b></small><br />
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=APL">APL</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=HINFO">HINFO</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=LOC">LOC</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=RP">RP</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=SOA">SOA</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=SRV">SRV</button>
+ <button type="button" class="btn btn-info" data-command="/bin/tools.py?command=kdig&query=TXT">TXT</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>DNSSEC records</b></small><br />
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools.py?command=kdig&query=CDNSKEY">CDNSKEY</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools.py?command=kdig&query=CDS">CDS</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools.py?command=kdig&query=DNSKEY">DNSKEY</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools.py?command=kdig&query=DS">DS</button>
+ <button type="button" class="btn btn-secondary" data-command="/bin/tools.py?command=kdig&query=RRSIG">RRSIG</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>Security-related records</b></small><br />
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=kdig&query=CAA">CAA</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=kdig&query=NSEC3">NSEC3</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=kdig&query=NSEC3PARAM">NSEC3PARAM</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=kdig&query=SSHFP">SSHFP</button>
+ <button type="button" class="btn btn-warning" data-command="/bin/tools.py?command=kdig&query=TLSA">TLSA</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>other records and types</b></small><br />
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=kdig&query=AXFR">AXFR*</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=kdig&query=MX">MX</button>
+ <button type="button" class="btn btn-success" data-command="/bin/tools.py?command=kdig&query=NS">NS</button>
+
+ <div style="height: 1em"></div>
+
+ <small><b>Legacy records</b></small><br />
+ <button type="button" class="btn btn-danger" data-command="/bin/tools.py?command=kdig&query=NSEC">NSEC</button>
+ <button type="button" class="btn btn-danger" data-command="/bin/tools.py?command=kdig&query=SPF">SPF</button>
+
+ <div style="height: 1em"></div>
+ </div>
+</div>
+
+<div class="row">
+ <div class="col-md-6">
+ <small><b>Notes:</b>
+ <ul>
+ <li>testssl can take up to 5min (with currently no output until the end)</li>
+ </ul></small>
+
+ <div style="height: 1em"></div>
+ </div>
+
+ <div class="col-md-6">
+ <small><b>*</b> only available for BFH authoritative zones</small>
+
+ <div style="height: 1em"></div>
+ </div>
+</div>
+
+<hr />
+
+<div id="output-hidden" style="display: none;">
+<a name="output"></a>
+<a href="#top"><button type="button" class="btn btn-light btn-sm float-right">&uarr;</button></a><br />
+<b>Output</b><br />
+<pre>
+<textarea id="output" readonly rows="25" style="background: #f1f1f1; width: 100%;"></textarea>
+</pre>
+</div>
+
+<div style="height: 1em"></div>
+
+
+ </div>
+
+ </main><!-- /.container -->
+
+ <footer class="footer py-5">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-2">
+ <a href="https://www.bfh.ch"><img src="/logo.svg" style="height: 112.5px" /></a><br />
+ <br />
+ </div>
+ <div class="col-md-3">
+ <small>
+ <strong><i class="fa-fw fas fa-map-marker"></i> Address</strong><br />
+ <a class="text-muted" href="https://www.openstreetmap.org/search?query=Dammweg 3%2C 3013 Bern">Berner Fachhochschule<br />
+ IT-Services<br />
+ Team Linux &amp; Infrastructure Services<br />
+ Dammweg 3, CH-3013 Bern</a><br />
+ <br />
+ </small>
+ </div>
+ <div class="col-md-3">
+ <small>
+ <strong><i class="fa-fw fas fa-phone"></i> Phone</strong><br />
+ <a class="text-muted" href="#">+41 31 848 48 48</a><br />
+ <br />
+ <strong><i class="fa-fw fas fa-envelope"></i> Email</strong><br />
+ <a class="text-muted" href="mailto:bfh-linux-sysadmin@lists.bfh.science?subject=BFH.science:%20Feedback">bfh-linux-sysadmin@lists.bfh.science</a><br />
+ <br />
+ </small>
+ </div>
+ <div class="col-md-4">
+ <small>
+ <br />
+ <br />
+ <br />
+ <br />
+ <i class="fa-fw fas fa-copyright"></i> <a class="text-muted" href="https://bfh.science/other/legal">2021</a>
+ &nbsp; &nbsp;
+ <a style="color: inherit;" href="https://bfh.science/other/legal" title="Legal Information"><i class="fa-fw fas fa-balance-scale"></i></a> <a class="text-muted" href="https://bfh.science/other/legal" title="Legal Information">Legal Information</a>
+ &nbsp; &nbsp;
+ <a class="a-hover-red" href="https://git.bfh.info" title="Made with Love and Git"><i class="fa-fw fas fa-heart"></i></a> <a class="text-muted" href="https://git.bfh.info" title="Made with Love and Git">Source Code</a><br />
+ <br />
+ </small>
+ </div>
+ </div>
+ </div>
+ </footer>
+
+ <!-- Bootstrap core JS -->
+ <script src="/_static/popperjs/popper.min.js"></script>
+ <script src="/_static/bootstrap/js/bootstrap.min.js"></script>
+
+ <!-- Custom scripts for this template -->
+ <script src="/_static/local/table.js"></script>
+ </body>
+</html>
diff --git a/web-tools/bin/tools-test.py b/web-tools/bin/tools-test.py
new file mode 100755
index 0000000..e804409
--- /dev/null
+++ b/web-tools/bin/tools-test.py
@@ -0,0 +1,260 @@
+#!/usr/bin/python3
+
+# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Dependencies:
+# sudo apt install iputils-ping traceroute whois nmap testssl.sh geoip-bin geoip-database knot-dnsutils
+
+from cgi import FieldStorage
+from datetime import datetime
+from ipaddress import ip_address
+from os import getenv
+from subprocess import Popen, PIPE
+from sys import exit
+
+def filter_nameservers(servers, protocol):
+ nameservers= []
+
+ for server in servers:
+ name = server.rstrip().rstrip('.')
+
+ if protocol == 'ipv6-only':
+ command = 'kdig -6'
+ options = ' -t AAAA +short -q '
+ elif protocol == 'ipv4-only':
+ command = 'kdig -4'
+ options = ' -t A +short -q '
+ else:
+ command = 'kdig'
+ options = ' +short -q '
+
+ command_line = (command + options + name).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ address = kdig.stdout.readline()
+
+ if address:
+ nameservers.append(name)
+
+ return nameservers
+
+def get_nameserver(name, protocol):
+ nameservers = []
+
+ if protocol == 'ipv6-only':
+ command = 'kdig -6'
+ elif protocol == 'ipv4-only':
+ command = 'kdig -4'
+ else:
+ command = 'kdig'
+
+ options = ' -t NS +short -q '
+
+ command_line = (command + options + name).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ servers = kdig.stdout.readlines()
+
+ count = 0
+ while not servers and count < 10:
+ name = name.split('.')
+ del name[0]
+ name = '.'.join(name)
+
+ command_line = (command + options + name).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ servers = kdig.stdout.readlines()
+
+ count += 1
+
+ names = []
+ for server in servers:
+ name = server.rstrip().decode('utf-8').rstrip('.')
+ names.append(name)
+
+ nameservers = filter_nameservers(names, protocol)
+ return nameservers
+
+def run_command(command):
+ process = Popen(command, stdout=PIPE)
+ empty_lines = 0
+ while True:
+ line = process.stdout.readline().rstrip()
+ if not line:
+ empty_lines = empty_lines + 1
+ if empty_lines > 2:
+ break
+ else:
+ print()
+ else:
+ empty_lines = 0
+ yield line.decode('utf-8')
+
+def main():
+ form = FieldStorage()
+
+ if form.getvalue("command"):
+ Command = form.getvalue("command").split()[0]
+
+ if "target" in form:
+ Target = form.getvalue("target").split()[0]
+
+ if "protocol" in form:
+ Protocol = form.getvalue("protocol").split()[0]
+
+ if "query" in form:
+ Query = form.getvalue("query").split()[0]
+
+ if Command and Protocol and Target:
+ print('Content-Type: text/html\n')
+
+ Date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+
+ if Command == 'kdig':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+
+ if Query == 'PTR':
+ arpa = ip_address(Target).reverse_pointer
+
+ nameserver = get_nameserver(arpa, Protocol)
+
+ protocol_passed = False
+
+ for server in nameserver:
+ check_options = options + ' @' + server + ' -t ' + Query + ' -q '
+
+ command_line = (Command + ' +short' + check_options + arpa).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ protocol_check = kdig.stdout.readline()
+
+ if protocol_check:
+ protocol_passed = True
+ break
+
+ if not protocol_passed:
+ print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n')
+ print('--')
+ print('Run: ' + str(command_line))
+ print('Date: ' + Date)
+
+ exit(0)
+
+ options = options + ' @' + server + ' -x '
+ else:
+ nameserver = get_nameserver(Target, Protocol)
+
+ protocol_passed = False
+
+ for server in nameserver:
+ check_options = options + ' @' + server + ' -t ' + Query + ' -q '
+
+ command_line = (Command + ' +short' + check_options + Target).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ protocol_check = kdig.stdout.readline()
+
+ if protocol_check:
+ protocol_passed = True
+ break
+
+ if not protocol_passed:
+ print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n')
+ print('--')
+ print('Run: ' + str(command_line))
+ print('Date: ' + Date)
+
+ exit(0)
+
+ options = options + ' @' + server + ' -t ' + Query + ' -q '
+ elif Command == 'ping':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+ options = options + ' -c3 '
+ elif Command == 'traceroute':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+ options = options + ' '
+ elif Command == 'tcptraceroute':
+ Command = 'traceroute'
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+ options = options + ' -T '
+ elif Command == 'nmap':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ else:
+ options = ' '
+ #-O -T5
+ elif Command == 'testssl':
+ options = ' --color 0 '
+ elif Command == 'whois':
+ options = ' -H '
+ else:
+ options = ' '
+
+ if Command == 'my-ip':
+ command_line = ''
+
+ address = getenv('REMOTE_ADDR')
+ print('IP address: ' + address)
+
+ # TODO: show reverse DNS
+
+ if ':' in address:
+ print('IP version: IPv6')
+ process = Popen(['geoiplookup6', address], stdout=PIPE)
+ else:
+ print('IP version: IPv4')
+ process = Popen(['geoiplookup', address], stdout=PIPE)
+
+ geoiplookup = process.stdout.readline().rstrip()
+ country = geoiplookup.decode('utf-8').split(':')[1]
+ print('Country:' + country + '\n\n')
+ elif Command == 'my-browser':
+ command_line = ''
+ print('User-Agent: ' + getenv('HTTP_USER_AGENT', 'n/a') + '\n\n')
+ else:
+ command_line = Command + options + Target
+
+ for path in run_command(command_line.split()):
+ print(path)
+
+ print('--')
+ print('Date: ' + Date)
+
+ if command_line:
+ print('Run: ' + command_line)
+
+ exit(0)
+
+if __name__ == '__main__':
+ main()
diff --git a/web-tools/bin/tools.py b/web-tools/bin/tools.py
new file mode 100755
index 0000000..bf1a067
--- /dev/null
+++ b/web-tools/bin/tools.py
@@ -0,0 +1,260 @@
+#!/usr/bin/python3
+
+# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org>
+#
+# SPDX-License-Identifier: GPL-3.0+
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Dependencies:
+# sudo apt install iputils-ping traceroute whois nmap testssl.sh geoip-bin geoip-database knot-dnsutils
+
+from cgi import FieldStorage
+from datetime import datetime
+import ipaddress
+from os import getenv
+from subprocess import Popen, PIPE
+from sys import exit
+
+def filter_nameservers(servers, protocol):
+ nameservers= []
+
+ for server in servers:
+ name = server.rstrip().rstrip('.')
+
+ if protocol == 'ipv6-only':
+ command = 'kdig -6'
+ options = ' -t AAAA +short -q '
+ elif protocol == 'ipv4-only':
+ command = 'kdig -4'
+ options = ' -t A +short -q '
+ else:
+ command = 'kdig'
+ options = ' +short -q '
+
+ command_line = (command + options + name).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ address = kdig.stdout.readline()
+
+ if address:
+ nameservers.append(name)
+
+ return nameservers
+
+def get_nameserver(name, protocol):
+ nameservers = []
+
+ if protocol == 'ipv6-only':
+ command = 'kdig -6'
+ elif protocol == 'ipv4-only':
+ command = 'kdig -4'
+ else:
+ command = 'kdig'
+
+ options = ' -t NS +short -q '
+
+ command_line = (command + options + name).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ servers = kdig.stdout.readlines()
+
+ count = 0
+ while not servers and count < 10:
+ name = name.split('.')
+ del name[0]
+ name = '.'.join(name)
+
+ command_line = (command + options + name).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ servers = kdig.stdout.readlines()
+
+ count += 1
+
+ names = []
+ for server in servers:
+ name = server.rstrip().decode('utf-8').rstrip('.')
+ names.append(name)
+
+ nameservers = filter_nameservers(names, protocol)
+ return nameservers
+
+def run_command(command):
+ process = Popen(command, stdout=PIPE)
+ empty_lines = 0
+ while True:
+ line = process.stdout.readline().rstrip()
+ if not line:
+ empty_lines = empty_lines + 1
+ if empty_lines > 2:
+ break
+ else:
+ print()
+ else:
+ empty_lines = 0
+ yield line.decode('utf-8')
+
+def main():
+ form = FieldStorage()
+
+ if form.getvalue("command"):
+ Command = form.getvalue("command").split()[0]
+
+ if "target" in form:
+ Target = form.getvalue("target").split()[0]
+
+ if "protocol" in form:
+ Protocol = form.getvalue("protocol").split()[0]
+
+ if "query" in form:
+ Query = form.getvalue("query").split()[0]
+
+ if Command and Protocol and Target:
+ print('Content-Type: text/html\n')
+
+ Date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+
+ if Command == 'kdig':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+
+ if Query == 'PTR':
+ arpa = ipaddress.ip_address(Target).reverse_pointer
+
+ nameserver = get_nameserver(arpa, Protocol)
+
+ protocol_passed = False
+
+ for server in nameserver:
+ check_options = options + ' @' + server + ' -t ' + Query + ' -q '
+
+ command_line = (Command + ' +short' + check_options + arpa).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ protocol_check = kdig.stdout.readline()
+
+ if protocol_check:
+ protocol_passed = True
+ break
+
+ if not protocol_passed:
+ print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n')
+ print('--')
+ print('Run: ' + str(command_line))
+ print('Date: ' + Date)
+
+ exit(0)
+
+ options = options + ' @' + server + ' -x '
+ else:
+ nameserver = get_nameserver(Target, Protocol)
+
+ protocol_passed = False
+
+ for server in nameserver:
+ check_options = options + ' @' + server + ' -t ' + Query + ' -q '
+
+ command_line = (Command + ' +short' + check_options + Target).split()
+ kdig = Popen(command_line, stdout=PIPE)
+ protocol_check = kdig.stdout.readline()
+
+ if protocol_check:
+ protocol_passed = True
+ break
+
+ if not protocol_passed:
+ print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n')
+ print('--')
+ print('Run: ' + str(command_line))
+ print('Date: ' + Date)
+
+ exit(0)
+
+ options = options + ' @' + server + ' -t ' + Query + ' -q '
+ elif Command == 'ping':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+ options = options + ' -c3 '
+ elif Command == 'traceroute':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+ options = options + ' '
+ elif Command == 'tcptraceroute':
+ Command = 'traceroute'
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ elif Protocol == 'ipv4-only':
+ options = ' -4'
+ else:
+ options = ''
+ options = options + ' -T '
+ elif Command == 'nmap':
+ if Protocol == 'ipv6-only':
+ options = ' -6'
+ else:
+ options = ' '
+ #-O -T5
+ elif Command == 'testssl':
+ options = ' --color 0 '
+ elif Command == 'whois':
+ options = ' -H '
+ else:
+ options = ' '
+
+ if Command == 'my-ip':
+ command_line = ''
+
+ ip_address = getenv('REMOTE_ADDR')
+ print('IP address: ' + ip_address)
+
+ # TODO: show reverse DNS
+
+ if ':' in ip_address:
+ print('IP version: IPv6')
+ process = Popen(['geoiplookup6', ip_address], stdout=PIPE)
+ else:
+ print('IP version: IPv4')
+ process = Popen(['geoiplookup', ip_address], stdout=PIPE)
+
+ geoiplookup = process.stdout.readline().rstrip()
+ country = geoiplookup.decode('utf-8').split(':')[1]
+ print('Country:' + country + '\n\n')
+ elif Command == 'my-browser':
+ command_line = ''
+ print('User-Agent: ' + getenv('HTTP_USER_AGENT', 'n/a') + '\n\n')
+ else:
+ command_line = Command + options + Target
+
+ for path in run_command(command_line.split()):
+ print(path)
+
+ print('--')
+ print('Date: ' + Date)
+
+ if command_line:
+ print('Run: ' + command_line)
+
+ exit(0)
+
+if __name__ == '__main__':
+ main()