diff --git a/chkip.py b/chkip.py index 4bcad8c..b0eb3b0 100644 --- a/chkip.py +++ b/chkip.py @@ -5,6 +5,7 @@ chkip.py – DNS- und Mailserver-Check-Tool Erstellt von Pascal Bouquet am 17.04.2025 +Aktualisiert am 19.04.2025 Dieses Programm ist freie Software: Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, @@ -20,6 +21,7 @@ Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht, siehe . """ + import sys import re import ipaddress @@ -28,6 +30,8 @@ import dns.reversename import requests import argparse import json +import socket +import subprocess # Resolver festlegen resolver = dns.resolver.Resolver() @@ -122,6 +126,43 @@ def resolve_tlsa(domain, mx_host): except: return "No TLSA record found" +def get_local_ipv4(): + try: + ip = next((ip for ip in resolver.nameservers if '.' in ip), '1.1.1.1') + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect((ip, 80)) + local_ip = s.getsockname()[0] + s.close() + return local_ip + except: + return "unavailable" + +def get_my_ip(): + def run_curl(protocol_flag): + try: + result = subprocess.run( + ["curl", "-s", protocol_flag, "ifconfig.me/ip"], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + timeout=2, + text=True + ) + return result.stdout.strip() + except: + return "unavailable" + + local_v4 = get_local_ipv4() + public_v4 = run_curl("-4") + public_v6 = run_curl("-6") + return local_v4, public_v4, public_v6 + +def is_cgnat(ip): + try: + ip_obj = ipaddress.ip_address(ip) + return ip_obj.is_private or ip_obj in ipaddress.ip_network("100.64.0.0/10") + except: + return False + def print_json(output): print(json.dumps(output, indent=2)) @@ -165,15 +206,29 @@ def print_text(output, is_ip_mode=False): def main(): parser = argparse.ArgumentParser(description="chkip.py – DNS- und Mailserver-Check-Tool") - parser.add_argument("domain", help="Domain oder IP-Adresse") + parser.add_argument("domain", nargs="?", help="Domain oder IP-Adresse") parser.add_argument("-sS", "--spf", action="store_true", help="Prüft den SPF-Eintrag") parser.add_argument("-sD", "--dmarc", action="store_true", help="Prüft den DMARC-Eintrag") parser.add_argument("-sM", "--mta_sts", action="store_true", help="Prüft den MTA-STS-Eintrag") parser.add_argument("-sT", "--tlsa", action="store_true", help="Prüft den TLSA-Eintrag") parser.add_argument("-sDK", "--dkim", type=str, help="Prüft den DKIM-Eintrag für den angegebenen Selector") parser.add_argument("--json", action="store_true", help="Ausgabe als JSON") + parser.add_argument("--me", action="store_true", help="Zeigt lokale & öffentliche IPs und prüft auf CGNAT") args = parser.parse_args() + if args.me: + local_v4, public_v4, public_v6 = get_my_ip() + print(f"Your local IPv4: {local_v4}") + print(f"Your public IPv4: {public_v4}") + print(f"Your public IPv6: {public_v6}") + if is_cgnat(public_v4): + print("⚠️ Hinweis: Du befindest dich möglicherweise hinter CGNAT (Carrier-Grade NAT)") + return + + if not args.domain: + parser.print_help() + return + domain = args.domain is_ip = is_ip_address(domain) output = {} @@ -192,7 +247,7 @@ def main(): print_json(output) else: print_text(output, is_ip_mode=True) - return # ✅ wichtig! + return # Domain-Zweig output["A"] = resolve_a(domain) or "No A record"