Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

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


Wednesday, April 29, 2026

fig.show() using Plotly does not work in jupyter

 Case:

  fig.show() using Plotly does not work in jupyter


What to do:

  Force rendering adding this line just before fig.show() using pio

  Example:

import plotly.io as pio

pio.renderers.default = 'iframe' 

fig.show()


Listo!

Monday, January 23, 2023

Python: reading a text file - character

Situation:

   Reading a text file in python3 (csv or txt) there is a character that can be appreciated using "more" in terminal but in python3 the situation is more complicated.


Example:

  $ more epa.csv

<U+FEFF>the text


Problem:

   Python3 reads the file well, it doesn't throw an error, but that invisible "character" remains in the variables, the texts, etc. and can cause some inconvenience.


Solution:

   The solution is to read the file and specify the encoding, something as simple as:


FILENAME="epa.csv"

with open(FILENAME, encoding='utf-8-sig') as file:

     for line in file:

         print(line)




Explanation (taken from: https://stackoverflow.com/questions/17912307/u-ufeff-in-python-string):


The Unicode character U+FEFF is the byte order mark, or BOM, and is used to tell the difference between big- and little-endian UTF-16 encoding.


Good luck,

Wednesday, June 30, 2021

Super easy script - Python3 & optimizing every table of a mysql db

 #!/usr/bin/python3.3

#The objetive of this script is to find all tables in a MYSQL DB and opmitize all of them

import dbconnect

import time

from datetime import datetime



## // VARIABLE DECLARATION ##//

startTime = datetime.now()

conn = dbconnect.dbconnect()

conn.autocommit(True)

cur = conn.cursor()


print ("Starting time: ", startTime)


SQLQUERY=("SHOW TABLES") #Find every table in the DB

cur.execute(SQLQUERY)

tables = cur.fetchall()



if len(tables)>0: #Prevent there are not tables in the list

  for table in tables:  #For every table in the DB

    try:

      SQLQUERY="OPTIMIZE TABLE "+ table[0]  #Construct the SQL QUERY

      print ("   Optimizing", table[0])

      cur.execute(SQLQUERY)

    except:

      pass


print ("Script execution time:",datetime.now()-startTime)

print ("Ending time: ", datetime.now())

print ("******** ****** ")

Tuesday, September 1, 2020

Tiny script: how to get the RRSIG DNS records with python3

 (I guess there are many other ways to do this, even more elegant)


import dns.resolver
domain='lacnic.net'
domain = dns.name.from_text(domain)
request = dns.message.make_query(domain, dns.rdatatype.ANY)
response = dns.query.tcp(request,'8.8.8.8')
#print(response)

for item in str(response).splitlines( ):
  if 'RRSIG' in item: print (item)


Friday, July 13, 2018

How to run Flask framework to listen in both IPv4 and IPv6 (DualStack)

Issue:
  How to run Flask framework to listen in both IPv4 and IPv6 (DualStack)

Answer:
  app.run(host='::',port=5005)


Monday, December 8, 2014

Python Script: Probably useless but functional IPv6 Network scanner

Below is the code of what is probably useless but a functional IPv6 host scanner written in Python using threading.

To perform a regular (brute force) network scans in an IPv6 Network is almost impossible it can take over 5.000 years to finish.

This project was purely academic and I just wanted to learn about threading in Python.

This software is not recommended for general usage.....

This  script  will call the OS to actually perform the ping

This software receives two parameters:
a) Prefix to scan in the format 2001:db8::/64 (subnet, not host)
b) Number of simultaneous processes it can run (MAXPINGS)

One more time it was purely academic stuff but hopefully it can make your day

Finally, AFAIK nmap does not yet support IPv6 network scan.

The code written in python3:

--- cut here ---

#!/usr/bin/python3

import threading
import sys
import ipaddress
import subprocess
import time

CURRENTPINGS=0 # Number of simultaneous ping at a time

def DOPING6(IPv6ADDRESS):
  global MAXPINGS, CURRENTPINGS
  CURRENTPINGS+=1
  CMD="ping6 -c 3 "+str(IPv6ADDRESS) + " 2> /dev/null > /dev/null"
  return_code = subprocess.call(CMD, shell=True)
  if return_code == 0:  #If ping was succesful
    print (IPv6ADDRESS," is alive")
 
  CURRENTPINGS-=1
 
def main():
  global MAXPINGS, CURRENTPINGS
  if len(sys.argv) != 3: #Validate how many parameters we are receiving
    print("  Not enough or too many parameter")
    print("  Usage: ./scanipv6.py IPv6Prefix/lenght MAXPINGS")
    print("  Example: ./scanipv6.py 2001:db8::/64 20")
    print("  Prefix lenght can be between 64-128")
    print("  MAXPINGS corresponds to how many pings will be running at the same time")
    exit()

  SUBNET,MASK=sys.argv[1].split("/")
  MAXPINGS=int(sys.argv[2])

  for addr in ipaddress.IPv6Network(sys.argv[1]):  #Let's loop for each address in the Block
    ping_thread=threading.Thread(target=DOPING6,args=(addr,))

    while CURRENTPINGS >= MAXPINGS: # With this while we make it possible to run max simultaneous pings
      time.sleep(1)  # Let's wait one second before proceeding
      #print ("Interrumping...., CURRENTPINGS > MAXPINGS") #Uncomment this line just for debugging

    ping_thread.start()

main()