#!/usr/bin/python3 # Copyright (C) 2013-2021 Daniel Baumann # # 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 . # 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()