Wednesday, October 21, 2026

Python3 script for checking IPv6 Mostly Networks

 Python script to check if your IPv6 Mostly Network is running ok


--- cut here validate_mostly_v6.py ---


#!/usr/bin/env python3
import subprocess
import platform
import re
import sys

# Terminal output colors
GREEN = '\033[0;32m'
RED = '\033[0;31m'
YELLOW = '\033[1;33m'
NC = '\033[0m' # No Color

print("==================================================")
print(" Starting IPv6-Mostly Network Validation Test (Py)")
print("==================================================")

# Detect Host Operating System
OS_TYPE = platform.system() # 'Darwin' for macOS, 'Linux' for Linux

def run_command(command):
    """Utility to run system commands and return stdout as string."""
    try:
        result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        return result.stdout.strip()
    except Exception:
        return ""

def test_ping(command):
    """Utility to run ping tests and return Boolean success."""
    try:
        result = subprocess.run(command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return result.returncode == 0
    except Exception:
        return False


# --- TEST 1: Verify Global IPv6 Allocation ---
print("Test 1: Checking Global IPv6 Address... ", end="", flush=True)
if OS_TYPE == "Darwin":
    ifconfig_out = run_command("ifconfig en0 2>/dev/null")
    ipv6_addresses = re.findall(r'inet6\s+([a-fA-F0-9:]+)', ifconfig_out)
    # Filter out link-local (fe80) and loopback (::1)
    global_v6 = [ip for ip in ipv6_addresses if not ip.lower().startswith("fe80") and ip != "::1"]
else:
    ip_out = run_command("ip -6 addr show scope global 2>/dev/null")
    global_v6 = re.findall(r'inet6\s+([a-fA-F0-9:]+)', ip_out)

if global_v6:
    print(f"{GREEN}PASSED{NC} (Found: {' '.join(global_v6)})")
else:
    print(f"{RED}FAILED{NC} (No Global IPv6 address detected on the main interface)")


# --- TEST 2: Verify IPv6-Mostly / DHCPv4 Option 108 Behavior ---
print("Test 2: Checking DHCPv4 Option 108 & CLAT Status... ", end="", flush=True)
clat_active = False
real_ipv4_found = []

if OS_TYPE == "Darwin":
    ifconfig_out = run_command("ifconfig en0 2>/dev/null")
    # macOS flags 'clat46' or 'nat64' when Option 108 forces an IPv6-only state
    if "clat46" in ifconfig_out or "nat64" in ifconfig_out:
        clat_active = True
    
    ipv4_addresses = re.findall(r'inet\s+([0-9.]+)', ifconfig_out)
    # Filter out the 192.0.0.2 dummy address created locally by the macOS CLAT process
    real_ipv4_found = [ip for ip in ipv4_addresses if ip != "192.0.0.2" and ip != "127.0.0.1"]
else:
    ip_out = run_command("ip addr 2>/dev/null")
    if "clat" in ip_out:
        clat_active = True
    
    ip4_out = run_command("ip -4 addr show scope global 2>/dev/null")
    ipv4_addresses = re.findall(r'inet\s+([0-9.]+)', ip4_out)
    real_ipv4_found = [ip for ip in ipv4_addresses if ip != "192.0.0.2"]

if clat_active and not real_ipv4_found:
    print(f"{GREEN}PASSED{NC} (IPv6-Only Preferred active. Network IPv4 is disabled. Local CLAT active)")
elif real_ipv4_found:
    print(f"{YELLOW}WARNING{NC} (Real native IPv4 address found: {' '.join(real_ipv4_found)}. Option 108 might be missing or ignored)")
else:
    print(f"{RED}FAILED{NC} (Neither Option 108 behavior nor local CLAT was detected)")


# --- TEST 3: Native IPv6 Egress Connectivity ---
print("Test 3: Testing Native IPv6 Connectivity... ", end="", flush=True)
if test_ping("ping6 -c 2 2001:4860:4860::8888"):
    print(f"{GREEN}PASSED{NC}")
else:
    print(f"{RED}FAILED{NC} (Cannot reach Google IPv6 DNS via native routing)")


# --- TEST 4: OS-Level IPv4-Only Hostname Resolution ---
print("Test 4: Checking IPv4-only Resolution via CLAT/DNS64... ", end="", flush=True)
if test_ping("ping -c 2 ipv4.google.com"):
    print(f"{GREEN}PASSED{NC} (System successfully routes IPv4-only hostnames)")
else:
    print(f"{RED}FAILED{NC} (System cannot reach or resolve an IPv4-only hostname)")


# --- TEST 4b: Optional Network-Side DNS64 Synthesis Verification ---
print("Test 4b: Checking Optional Network-side DNS64 Synthesis... ", end="", flush=True)
dns_out = run_command("host -t AAAA ://google.com 2>/dev/null")

if "has AAAA address" in dns_out:
    synth_ips = re.findall(r'has AAAA address\s+([a-fA-F0-9:]+)', dns_out)
    print(f"{GREEN}ACTIVE{NC} (Network DNS is actively synthesizing AAAA records: {' '.join(synth_ips)})")
else:
    print(f"{YELLOW}NOT ACTIVE{NC} (Network DNS provides clean IPv4 records. Expected behavior for native CLAT)")


# --- TEST 5: Literal IPv4 Address Translation (End-to-End NAT64/CLAT) ---
print("Test 5: Testing NAT64/CLAT Translation (Ping to Literal IPv4)... ", end="", flush=True)
if test_ping("ping -c 2 8.8.8.8"):
    print(f"{GREEN}PASSED{NC} (End-to-end legacy IPv4 literal translation works perfectly)")
else:
    print(f"{RED}FAILED{NC} (Literal IPv4 traffic is blocked or translation gateway failed)")

print("==================================================")
print(" Validation Completed.")
print("==================================================")




--- cut here validate_mostly_v6.py ---


No comments:

Post a Comment