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 ---


Humble bash script to check your IPv6 Mostly Network

Imagine you connect to an IPv6 Mostly Network, is it ok?


--- cut here validate_mostly_v6.sh ---

 

#!/bin/bash


# Terminal output colors

GREEN='\033[0;32m'

RED='\033[0;31m'

YELLOW='\033[1;33m'

NC='\033[0m' # No Color


echo "=================================================="

echo " Starting IPv6-Mostly Network Validation Test"

echo "=================================================="


# Detect Host Operating System

OS="$(uname)"


# --- TEST 1: Verify Global IPv6 Allocation ---

echo -n "Test 1: Checking Global IPv6 Address... "

if [ "$OS" = "Darwin" ]; then

    # macOS network interface scanning

    IPV6_GBL=$(ifconfig en0 2>/dev/null | grep 'inet6 ' | grep -v 'fe80::' | grep -v '::1' | awk '{print $2}')

else

    # Linux network interface scanning

    IPV6_GBL=$(ip -6 addr show scope global | grep 'inet6' | awk '{print $2}')

fi


if [ -n "$IPV6_GBL" ]; then

    echo -e "${GREEN}PASSED${NC} (Found: $(echo $IPV6_GBL | tr '\n' ' '))"

else

    echo -e "${RED}FAILED${NC} (No Global IPv6 address detected on the main interface)"

fi



# --- TEST 2: Verify IPv6-Mostly / DHCPv4 Option 108 Behavior ---

echo -n "Test 2: Checking DHCPv4 Option 108 & CLAT Status... "

if [ "$OS" = "Darwin" ]; then

    # macOS flags 'clat46' or 'nat64' when Option 108 forces an IPv6-only state with translation

    CLAT_CHECK=$(ifconfig en0 2>/dev/null | grep -E 'clat46|nat64')

    # Filter out the 192.0.0.2 dummy address created locally by the macOS CLAT process

    IPV4_REAL=$(ifconfig en0 2>/dev/null | grep 'inet ' | grep -v '192.0.0.2')

else

    # Linux native CLAT or node state verification

    CLAT_CHECK=$(ip addr 2>/dev/null | grep 'clat')

    IPV4_REAL=$(ip -4 addr show scope global 2>/dev/null | grep 'inet' | grep -v '192.0.0.2')

fi


if [ -n "$CLAT_CHECK" ] && [ -z "$IPV4_REAL" ]; then

    echo -e "${GREEN}PASSED${NC} (IPv6-Only Preferred active. Network IPv4 is disabled. Local CLAT active)"

elif [ -n "$IPV4_REAL" ]; then

    echo -e "${YELLOW}WARNING${NC} (Real native IPv4 address found: $IPV4_REAL. Option 108 might be missing or ignored)"

else

    echo -e "${RED}FAILED${NC} (Neither Option 108 behavior nor local CLAT was detected)"

fi



# --- TEST 3: Native IPv6 Egress Connectivity ---

echo -n "Test 3: Testing Native IPv6 Connectivity... "

# Sending ICMPv6 packets to Google Public DNS to verify native routing

if ping6 -c 2 2001:4860:4860::8888 > /dev/null 2>&1; then

    echo -e "${GREEN}PASSED${NC}"

else

    echo -e "${RED}FAILED${NC} (Cannot reach Google IPv6 DNS via native routing)"

fi



# --- TEST 4: OS-Level IPv4-Only Hostname Resolution ---

echo -n "Test 4: Checking IPv4-only Resolution via CLAT/DNS64... "

# Verifies if the OS subsystem can resolve and route an IPv4-only domain name natively

if ping -c 2 ://google.com > /dev/null 2>&1; then

    echo -e "${GREEN}PASSED${NC} (System successfully routes IPv4-only hostnames)"

else

    echo -e "${RED}FAILED${NC} (System cannot reach or resolve an IPv4-only hostname)"

fi



# --- TEST 4b: Optional Network-Side DNS64 Synthesis Verification ---

echo -n "Test 4b: Checking Optional Network-side DNS64 Synthesis... "

# Querying the network DNS server directly for a AAAA record on an IPv4-only target.

# Per RFC 8925, DNS64 is optional if the client runs a local CLAT (464XLAT) environment.

DNS64_SYNTH=$(host -t AAAA ://google.com 2>/dev/null | grep 'has AAAA address')


if [ -n "$DNS64_SYNTH" ]; then

    SYNTH_IP=$(echo "$DNS64_SYNTH" | awk '{print $NF}')

    echo -e "${GREEN}ACTIVE${NC} (Network DNS is actively synthesizing AAAA records: $SYNTH_IP)"

else

    echo -e "${YELLOW}NOT ACTIVE${NC} (Network DNS provides clean IPv4 records. Expected behavior for native CLAT)"

fi



# --- TEST 5: Literal IPv4 Address Translation (End-to-End NAT64/CLAT) ---

echo -n "Test 5: Testing NAT64/CLAT Translation (Ping to Literal IPv4)... "

# Sending a ping to a literal IPv4 address. 

# Success proves that the local CLAT engine successfully translates and encapsulates legacy raw IPv4 traffic into IPv6

if ping -c 2 8.8.8.8 > /dev/null 2>&1; then

    echo -e "${GREEN}PASSED${NC} (End-to-end legacy IPv4 literal translation works perfectly)"

else

    echo -e "${RED}FAILED${NC} (Literal IPv4 traffic is blocked or translation gateway failed)"

fi


echo "=================================================="

echo " Validation Completed."

echo "=================================================="



--- cut here validate_mostly_v6.sh ---