yougotmapped 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yougotmapped/cli.py +181 -138
- yougotmapped/utils/anonymity.py +68 -34
- yougotmapped/utils/bandwidth.py +54 -0
- yougotmapped/utils/dependencies.py +46 -24
- yougotmapped/utils/ingress.py +67 -0
- yougotmapped/utils/jitter.py +78 -0
- yougotmapped/utils/mapping.py +90 -39
- yougotmapped/utils/mss.py +132 -0
- yougotmapped/utils/mtu.py +81 -0
- yougotmapped/utils/network.py +81 -20
- yougotmapped/utils/output.py +61 -48
- yougotmapped/utils/ping.py +90 -39
- yougotmapped/utils/trace.py +73 -48
- yougotmapped-1.1.0.dist-info/METADATA +196 -0
- yougotmapped-1.1.0.dist-info/RECORD +21 -0
- {yougotmapped-1.0.1.dist-info → yougotmapped-1.1.0.dist-info}/WHEEL +1 -1
- {yougotmapped-1.0.1.dist-info → yougotmapped-1.1.0.dist-info}/licenses/LICENSE +3 -9
- yougotmapped/utils/token.py +0 -31
- yougotmapped-1.0.1.dist-info/METADATA +0 -133
- yougotmapped-1.0.1.dist-info/RECORD +0 -17
- {yougotmapped-1.0.1.dist-info → yougotmapped-1.1.0.dist-info}/entry_points.txt +0 -0
- {yougotmapped-1.0.1.dist-info → yougotmapped-1.1.0.dist-info}/top_level.txt +0 -0
yougotmapped/utils/output.py
CHANGED
|
@@ -1,67 +1,80 @@
|
|
|
1
|
-
# utils/output.py
|
|
2
1
|
import json
|
|
3
2
|
import csv
|
|
3
|
+
from pathlib import Path
|
|
4
4
|
from io import StringIO
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
def _flatten_dict(data: dict, parent_key: str = "", sep: str = "_") -> dict:
|
|
8
|
+
items = {}
|
|
9
|
+
|
|
10
|
+
for key, value in data.items():
|
|
11
|
+
new_key = f"{parent_key}{sep}{key}" if parent_key else key
|
|
12
|
+
|
|
13
|
+
if isinstance(value, dict):
|
|
14
|
+
items.update(_flatten_dict(value, new_key, sep=sep))
|
|
15
|
+
else:
|
|
16
|
+
items[new_key] = value
|
|
17
|
+
|
|
18
|
+
return items
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def format_normal(results: list[dict]) -> str:
|
|
22
|
+
blocks = []
|
|
23
|
+
|
|
24
|
+
for entry in results:
|
|
10
25
|
lines = []
|
|
11
|
-
for key, value in
|
|
26
|
+
for key, value in entry.items():
|
|
12
27
|
if isinstance(value, dict):
|
|
13
|
-
lines.append(f"{key
|
|
28
|
+
lines.append(f"{key}:")
|
|
14
29
|
for sub_key, sub_val in value.items():
|
|
15
|
-
lines.append(f" {sub_key
|
|
30
|
+
lines.append(f" {sub_key}: {sub_val}")
|
|
16
31
|
else:
|
|
17
|
-
lines.append(f"{key
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"""
|
|
28
|
-
flat = {}
|
|
29
|
-
for key, value in entry.items():
|
|
30
|
-
if isinstance(value, dict):
|
|
31
|
-
for sub_key, sub_val in value.items():
|
|
32
|
-
flat[f"{key}_{sub_key}"] = sub_val
|
|
33
|
-
else:
|
|
34
|
-
flat[key] = value
|
|
35
|
-
return flat
|
|
32
|
+
lines.append(f"{key}: {value}")
|
|
33
|
+
|
|
34
|
+
blocks.append("\n".join(lines))
|
|
35
|
+
blocks.append("-" * 40)
|
|
36
|
+
|
|
37
|
+
return "\n".join(blocks)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def format_json(results: list[dict]) -> str:
|
|
41
|
+
return json.dumps(results, indent=4)
|
|
36
42
|
|
|
37
43
|
|
|
38
|
-
def
|
|
39
|
-
if not
|
|
44
|
+
def format_csv(results: list[dict]) -> str:
|
|
45
|
+
if not results:
|
|
40
46
|
return ""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
|
|
48
|
+
flattened = [_flatten_dict(r) for r in results]
|
|
49
|
+
|
|
50
|
+
fieldnames = sorted(
|
|
51
|
+
{key for entry in flattened for key in entry.keys()}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
buffer = StringIO()
|
|
55
|
+
writer = csv.DictWriter(buffer, fieldnames=fieldnames)
|
|
46
56
|
writer.writeheader()
|
|
47
|
-
for d in flat_data:
|
|
48
|
-
writer.writerow(d)
|
|
49
|
-
return output.getvalue()
|
|
50
57
|
|
|
58
|
+
for entry in flattened:
|
|
59
|
+
writer.writerow(entry)
|
|
60
|
+
|
|
61
|
+
return buffer.getvalue()
|
|
51
62
|
|
|
52
|
-
def format_as_json(data):
|
|
53
|
-
return json.dumps(data, indent=4)
|
|
54
63
|
|
|
64
|
+
def write_output(
|
|
65
|
+
results: list[dict],
|
|
66
|
+
path: str | Path,
|
|
67
|
+
fmt: str = "normal",
|
|
68
|
+
) -> Path:
|
|
69
|
+
fmt = fmt.lower()
|
|
70
|
+
path = Path(path).resolve()
|
|
55
71
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
elif fmt_type == "json":
|
|
61
|
-
formatted = format_as_json(data)
|
|
72
|
+
if fmt == "json":
|
|
73
|
+
content = format_json(results)
|
|
74
|
+
elif fmt == "csv":
|
|
75
|
+
content = format_csv(results)
|
|
62
76
|
else:
|
|
63
|
-
|
|
77
|
+
content = format_normal(results)
|
|
64
78
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
print(f"Output saved to {file_path} in {fmt_type.upper()} format.")
|
|
79
|
+
path.write_text(content, encoding="utf-8")
|
|
80
|
+
return path
|
yougotmapped/utils/ping.py
CHANGED
|
@@ -1,56 +1,107 @@
|
|
|
1
|
-
# utils/pings.py
|
|
2
1
|
from ping3 import ping
|
|
3
2
|
import statistics
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
4
|
+
|
|
5
|
+
FIBER_SPEED_KM_PER_MS = 200 # physical upper bound
|
|
6
|
+
REAL_WORLD_FACTOR = 0.5 # routing + overhead penalty
|
|
7
|
+
EFFECTIVE_SPEED = FIBER_SPEED_KM_PER_MS * REAL_WORLD_FACTOR
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def estimate_distance_km(rtt_ms: float) -> tuple[int, int, int]:
|
|
11
|
+
one_way_ms = rtt_ms / 2
|
|
12
|
+
|
|
13
|
+
estimated = one_way_ms * EFFECTIVE_SPEED
|
|
14
|
+
|
|
15
|
+
min_km = int(estimated * 0.7)
|
|
16
|
+
max_km = int(estimated * 1.3)
|
|
17
|
+
|
|
18
|
+
return int(min_km), int(estimated), int(max_km)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def classify_latency(rtt_ms: float) -> str:
|
|
22
|
+
if rtt_ms < 1:
|
|
23
|
+
return "Loopback or same-host"
|
|
24
|
+
if rtt_ms < 5:
|
|
25
|
+
return "Local network / same building"
|
|
26
|
+
if rtt_ms < 20:
|
|
27
|
+
return "Metro or nearby region"
|
|
28
|
+
if rtt_ms < 50:
|
|
29
|
+
return "Regional / same country"
|
|
30
|
+
if rtt_ms < 100:
|
|
31
|
+
return "Inter-country"
|
|
32
|
+
if rtt_ms < 200:
|
|
33
|
+
return "Intercontinental"
|
|
34
|
+
return "Very distant or routed via relay/VPN"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def ping_target(host: str, count: int = 5, timeout: float = 1.0) -> dict:
|
|
27
38
|
latencies = []
|
|
28
39
|
|
|
29
40
|
for _ in range(count):
|
|
30
41
|
try:
|
|
31
|
-
delay = ping(host, timeout=
|
|
32
|
-
if delay:
|
|
33
|
-
latencies.append(delay)
|
|
42
|
+
delay = ping(host, timeout=timeout)
|
|
43
|
+
if delay is not None:
|
|
44
|
+
latencies.append(delay * 1000) # ms
|
|
34
45
|
except Exception:
|
|
35
46
|
continue
|
|
36
47
|
|
|
48
|
+
sent = count
|
|
37
49
|
received = len(latencies)
|
|
38
|
-
lost =
|
|
50
|
+
lost = sent - received
|
|
39
51
|
|
|
40
52
|
if received == 0:
|
|
41
|
-
return
|
|
53
|
+
return {
|
|
54
|
+
"reachable": False,
|
|
55
|
+
"sent": sent,
|
|
56
|
+
"received": 0,
|
|
57
|
+
"packet_loss_percent": 100.0,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
min_rtt = round(min(latencies), 2)
|
|
61
|
+
avg_rtt = round(statistics.mean(latencies), 2)
|
|
62
|
+
med_rtt = round(statistics.median(latencies), 2)
|
|
63
|
+
max_rtt = round(max(latencies), 2)
|
|
64
|
+
|
|
65
|
+
min_km, est_km, max_km = estimate_distance_km(med_rtt)
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
"reachable": True,
|
|
69
|
+
"sent": sent,
|
|
70
|
+
"received": received,
|
|
71
|
+
"packet_loss_percent": round((lost / sent) * 100, 1),
|
|
72
|
+
"rtt_ms": {
|
|
73
|
+
"min": min_rtt,
|
|
74
|
+
"avg": avg_rtt,
|
|
75
|
+
"median": med_rtt,
|
|
76
|
+
"max": max_rtt,
|
|
77
|
+
},
|
|
78
|
+
"distance_km": {
|
|
79
|
+
"estimated": est_km,
|
|
80
|
+
"min": min_km,
|
|
81
|
+
"max": max_km,
|
|
82
|
+
},
|
|
83
|
+
"classification": classify_latency(med_rtt),
|
|
84
|
+
}
|
|
42
85
|
|
|
43
|
-
avg_latency_ms = round(statistics.mean(latencies) * 1000, 2)
|
|
44
|
-
packet_loss = round((lost / count) * 100, 1)
|
|
45
86
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
87
|
+
def format_ping_result(result: dict) -> None:
|
|
88
|
+
if not result.get("reachable"):
|
|
89
|
+
print("Host unreachable (100% packet loss)")
|
|
90
|
+
return
|
|
49
91
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
f"
|
|
92
|
+
print(f"Packets: sent={result['sent']} received={result['received']}")
|
|
93
|
+
print(f"Packet loss: {result['packet_loss_percent']}%")
|
|
94
|
+
|
|
95
|
+
rtt = result["rtt_ms"]
|
|
96
|
+
print(
|
|
97
|
+
f"RTT (ms): min={rtt['min']} avg={rtt['avg']} "
|
|
98
|
+
f"median={rtt['median']} max={rtt['max']}"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
dist = result["distance_km"]
|
|
102
|
+
print(
|
|
103
|
+
f"Estimated distance: ~{dist['estimated']} km "
|
|
104
|
+
f"(range {dist['min']}–{dist['max']} km)"
|
|
56
105
|
)
|
|
106
|
+
|
|
107
|
+
print(f"Inference: {result['classification']}")
|
yougotmapped/utils/trace.py
CHANGED
|
@@ -1,70 +1,95 @@
|
|
|
1
|
-
# utils/trace.py
|
|
2
1
|
import subprocess
|
|
3
2
|
import platform
|
|
4
|
-
import re
|
|
5
3
|
import ipaddress
|
|
6
|
-
|
|
4
|
+
import re
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
system = platform.system()
|
|
10
|
-
if system == "Windows":
|
|
11
|
-
cmd = ["tracert", "-h", str(max_hops), host]
|
|
12
|
-
elif system in ["Linux", "Darwin"]:
|
|
13
|
-
cmd = ["traceroute", "-m", str(max_hops), "-w", "1", host]
|
|
14
|
-
else:
|
|
15
|
-
return f"Traceroute not supported on {system}"
|
|
6
|
+
from yougotmapped.utils.network import get_hop_location
|
|
16
7
|
|
|
17
|
-
try:
|
|
18
|
-
result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
|
19
|
-
return format_trace_output(result.stdout)
|
|
20
|
-
except subprocess.TimeoutExpired:
|
|
21
|
-
return f"Traceroute to {host} timed out after {timeout} seconds."
|
|
22
|
-
except FileNotFoundError:
|
|
23
|
-
return f"Traceroute command not found on this system."
|
|
24
|
-
except Exception as e:
|
|
25
|
-
return f"Traceroute failed: {e}"
|
|
26
8
|
|
|
9
|
+
IP_REGEX = re.compile(r"(\d{1,3}(?:\.\d{1,3}){3})")
|
|
10
|
+
RTT_REGEX = re.compile(r"(\d+(?:\.\d+)?)\s*ms")
|
|
27
11
|
|
|
28
|
-
|
|
12
|
+
|
|
13
|
+
def _is_private_ip(ip: str) -> bool:
|
|
29
14
|
try:
|
|
30
15
|
return ipaddress.ip_address(ip).is_private
|
|
31
16
|
except ValueError:
|
|
32
17
|
return False
|
|
33
18
|
|
|
34
19
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
def _build_traceroute_command(host: str, max_hops: int) -> list[str]:
|
|
21
|
+
if platform.system() == "Windows":
|
|
22
|
+
return ["tracert", "-h", str(max_hops), host]
|
|
23
|
+
|
|
24
|
+
return ["traceroute", "-m", str(max_hops), "-w", "1", host]
|
|
39
25
|
|
|
40
26
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
def run_traceroute(
|
|
28
|
+
host: str,
|
|
29
|
+
max_hops: int = 30,
|
|
30
|
+
timeout: int = 60,
|
|
31
|
+
) -> dict:
|
|
32
|
+
cmd = _build_traceroute_command(host, max_hops)
|
|
45
33
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
try:
|
|
35
|
+
proc = subprocess.run(
|
|
36
|
+
cmd,
|
|
37
|
+
capture_output=True,
|
|
38
|
+
text=True,
|
|
39
|
+
timeout=timeout,
|
|
40
|
+
)
|
|
41
|
+
except subprocess.TimeoutExpired:
|
|
42
|
+
return {"error": "Traceroute timed out"}
|
|
43
|
+
except FileNotFoundError:
|
|
44
|
+
return {"error": "Traceroute command not found"}
|
|
45
|
+
except Exception as exc:
|
|
46
|
+
return {"error": str(exc)}
|
|
47
|
+
|
|
48
|
+
hops = []
|
|
49
|
+
|
|
50
|
+
for index, line in enumerate(proc.stdout.splitlines(), start=1):
|
|
51
|
+
ips = IP_REGEX.findall(line)
|
|
52
|
+
if not ips:
|
|
49
53
|
continue
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
ip = ips[0]
|
|
56
|
+
private = _is_private_ip(ip)
|
|
57
|
+
|
|
58
|
+
rtts = [float(x) for x in RTT_REGEX.findall(line)]
|
|
59
|
+
rtt_ms = rtts if rtts else None
|
|
60
|
+
|
|
61
|
+
hop_geo = None
|
|
62
|
+
if not private:
|
|
63
|
+
hop_geo = get_hop_location(ip)
|
|
64
|
+
|
|
65
|
+
hops.append({
|
|
66
|
+
"hop": index,
|
|
67
|
+
"ip": ip,
|
|
68
|
+
"private": private,
|
|
69
|
+
"rtt_ms": rtt_ms,
|
|
70
|
+
"latitude": hop_geo.get("latitude") if hop_geo else None,
|
|
71
|
+
"longitude": hop_geo.get("longitude") if hop_geo else None,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
"target": host,
|
|
76
|
+
"hops": hops,
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
|
|
55
|
-
|
|
56
|
-
if
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
geo_info = f" --> {data.get('city', 'N/A')}, {data.get('region', '')} ({data.get('org', 'N/A')})"
|
|
60
|
-
formatted_lines.append(geo_info)
|
|
80
|
+
def format_traceroute(result: dict) -> None:
|
|
81
|
+
if "error" in result:
|
|
82
|
+
print(f"Traceroute error: {result['error']}")
|
|
83
|
+
return
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
for hop in result.get("hops", []):
|
|
86
|
+
hop_no = hop["hop"]
|
|
87
|
+
ip = hop["ip"]
|
|
88
|
+
label = "PRIVATE" if hop["private"] else "PUBLIC"
|
|
63
89
|
|
|
90
|
+
rtt = hop["rtt_ms"]
|
|
91
|
+
rtt_display = (
|
|
92
|
+
f"{min(rtt):.1f} ms" if isinstance(rtt, list) else "*"
|
|
93
|
+
)
|
|
64
94
|
|
|
65
|
-
|
|
66
|
-
parts = line.split()
|
|
67
|
-
for part in parts:
|
|
68
|
-
if any(ext in part for ext in [".com", ".net", ".org"]):
|
|
69
|
-
return f"({part})"
|
|
70
|
-
return "(Public)"
|
|
95
|
+
print(f"[{hop_no:>2}] {ip:<15} {label:<7} {rtt_display}")
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yougotmapped
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: A terminal tool to map IPs and domains with style.
|
|
5
|
+
Author-email: diputs <diputs-sudo@proton.me>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/diputs-sudo/YouGotMapped
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: requests
|
|
15
|
+
Requires-Dist: folium
|
|
16
|
+
Requires-Dist: ping3
|
|
17
|
+
Requires-Dist: scapy
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# YouGotMapped
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
YouGotMapped is a command-line network intelligence and visualization tool that correlates IP addresses and domains with geographic, routing, and performance data.
|
|
25
|
+
|
|
26
|
+
It integrates geolocation, latency analysis, traceroute inspection, and anonymity detection into a single, structured workflow, producing both human-readable output and machine-consumable logs.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Overview
|
|
31
|
+
|
|
32
|
+
YouGotMapped is designed to provide visibility into how traffic traverses networks and where endpoints are geographically represented. It is suitable for diagnostic, educational, and research use in environments where the user has appropriate authorization.
|
|
33
|
+
|
|
34
|
+
The tool emphasizes clarity, traceability, and reproducibility of results.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Key Capabilities
|
|
39
|
+
|
|
40
|
+
- IP and domain geolocation
|
|
41
|
+
- Interactive geographic visualization via HTML maps
|
|
42
|
+
- ICMP-based reachability and latency measurement
|
|
43
|
+
- Jitter analysis and stability inference
|
|
44
|
+
- TCP MSS discovery
|
|
45
|
+
- Bandwidth estimation using TCP performance models
|
|
46
|
+
- Hop-by-hop traceroute with geographic correlation
|
|
47
|
+
- VPN, proxy, and anonymity signal detection
|
|
48
|
+
- Structured output in JSON, CSV, or plain text formats
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Intended Use
|
|
53
|
+
|
|
54
|
+
YouGotMapped is intended for:
|
|
55
|
+
|
|
56
|
+
- Network diagnostics and troubleshooting
|
|
57
|
+
- Infrastructure visibility and analysis
|
|
58
|
+
- Educational exploration of routing behavior
|
|
59
|
+
- Authorized reconnaissance in controlled environments
|
|
60
|
+
|
|
61
|
+
Users are responsible for ensuring they have explicit permission to analyze any systems or networks they do not own.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Prohibited Use
|
|
66
|
+
|
|
67
|
+
This project must not be used for:
|
|
68
|
+
|
|
69
|
+
- Unauthorized monitoring or surveillance
|
|
70
|
+
- Targeting individuals or private infrastructure
|
|
71
|
+
- Harassment, exploitation, or data misuse
|
|
72
|
+
- Any activity that violates applicable laws or policies
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Requirements
|
|
77
|
+
|
|
78
|
+
- Python 3.8 or newer
|
|
79
|
+
- Network access permitting ICMP and TCP probes
|
|
80
|
+
- Runtime dependencies:
|
|
81
|
+
- `requests`
|
|
82
|
+
- `folium`
|
|
83
|
+
- `ping3`
|
|
84
|
+
- `scapy`
|
|
85
|
+
|
|
86
|
+
Dependencies are validated at startup.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
YouGotMapped can be installed directly from PyPI:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install yougotmapped
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
After installation, the `yougotmapped` command is available on the system PATH.
|
|
99
|
+
|
|
100
|
+
### From Source
|
|
101
|
+
|
|
102
|
+
Clone the repository:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
git clone https://github.com/your-username/YouGotMapped.git
|
|
106
|
+
cd YouGotMapped
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Install dependencies:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pip install -r requirements.txt
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Running from Source:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
python -m yougotmapped.cli
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Usage
|
|
124
|
+
|
|
125
|
+
Analyze a single target using all available modules:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
yougotmapped -i 8.8.8.8 -a
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Export results as JSON:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
yougotmapped -i 8.8.8.8 -a -o f:json
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Disable map generation:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
yougotmapped -i example.com -t --no-map
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Command-Line Options
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
-i, --ip [IP ...] IP addresses or domains
|
|
149
|
+
-f, --file FILE Input file with targets
|
|
150
|
+
-p, --ping Latency and reachability test
|
|
151
|
+
-j, --jitter Jitter and stability analysis
|
|
152
|
+
-m, --mtu MTU / MSS discovery
|
|
153
|
+
-b, --bandwidth Bandwidth estimation
|
|
154
|
+
-t, --trace Traceroute analysis
|
|
155
|
+
-c, --hidecheck Anonymity detection
|
|
156
|
+
-a, --all Run all modules
|
|
157
|
+
--no-map Disable map output
|
|
158
|
+
-o, --output Output format (f:json, f:csv, f:normal)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Output
|
|
164
|
+
|
|
165
|
+
Each execution produces:
|
|
166
|
+
|
|
167
|
+
* Structured log files with timestamps
|
|
168
|
+
* Optional interactive HTML maps
|
|
169
|
+
* Terminal summaries for immediate inspection
|
|
170
|
+
|
|
171
|
+
Outputs are designed to be both auditable and reproducible.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Legal Notice
|
|
176
|
+
|
|
177
|
+
By using this software, you acknowledge that:
|
|
178
|
+
|
|
179
|
+
* You have authorization to analyze the specified targets
|
|
180
|
+
* You accept full responsibility for its use
|
|
181
|
+
* The author is not liable for misuse or resulting damages
|
|
182
|
+
|
|
183
|
+
This software is provided for educational and research purposes.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Contributing
|
|
188
|
+
|
|
189
|
+
Contributions are welcome if they improve accuracy, reliability, or clarity and adhere to ethical and legal standards. Functionality that materially enables misuse will not be accepted.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
This project is licensed under the MIT License. See the LICENSE file for details.
|
|
196
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
yougotmapped/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
yougotmapped/cli.py,sha256=wK4y2Oh1iGiBXdJ6stMJ6veajS6-_0ZXh5OxsWnjHHo,7399
|
|
3
|
+
yougotmapped/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
yougotmapped/utils/anonymity.py,sha256=qi2vdNsnppYwounC1OQdaAs21FqmNj4KewtDh3e5H7c,2439
|
|
5
|
+
yougotmapped/utils/bandwidth.py,sha256=6jVUPNn4e0DM_mwN5k5AwVSzNoipY1DmWqZZpbbOtTw,1526
|
|
6
|
+
yougotmapped/utils/dependencies.py,sha256=hF_r2PDBGfXgKeOyDc-iTtOzmdvBlR95iUnJZ0soimo,1494
|
|
7
|
+
yougotmapped/utils/ingress.py,sha256=X9Gp11KnKMBwaox3W4tAaQs52ICiDPSMWJwwLSrIg4w,1692
|
|
8
|
+
yougotmapped/utils/jitter.py,sha256=Kuc66BbywBoFDmbi-FRkMrx21r9YBlqfFhUI9GQuT_g,1940
|
|
9
|
+
yougotmapped/utils/mapping.py,sha256=j-kPVEFocNy8fUvjdxr9H5hDSbvSLVNEek6J9xJ0Vlc,2719
|
|
10
|
+
yougotmapped/utils/mss.py,sha256=KK8gVtnzpYi9c8eM313BC4X_wPx1wOGis4vTZgdNs_Q,3029
|
|
11
|
+
yougotmapped/utils/mtu.py,sha256=ZbjLhNRko0ngYEPBKtZbnOTtXIlxcm-ylYOIz_SReZM,1772
|
|
12
|
+
yougotmapped/utils/network.py,sha256=kq_uFKq2vpzDdZ9s748ke-NzLS3Y_woARSB3htNC8Qg,2173
|
|
13
|
+
yougotmapped/utils/output.py,sha256=1nLRr3X-o_KdsUASWXhvS9TibZOv05X_Inj7_a2ZCWI,1867
|
|
14
|
+
yougotmapped/utils/ping.py,sha256=TbI-lWSR6OaYKRpYqmUNEraW-nhkh5F-9WJd7jl7bto,2866
|
|
15
|
+
yougotmapped/utils/trace.py,sha256=dKDpxcMnrZd-y6jjqTMrl6_ylIwYSreZMOmXXvbwHrw,2383
|
|
16
|
+
yougotmapped-1.1.0.dist-info/licenses/LICENSE,sha256=E9UVVmDEpddJlGAMso045DiZPv_MO-UdjzTXkhiG7ps,1068
|
|
17
|
+
yougotmapped-1.1.0.dist-info/METADATA,sha256=1p8ZuWX9wLV_epP93rhURl1_YjpJmbl5FldS9SVeRvE,4790
|
|
18
|
+
yougotmapped-1.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
19
|
+
yougotmapped-1.1.0.dist-info/entry_points.txt,sha256=zv6jK4RV-3qvJ59qY1dZxML0g3qahKVMztwobKtTP-Q,55
|
|
20
|
+
yougotmapped-1.1.0.dist-info/top_level.txt,sha256=XYHTw9YTF8Rz9Xj06Gh-xEl5IYs467gQR4BYlNrxZmM,13
|
|
21
|
+
yougotmapped-1.1.0.dist-info/RECORD,,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 diputs
|
|
3
|
+
Copyright (c) 2025 diputs-sudo
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
7
|
in the Software without restriction, including without limitation the rights
|
|
8
8
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
|
@@ -12,16 +12,10 @@ furnished to do so, subject to the following conditions:
|
|
|
12
12
|
The above copyright notice and this permission notice shall be included in all
|
|
13
13
|
copies or substantial portions of the Software.
|
|
14
14
|
|
|
15
|
-
THE SOFTWARE IS PROVIDED
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
📝 Side note from the author:
|
|
26
|
-
If this script crashes your terminal or geo-locates your toaster... that's on you.
|
|
27
|
-
But hey — it worked flawlessly on my end. 🫠
|