Add --me flag to display local and public IPs with CGNAT detection

This commit introduces the --me flag, which allows users to quickly display
their current local IPv4 and public IPv4/IPv6 addresses.

The public IPs are retrieved using ifconfig.me via curl, ensuring accurate
detection even in CGNAT or split-DNS scenarios. Local IPv4 is determined
via the system's active route through the configured resolver.

The output also includes a CGNAT detection based on private IP ranges and
the reserved 100.64.0.0/10 block, providing a helpful warning if detected.

IPv6 privacy extensions are common, so local IPv6 detection has been removed
to avoid redundant or unstable information.
This commit is contained in:
Pascal Bouquet 2025-04-19 16:39:54 +02:00
parent 7058e26be3
commit fb00a11bef

View File

@ -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 <https://www.gnu.org/licenses/>.
"""
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"