mirror of
https://github.com/Astatin3/ip-hilbert.git
synced 2026-06-09 00:18:01 -06:00
Make this into more of a CLI thing. Also write some code
This commit is contained in:
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.12 (hilbert)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (hilbert)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/hilbert.iml" filepath="$PROJECT_DIR$/.idea/hilbert.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
import sys
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.colors as colors
|
||||||
|
from utils import *
|
||||||
|
|
||||||
|
order=16
|
||||||
|
grid_size=128
|
||||||
|
def line_chart(x,y ):
|
||||||
|
plt.plot(x, y)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def graph_density(ip_list: str):
|
||||||
|
xarr = []
|
||||||
|
yarr = []
|
||||||
|
for ip in ip_list:
|
||||||
|
try:
|
||||||
|
if ":" in ip:
|
||||||
|
ip = ip_to_int(ip.split(":")[0])
|
||||||
|
else:
|
||||||
|
ip = ip_to_int(ip)
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
continue
|
||||||
|
x, y = d2xy(2**order, ip)
|
||||||
|
xarr.append(x)
|
||||||
|
yarr.append(y)
|
||||||
|
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(64, 64))
|
||||||
|
|
||||||
|
# Create density grid
|
||||||
|
H, xedges, yedges = np.histogram2d(xarr, yarr, bins=grid_size, range=[[0, 2**order], [0, 2**order]])
|
||||||
|
|
||||||
|
# Plot heatmap
|
||||||
|
im = ax.imshow(H.T, cmap='YlOrRd', extent=[0, 2**order, 0, 2**order], origin='lower',
|
||||||
|
norm=colors.LogNorm(vmin=1, vmax=H.max()))
|
||||||
|
# Plot points
|
||||||
|
ax.scatter(xarr, yarr, color='blue', s=1, alpha=0.5)
|
||||||
|
|
||||||
|
ax.set_xlim(0, 2 ** order)
|
||||||
|
ax.set_ylim(0, 2 ** order)
|
||||||
|
|
||||||
|
# plt.colorbar(im, label='Number of IPs')
|
||||||
|
plt.axis('on')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def graph_ports(ip_list: str):
|
||||||
|
count = np.zeros(65536)
|
||||||
|
|
||||||
|
for ip in ip_list:
|
||||||
|
if not ":" in ip:
|
||||||
|
continue
|
||||||
|
port = int(ip.split(":")[1])
|
||||||
|
count[port] += 1
|
||||||
|
|
||||||
|
line_chart(np.arange(0, 65536), count)
|
||||||
|
|
||||||
|
|
||||||
|
def graph_nonstandard_ports(ip_list: str):
|
||||||
|
xarr = []
|
||||||
|
yarr = []
|
||||||
|
colorarr = []
|
||||||
|
for ip in ip_list:
|
||||||
|
try:
|
||||||
|
if ":" in ip:
|
||||||
|
split = ip.split(":")
|
||||||
|
ip = ip_to_int(split[0])
|
||||||
|
if split[1] == "25565":
|
||||||
|
colorarr.append('red')
|
||||||
|
else:
|
||||||
|
colorarr.append('blue')
|
||||||
|
|
||||||
|
else:
|
||||||
|
ip = ip_to_int(ip)
|
||||||
|
colorarr.append('green')
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
continue
|
||||||
|
x, y = d2xy(2**order, ip)
|
||||||
|
xarr.append(x)
|
||||||
|
yarr.append(y)
|
||||||
|
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(12, 12))
|
||||||
|
|
||||||
|
# Create density grid
|
||||||
|
H, xedges, yedges = np.histogram2d(xarr, yarr, bins=grid_size, range=[[0, 2**order], [0, 2**order]])
|
||||||
|
|
||||||
|
# Plot heatmap
|
||||||
|
im = ax.imshow(H.T, cmap='YlOrRd', extent=[0, 2**order, 0, 2**order], origin='lower',
|
||||||
|
norm=colors.LogNorm(vmin=1, vmax=H.max()))
|
||||||
|
# Plot points
|
||||||
|
ax.scatter(xarr, yarr, color=colorarr, s=1, alpha=0.5)
|
||||||
|
|
||||||
|
ax.set_xlim(0, 2 ** order)
|
||||||
|
ax.set_ylim(0, 2 ** order)
|
||||||
|
|
||||||
|
# plt.colorbar(im, label='Number of IPs')
|
||||||
|
plt.axis('on')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def random_choord(H):
|
||||||
|
weights = H.flatten()
|
||||||
|
|
||||||
|
weights = weights / np.sum(weights)
|
||||||
|
index = np.random.choice(grid_size*grid_size, p=weights)
|
||||||
|
x, y = divmod(index, grid_size)
|
||||||
|
|
||||||
|
x += np.random.random()
|
||||||
|
y += np.random.random()
|
||||||
|
|
||||||
|
x /= grid_size
|
||||||
|
y /= grid_size
|
||||||
|
|
||||||
|
x *= 2 ** order
|
||||||
|
y *= 2 ** order
|
||||||
|
|
||||||
|
return x, y
|
||||||
|
|
||||||
|
|
||||||
|
def generate_random_ips(ip_list: str, count: int):
|
||||||
|
xarr = []
|
||||||
|
yarr = []
|
||||||
|
for ip in ip_list:
|
||||||
|
try:
|
||||||
|
if ":" in ip:
|
||||||
|
split = ip.split(":")
|
||||||
|
ip = ip_to_int(split[0])
|
||||||
|
else:
|
||||||
|
ip = ip_to_int(ip)
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
continue
|
||||||
|
x, y = d2xy(2**order, ip)
|
||||||
|
xarr.append(x)
|
||||||
|
yarr.append(y)
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(12, 12))
|
||||||
|
|
||||||
|
H, xedges, yedges = np.histogram2d(xarr, yarr, bins=grid_size, range=[[0, 2**order], [0, 2**order]])
|
||||||
|
|
||||||
|
|
||||||
|
# x /= grid_size
|
||||||
|
# y /= grid_size
|
||||||
|
|
||||||
|
# ips = []
|
||||||
|
|
||||||
|
print(count)
|
||||||
|
|
||||||
|
for i in range(count):
|
||||||
|
x, y = random_choord(H)
|
||||||
|
d = xy2d(2**order, x, y)
|
||||||
|
ip = ip_int_to_ip(d)
|
||||||
|
print(ip)
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
import sys
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
import matplotlib.colors as colors
|
|
||||||
|
|
||||||
def hilbert_xy(ip_int, order=16):
|
|
||||||
"""Convert IP integer to (x,y) on a Hilbert curve of given order."""
|
|
||||||
x = y = 0
|
|
||||||
for i in range(order):
|
|
||||||
xi = (ip_int >> (2 * i)) & 1
|
|
||||||
yi = (ip_int >> (2 * i + 1)) & 1
|
|
||||||
|
|
||||||
if yi == 0:
|
|
||||||
if xi == 1:
|
|
||||||
x = (1 << order) - 1 - x
|
|
||||||
y = (1 << order) - 1 - y
|
|
||||||
x, y = y, x
|
|
||||||
|
|
||||||
x += xi << i
|
|
||||||
y += yi << i
|
|
||||||
|
|
||||||
return x, y
|
|
||||||
|
|
||||||
def ip_to_int(ip):
|
|
||||||
return int(''.join([bin(int(x) + 256)[3:] for x in ip.split('.')]), 2)
|
|
||||||
|
|
||||||
def create_hilbert_points(ip_list, order=16):
|
|
||||||
points = []
|
|
||||||
for ip in ip_list:
|
|
||||||
ip_int = ip_to_int(ip)
|
|
||||||
x, y = hilbert_xy(ip_int, order)
|
|
||||||
points.append((x, y))
|
|
||||||
return points
|
|
||||||
|
|
||||||
def visualize_hilbert_points(ip_list, order=16, grid_size=32):
|
|
||||||
points = create_hilbert_points(ip_list, order)
|
|
||||||
x, y = zip(*points)
|
|
||||||
|
|
||||||
fig, ax = plt.subplots(figsize=(12, 12))
|
|
||||||
|
|
||||||
# Create density grid
|
|
||||||
H, xedges, yedges = np.histogram2d(x, y, bins=grid_size, range=[[0, 2**order], [0, 2**order]])
|
|
||||||
|
|
||||||
# Plot heatmap
|
|
||||||
im = ax.imshow(H.T, cmap='YlOrRd', extent=[0, 2**order, 0, 2**order], origin='lower',
|
|
||||||
norm=colors.LogNorm(vmin=1, vmax=H.max()))
|
|
||||||
|
|
||||||
# Plot points
|
|
||||||
ax.scatter(x, y, color='blue', s=2, alpha=0.5)
|
|
||||||
|
|
||||||
ax.set_xlim(0, 2 ** order)
|
|
||||||
ax.set_ylim(0, 2 ** order)
|
|
||||||
|
|
||||||
plt.title(f"IP Addresses on Hilbert Curve (order {order}) with Density Heatmap")
|
|
||||||
plt.colorbar(im, label='Number of IPs')
|
|
||||||
plt.axis('off')
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
ip_list = open(sys.argv[1]).read().splitlines()
|
|
||||||
visualize_hilbert_points(ip_list)
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
def inverse_hilbert_xy(x, y, order=16):
|
|
||||||
"""Convert (x, y) on a Hilbert curve of given order to IP integer."""
|
|
||||||
ip_int = 0
|
|
||||||
for i in range(order - 1, -1, -1):
|
|
||||||
xi = (x >> i) & 1
|
|
||||||
yi = (y >> i) & 1
|
|
||||||
|
|
||||||
if yi == 0:
|
|
||||||
if xi == 1:
|
|
||||||
x, y = (1 << order) - 1 - y, (1 << order) - 1 - x
|
|
||||||
x, y = y, x
|
|
||||||
|
|
||||||
ip_int |= (xi << (2 * i)) | (yi << (2 * i + 1))
|
|
||||||
|
|
||||||
return ip_int
|
|
||||||
|
|
||||||
|
|
||||||
def ip_int_to_ip(ip_int):
|
|
||||||
"""Convert an integer IP address to a string IP address."""
|
|
||||||
return ".".join(str((ip_int >> i) & 0xFF) for i in [24, 16, 8, 0])
|
|
||||||
|
|
||||||
def generate_ip_ranges(size=16, order=16):
|
|
||||||
# for x in range(size):
|
|
||||||
# for y in range(size):
|
|
||||||
# x_pos = int((x/size)*(2 ** order)/2)
|
|
||||||
# y_pos = int((y/size)*(2 ** order)/2)
|
|
||||||
# ip = inverse_hilbert_xy(x_pos, y_pos, order=order)
|
|
||||||
# print(ip_int_to_ip(ip))
|
|
||||||
|
|
||||||
for x in range(256):
|
|
||||||
for y in range(256):
|
|
||||||
print(str(x)+"."+str(y)+".255.255")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
generate_ip_ranges()
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import utils
|
||||||
|
|
||||||
|
|
||||||
|
def process_ips(file_path, verbose=True):
|
||||||
|
ip_port_map = {}
|
||||||
|
ip_regex = r'(?P<ip>(?:\d{1,3}\.){3}\d{1,3})(?::(?P<port>\d{1,5}))?'
|
||||||
|
|
||||||
|
ip_count = 0
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print("Reading " + file_path)
|
||||||
|
|
||||||
|
with open(file_path, 'r') as file:
|
||||||
|
for line in file:
|
||||||
|
matches = re.finditer(ip_regex, line)
|
||||||
|
for match in matches:
|
||||||
|
ip = match.group('ip')
|
||||||
|
port = match.group('port')
|
||||||
|
|
||||||
|
ip_count += 1
|
||||||
|
|
||||||
|
if ip in ip_port_map:
|
||||||
|
if port:
|
||||||
|
ip_port_map[ip].add(port)
|
||||||
|
else:
|
||||||
|
ip_port_map[ip] = {port} if port else set()
|
||||||
|
|
||||||
|
unique_ips = []
|
||||||
|
for ip, ports in ip_port_map.items():
|
||||||
|
if ports: # Only add ports if they exist
|
||||||
|
for port in ports:
|
||||||
|
if port:
|
||||||
|
unique_ips.append(f"{ip}:{port}")
|
||||||
|
else:
|
||||||
|
unique_ips.append(ip)
|
||||||
|
else:
|
||||||
|
unique_ips.append(ip)
|
||||||
|
del ip_port_map
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print("Removed " + str(ip_count - len(unique_ips)) + " Duplicate IPs")
|
||||||
|
|
||||||
|
# removed_count = 0
|
||||||
|
# valid_ips = []
|
||||||
|
#
|
||||||
|
# for ip in unique_ips:
|
||||||
|
# if utils.is_valid_ip(ip):
|
||||||
|
# valid_ips.append(ip)
|
||||||
|
# else:
|
||||||
|
# removed_count += 1
|
||||||
|
# print(ip)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# del unique_ips
|
||||||
|
# print("Removed " + str(removed_count) + " invalid IPs")
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print("Retrieved " + str(len(unique_ips)) + " IPs")
|
||||||
|
|
||||||
|
return unique_ips
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import graphs
|
||||||
|
import ip_parser
|
||||||
|
order = 16
|
||||||
|
|
||||||
|
def printHelp():
|
||||||
|
print("""
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
./main.py <command> [options]
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
parse <input file>
|
||||||
|
graph_density <input file>
|
||||||
|
graph_ports <input file>
|
||||||
|
graph_nonstandard_ports <input file>
|
||||||
|
generate_random_ips <input file> <count>
|
||||||
|
""")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
argv = sys.argv
|
||||||
|
match argv[1]:
|
||||||
|
case 'parse':
|
||||||
|
for ip in ip_parser.process_ips(sys.argv[2], verbose=False):
|
||||||
|
print(ip)
|
||||||
|
case 'graph_density':
|
||||||
|
graphs.graph_density(ip_parser.process_ips(sys.argv[2]))
|
||||||
|
case 'graph_ports':
|
||||||
|
graphs.graph_ports(ip_parser.process_ips(sys.argv[2]))
|
||||||
|
case 'graph_nonstandard_ports':
|
||||||
|
graphs.graph_nonstandard_ports(ip_parser.process_ips(sys.argv[2]))
|
||||||
|
case 'generate_random_ips':
|
||||||
|
graphs.generate_random_ips(ip_parser.process_ips(sys.argv[2]), int(sys.argv[3]))
|
||||||
|
case _:
|
||||||
|
printHelp()
|
||||||
|
except Exception as e:
|
||||||
|
ex_type, ex, tb = sys.exc_info()
|
||||||
|
traceback.print_tb(tb)
|
||||||
|
print(str(e))
|
||||||
|
printHelp()
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
with open("./ips_1.txt") as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
for line in lines:
|
|
||||||
print(line.split("/")[1].split(":")[0].rstrip())
|
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# https://github.com/bonsaiviking/IPMap/blob/master/ipmap/hilbert.py
|
||||||
|
def xy2d(side_length: int, x: int, y: int):
|
||||||
|
"""Find the distance of the point (x, y) along a Hilbert curve
|
||||||
|
which fills a square *side_length* units on a side."""
|
||||||
|
y = side_length-y
|
||||||
|
s = side_length / 2
|
||||||
|
d = 0
|
||||||
|
while( s > 0 ):
|
||||||
|
rx = 1 if (int(x) & int(s)) else 0
|
||||||
|
ry = 1 if (int(y) & int(s)) else 0
|
||||||
|
d += s * s * ((3 * rx) ^ ry)
|
||||||
|
if (ry == 0):
|
||||||
|
if (rx == 1):
|
||||||
|
x = s-1 - x
|
||||||
|
y = s-1 - y
|
||||||
|
(x, y) = (y, x)
|
||||||
|
s /= 2
|
||||||
|
return int(d)
|
||||||
|
|
||||||
|
# https://github.com/bonsaiviking/IPMap/blob/master/ipmap/hilbert.py
|
||||||
|
def d2xy(side_length: int, d: int):
|
||||||
|
"""Find the coordinates (x, y) of a point some distance *d* along
|
||||||
|
a Hilbert curve which fills a square *side_length* units on a side."""
|
||||||
|
x = y = 0
|
||||||
|
s = 1
|
||||||
|
while( s < side_length ):
|
||||||
|
rx = 1 & int(d/2)
|
||||||
|
ry = 1 & (int(d) ^ rx)
|
||||||
|
if (ry == 0):
|
||||||
|
if (rx == 1):
|
||||||
|
x = s-1 - x
|
||||||
|
y = s-1 - y
|
||||||
|
(x, y) = (y, x)
|
||||||
|
x += s * rx
|
||||||
|
y += s * ry
|
||||||
|
d /= 4
|
||||||
|
s *= 2
|
||||||
|
|
||||||
|
# if y < 10000:
|
||||||
|
# print(ip_int_to_ip(int(d)))
|
||||||
|
|
||||||
|
return x, side_length-y
|
||||||
|
|
||||||
|
def ip_to_int(ip):
|
||||||
|
return int(''.join([bin(int(x) + 256)[3:] for x in ip.split('.')]), 2)
|
||||||
|
|
||||||
|
def ip_int_to_ip(ip_int):
|
||||||
|
return ".".join(str((ip_int >> i) & 0xFF) for i in [24, 16, 8, 0])
|
||||||
|
|
||||||
|
|
||||||
|
def ipInCIDR(ip: str, ip_CIDR: str):
|
||||||
|
range_parts = ip_CIDR.split('/')
|
||||||
|
range_mask = int(range_parts[1])
|
||||||
|
|
||||||
|
range_mask_num = (0xFFFFFFFF << (32 - range_mask)) & 0xFFFFFFFF
|
||||||
|
|
||||||
|
return (ip_to_int(ip) & range_mask_num) == (ip_to_int(range_parts[0]) & range_mask_num)
|
||||||
|
|
||||||
|
|
||||||
|
def ipInRange(ip: str, ip_range: str):
|
||||||
|
ip_int = ip_to_int(ip)
|
||||||
|
start_ip_int, end_ip_int = [ip_to_int(ip) for ip in ip_range.split('-')]
|
||||||
|
|
||||||
|
return start_ip_int <= ip_int <= end_ip_int
|
||||||
|
|
||||||
|
reserved_ip_blocks=[
|
||||||
|
"0.0.0.0/8",
|
||||||
|
"10.0.0.0/8",
|
||||||
|
"100.64.0.0/10",
|
||||||
|
"127.0.0.0/8",
|
||||||
|
"169.254.0.0/16",
|
||||||
|
"172.16.0.0/12",
|
||||||
|
"192.0.0.0/24",
|
||||||
|
"192.0.2.0/24",
|
||||||
|
"192.88.99.0/24",
|
||||||
|
"192.168.0.0/16",
|
||||||
|
"198.18.0.0/15",
|
||||||
|
"198.51.100.0/24",
|
||||||
|
"203.0.113.0/24",
|
||||||
|
"224.0.0.0/4",
|
||||||
|
"233.252.0.0/24",
|
||||||
|
"240.0.0.0/4",
|
||||||
|
"255.255.255.255/32"
|
||||||
|
]
|
||||||
|
|
||||||
|
def is_valid_ip(ip: str):
|
||||||
|
if ":" in ip:
|
||||||
|
ip = ip.split(":")[0]
|
||||||
|
|
||||||
|
for reserved_ip in reserved_ip_blocks:
|
||||||
|
if ipInCIDR(ip, reserved_ip):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
Reference in New Issue
Block a user