Files
felhom.eu/documentation/audits/night-2026-10-25/tools/tracker.py
T

44 lines
1.8 KiB
Python

#!/usr/bin/env python3
"""tracker.py [port] — a minimal HTTP BitTorrent tracker for the night's R-1261 rig (stdlib only). It records every
peer that announces (by source address and the announced port) and answers the others in compact form."""
import http.server, socket, struct, sys, time, urllib.parse
PEERS = {} # info_hash -> {(ip, port): last_seen}
def benc(d):
out = b"d"
for k in sorted(d):
v = d[k]
out += b"%d:%s" % (len(k), k.encode())
out += (b"i%de" % v) if isinstance(v, int) else (b"%d:%s" % (len(v), v))
return out + b"e"
class H(http.server.BaseHTTPRequestHandler):
def do_GET(self):
u = urllib.parse.urlsplit(self.path)
q = urllib.parse.parse_qs(u.query, keep_blank_values=True, encoding="latin-1")
ih = q.get("info_hash", [""])[0].encode("latin-1")
port = int(q.get("port", ["0"])[0] or 0)
ip = self.client_address[0]
now = time.time()
peers = PEERS.setdefault(ih, {})
if q.get("event", [""])[0] == "stopped":
peers.pop((ip, port), None)
else:
peers[(ip, port)] = now
others = [p for p, t in peers.items() if p != (ip, port) and now - t < 600]
compact = b"".join(socket.inet_aton(a) + struct.pack(">H", pt) for a, pt in others)
body = benc({"interval": 30, "peers": compact})
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
sys.stdout.write("%s announce %s:%d -> %d peer(s)\n" % (time.strftime("%H:%M:%S"), ip, port, len(others)))
sys.stdout.flush()
def log_message(self, *a):
pass
http.server.ThreadingHTTPServer(("0.0.0.0", int(sys.argv[1]) if len(sys.argv) > 1 else 6969), H).serve_forever()