Skip to content

Instantly share code, notes, and snippets.

@Grynn
Last active April 12, 2024 13:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Grynn/cb47f73618df001b6b3f5ada99cd2ccb to your computer and use it in GitHub Desktop.
Save Grynn/cb47f73618df001b6b3f5ada99cd2ccb to your computer and use it in GitHub Desktop.
Show all IP addresses with scope in a nice table format
#!/usr/bin/env python
import sys
import os
import json
import pandas as pd
import ipaddress
private_ranges = [
ipaddress.IPv4Network("10.0.0.0/8"),
ipaddress.IPv4Network("172.16.0.0/12"),
ipaddress.IPv4Network("192.168.0.0/16"),
ipaddress.IPv4Network("127.0.0.0/8"),
ipaddress.IPv6Network("::1/128"),
ipaddress.IPv6Network("fc00::/7"),
]
special_ranges = [
ipaddress.IPv4Network("100.64.0.0/10")
]
scope_priority = {
"global": 1,
"tailscale": 2,
"bogon": 3,
"local": 4
}
def is_special(ip_str):
try:
ip_obj = ipaddress.ip_address(ip_str)
except ValueError:
print(f"Invalid IP address: {ip_str}")
return None
for network in special_ranges:
if ip_obj in network:
return True
return False
def is_bogon(ip_str):
"""
Determines if an IP address is local (non-routable, aka bogon) or global.
Args:
ip_str (str): The IP address to check.
Returns:
bool: True if the IP address is local, False if it's global.
"""
try:
ip_obj = ipaddress.ip_address(ip_str)
except ValueError:
print(f"Invalid IP address: {ip_str}")
return None
for network in private_ranges:
if ip_obj in network:
return True
return False
def main():
# run ip --json address list and parse the output
cmd = "ip --json address list"
result = os.popen(cmd).read()
# parse result as JSON
data = json.loads(result)
# make a dataframe with the following columns: interface, ip, prefixlen, scope
rows = []
for interface in data:
for addr in interface['addr_info']:
scope = addr["scope"]
ip_addr_str = addr["local"]
prefixlen = addr["prefixlen"]
if scope == "global":
if is_bogon(ip_addr_str): scope = "bogon"
if is_special(ip_addr_str): scope = "tailscale"
rows.append({
"interface": interface['ifname'],
"ip": f"{ip_addr_str}/{prefixlen}",
"scope": scope})
df = pd.DataFrame(rows, columns=["interface", "ip", "scope"])
# print the dataframe sorted by scope (global, then bogon, then local)
print(df.sort_values(by="scope", key=lambda x: x.map(scope_priority)))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment