Files
dark0rbits/app.py

581 lines
37 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""AURIGA — homelab toolbox: IP intel, card validator, SMS rentals, proxy tools."""
import base64, binascii, hashlib, json, os, re, secrets, socket, sqlite3, string, struct, time, uuid
import urllib.request, urllib.parse
from flask import Flask, request, jsonify, render_template_string, g
app = Flask(__name__)
DB_PATH = os.environ.get("AURIGA_DB", "/opt/auriga/auriga.db")
SMSP_KEY = os.environ.get("SMSP_KEY", "")
PLEIADES_GW = os.environ.get("PLEIADES_GW", "10.30.20.178:8080")
PLEIADES_APP = os.environ.get("PLEIADES_APP", "http://10.30.20.178:5000")
BMAC = "https://buymeacoffee.com/r26xrthzttg"
def db():
con = sqlite3.connect(DB_PATH); con.row_factory = sqlite3.Row
con.execute("""CREATE TABLE IF NOT EXISTS sms_rentals(
id INTEGER PRIMARY KEY, phone TEXT, service TEXT, country TEXT,
purchase_id TEXT, cost REAL, status TEXT, created INTEGER, expires INTEGER)""")
con.execute("""CREATE TABLE IF NOT EXISTS proxy_checks(
id INTEGER PRIMARY KEY, user_key TEXT, egress_ip TEXT, geo TEXT, ok INTEGER, ts INTEGER)""")
return con
def http(url, headers=None, data=None, method="GET", timeout=12):
h = {"User-Agent": "Mozilla/5.0 (Auriga toolbox)"}
h.update(headers or {})
req = urllib.request.Request(url, headers=h, data=data, method=method)
try:
with urllib.request.urlopen(req, timeout=timeout) as r:
return r.status, r.read().decode("utf-8", "replace")
except urllib.error.HTTPError as e:
return e.code, e.read().decode("utf-8", "replace")
except Exception as e:
return 0, str(e)
def jf(b):
try: return json.loads(b)
except Exception: return None
BASE = """<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<meta name=robots content="noindex"><title>AURIGA — Toolbox</title>
<style>
:root{--bg:#0b0e17;--card:#141a2b;--fg:#e8ecf7;--dim:#8b95b3;--acc:#f0b429;--ok:#3ecf8e;--bad:#ff5d5d}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.5 ui-monospace,Menlo,Consolas,monospace}
nav{display:flex;flex-wrap:wrap;gap:.4rem;padding:1rem 1.4rem;border-bottom:1px solid #232b45;position:sticky;top:0;background:var(--bg);z-index:5}
nav a{color:var(--dim);text-decoration:none;padding:.45rem .9rem;border:1px solid #232b45;border-radius:999px}
nav a.on,nav a:hover{color:var(--acc);border-color:var(--acc)}
main{max-width:960px;margin:0 auto;padding:2rem 1.4rem}
h1{font-size:1.7rem;letter-spacing:.2em}h1 span{color:var(--acc)}
.sub{color:var(--dim);margin:.3rem 0 1.6rem}
.card{background:var(--card);border:1px solid #232b45;border-radius:14px;padding:1.2rem 1.4rem;margin:1rem 0}
.kv{display:grid;grid-template-columns:minmax(140px,220px) 1fr;gap:.3rem 1rem}
.kv div:nth-child(odd){color:var(--dim)}
input,select,button,textarea{font:inherit;background:#0e1424;color:var(--fg);border:1px solid #2a3555;border-radius:8px;padding:.6rem .8rem}
button{background:var(--acc);color:#111;border:0;font-weight:700;cursor:pointer}
button:hover{filter:brightness(1.1)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
@media(max-width:700px){.grid2{grid-template-columns:1fr}.kv{grid-template-columns:1fr}}
.tag{display:inline-block;padding:.15rem .6rem;border-radius:999px;font-size:.8rem;border:1px solid}
.tag.ok{color:var(--ok);border-color:var(--ok)}.tag.bad{color:var(--bad);border-color:var(--bad)}.tag.warn{color:var(--acc);border-color:var(--acc)}
table{width:100%;border-collapse:collapse}td,th{padding:.4rem;border-bottom:1px solid #232b45;text-align:left;font-size:.9rem}
footer{color:var(--dim);text-align:center;padding:2rem;font-size:.85rem}footer a{color:var(--acc)}
.spin{display:inline-block;animation:r 1s linear infinite}@keyframes r{to{transform:rotate(360deg)}}
</style></head><body>
<nav>
<a href=/ class={{o(ip)}}>◈ WHATS-MY-IP</a><a href=/card class={{o(card)}}>◈ CARD CHECK</a>
<a href=/sms class={{o(sms)}}>◈ SMS RENTAL</a><a href=/proxy class={{o(proxy)}}>◈ PROXY LAB</a>
<a href=/tools class={{o(tools)}}>◈ FREE TOOLS</a>
</nav><main>{{body}}</main>
<footer>Built for agents &amp; humans · <a href="{{bmac}}" target=_blank rel=noopener>☕ fuel the lab</a></footer>
<script defer src="https://analytics.thetempleofdoom.com/script.js" data-website-id="953c15df-ba4c-453a-a7c6-465fa9e3f202"></script>
<script>
function cp(t){navigator.clipboard.writeText(t).then(function(){toast('Copied ✓')})}
function toast(m){var d=document.createElement('div');d.textContent=m;d.style.cssText='position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--acc);color:#111;padding:.5rem 1rem;border-radius:8px;font-weight:700;z-index:99';document.body.appendChild(d);setTimeout(function(){d.remove()},1500)}
</script>
</body></html>"""
def page(sec, body):
return render_template_string(BASE, body=body, bmac=BMAC, o=lambda s: "on" if s == sec else "")
def kv(pairs):
rows = "".join(f"<div>{k}</div><div>{v}</div>" for k, v in pairs)
return f'<div class="card"><div class="kv">{rows}</div></div>'
# ---------- 0. AGENT DISCOVERY ----------
API_INDEX = {
"service": "AURIGA toolbox",
"description": "IP intel, card BIN validation, 30-min SMS rentals, residential proxy lab, free utilities. Human UI at /, all tools also JSON APIs.",
"endpoints": [
{"method": "GET", "path": "/api/ip", "desc": "Everything about the caller's IP: geo, ASN, ISP, VPN/proxy/hosting flags, rDNS, request headers."},
{"method": "POST", "path": "/api/card", "params": {"num": "card number (digits or formatted)"}, "desc": "Luhn + BIN intel: brand, issuer, country, type, prepaid risk flags. Nothing stored/charged."},
{"method": "POST", "path": "/api/sms/rent", "params": {"service": "SMSPool service id or keyword (273=discord, 395=google, telegram, whatsapp, other)", "country": "country id (1=US,2=UK,4=NL,150=DE)"}, "desc": "Rent a disposable number for 30 min. Returns number + orderid. Cancel before a code = full refund."},
{"method": "GET", "path": "/api/sms/check", "params": {"pid": "orderid"}, "desc": "Poll for the received SMS code."},
{"method": "GET", "path": "/api/sms/cancel", "params": {"pid": "orderid"}, "desc": "Cancel order + refund."},
{"method": "GET", "path": "/api/sms/history", "desc": "Your rental history from this site."},
{"method": "POST", "path": "/api/proxy/test", "params": {"user": "Pleiades gateway username", "pass": "password (geo suffixes allowed)"}, "desc": "Tunnel CONNECT through the Pleiades gateway, return real egress IP + geo."},
{"method": "GET", "path": "/api/hash", "params": {"s": "string"}, "desc": "md5/sha1/sha256/sha512."},
{"method": "GET", "path": "/api/hdr", "params": {"url": "target URL"}, "desc": "Fetch URL, return status + all response headers."},
],
"payment": "SMS meters against the house SMSPool account; proxy plans at the Pleiades storefront. BTCPay BTC only — no Stripe.",
}
@app.route("/api")
def api_index(): return jsonify(API_INDEX)
@app.route("/robots.txt")
def robots():
return "User-agent: *\nAllow: /\n", 200, {"Content-Type": "text/plain"}
@app.route("/llms.txt")
def llms():
eps = "\n".join(f"- `{e['method']} {e['path']}` — {e['desc']} Params: {e.get('params','-')}" for e in API_INDEX["endpoints"])
body = f"# AURIGA toolbox\n\nNetwork toolbox for humans and agents. Base: https://auriga.thetempleofdoom.com\n\n## API\n{eps}\n\nAll responses JSON. POST bodies are form-encoded. Human pages at /, /card, /sms, /proxy, /tools.\n"
return body, 200, {"Content-Type": "text/plain"}
@app.route("/ai-plugin.json")
def aiplugin():
return jsonify({"name_for_model": "auriga", "schema_version": "v1",
"description_for_model": "IP intelligence, card BIN validation, disposable SMS number rentals (30 min, refundable), residential proxy egress testing, hashing/URL/DNS utilities.",
"api": {"type": "openapi", "url": "https://auriga.thetempleofdoom.com/openapi.json"},
"auth": {"type": "none"}, "contact_email": "indianaholmes1@icloud.com"})
@app.route("/openapi.json")
def openapi():
B = "https://auriga.thetempleofdoom.com"
ps = {"openapi": "3.0.0", "info": {"title": "AURIGA", "version": "1.1.0"}, "paths": {}}
def add(path, method, desc, params=None, req=False):
item = {"summary": desc}
if params:
if method == "get":
item["parameters"] = [{"name": k, "in": "query", "required": req, "schema": {"type": "string"}, "description": v} for k, v in params.items()]
else:
item["requestBody"] = {"content": {"application/x-www-form-urlencoded": {"schema": {"type": "object", "properties": {k: {"type": "string", "description": v} for k, v in params.items()}, "required": [k for k in params] if req else []}}}}
ps["paths"][path] = ps["paths"].get(path, {}) | {method: {"responses": {"200": {"description": "ok"}}, **item}}
add("/api/ip", "get", "Caller IP intel: geo/ASN/ISP/VPN flags/headers")
add("/api/card", "post", "Luhn + BIN validation", {"num": "card number"}, req=True)
add("/api/sms/rent", "post", "Rent disposable number, 30 min", {"service": "service id/keyword", "country": "country id"}, req=True)
add("/api/sms/check", "get", "Poll SMS code", {"pid": "orderid"}, req=True)
add("/api/sms/cancel", "get", "Cancel + refund", {"pid": "orderid"}, req=True)
add("/api/sms/history", "get", "Rental history")
add("/api/proxy/test", "post", "Test Pleiades gateway creds", {"user": "username", "pass": "password"}, req=True)
add("/api/hash", "get", "Hashes of s", {"s": "string"}, req=True)
add("/api/hdr", "get", "HTTP response headers of url", {"url": "url"}, req=True)
return jsonify(ps)
def param(name):
return request.form.get(name) or request.args.get(name) or request.args.get("orderid") or request.form.get("orderid")
def human(n):
return n
# ---------- 1. WHAT'S MY IP ----------
@app.route("/ip")
def ip_route(): return ip_lookup()
def ip_lookup():
ip = request.headers.get("X-Real-IP") or request.remote_addr or ""
st, b = http(f"http://ip-api.com/json/{ip}?fields=66846719")
d = jf(b) or {}
hdrs = {k: v for k, v in request.headers.items() if k.lower() in
("user-agent","accept-language","x-forwarded-for","cf-connecting-ip","cf-ipcountry","x-real-ip")}
proxy_hint = any(k.lower().startswith(("x-forwarded","via","proxy")) for k in request.headers.keys())
rows = [
("YOUR IP", f"<b style='font-size:1.3rem;color:var(--acc)'>{d.get('query', ip)}</b>"),
("Country", f"{d.get('country','?')} ({d.get('countryCode','?')}) 🏴 {d.get('flag') if 'flag' in d else ''}".strip()),
("Region / City", f"{d.get('regionName','?')} / {d.get('city','?')} {d.get('zip','')}"),
("Lat, Lon", f"{d.get('lat','?')}, {d.get('lon','?')} · TZ: {d.get('timezone','?')} · UTC offset {d.get('offset','?')}s"),
("ISP", d.get('isp','?')), ("Organization", d.get('org','?')), ("AS", d.get('as','?') if d.get('as') else d.get('asname','?')),
("Reverse DNS", str(d.get('reverse','—'))),
("Connection", f"mobile: {d.get('mobile')} · proxy/VPN: {d.get('proxy')} · hosting: {d.get('hosting')}"),
("Local guess", d.get('district') or '—'),
("Proxy headers seen", "YES ⚠ (you're behind a relay)" if proxy_hint else "none — looks direct"),
("Currency", d.get('currency','?')),
]
hdr_rows = "".join(f"<tr><td>{k}</td><td>{v}</td></tr>" for k, v in hdrs.items())
body = f"""
<h1>WHATS <span>MY IP</span></h1><p class=sub>Every drop of intel we can legally scrape, always on.</p>
{kv(rows)}
<div class=card><b>Headers you sent</b><table>{hdr_rows}</table></div>
<div class=card><b>Live check</b> — your browser also resolved this page in
<span id=ms>…</span>. <script>t=performance.timing.responseStart-performance.timing.requestStart;
document.getElementById('ms').textContent=Math.max(0,t)+' ms';</script></div>
<div class=card>API: <code>GET /api/ip</code> → same data as JSON. Agent-friendly.</div>"""
return page("ip", body)
@app.route("/api/ip")
def api_ip():
ip = request.headers.get("X-Real-IP") or request.remote_addr or ""
st, b = http(f"http://ip-api.com/json/{ip}?fields=66846719")
d = jf(b) or {}
d["headers_seen"] = {k: v for k, v in request.headers.items()}
return jsonify(d)
# ---------- 2. CARD CHECK ----------
def luhn_ok(num):
digits = [int(c) for c in num]
odd = digits[-1::-2]; even = digits[-2::-2]
s = sum(odd)
for d in even:
d *= 2
if d > 9: d -= 9
s += d
return s % 10 == 0
BRANDS = [("4","Visa"),("51","Mastercard"),("52","Mastercard"),("53","Mastercard"),("54","Mastercard"),("55","Mastercard"),
("22","Mastercard"),("23","Mastercard"),("24","Mastercard"),("25","Mastercard"),("26","Mastercard"),("27","Mastercard"),
("34","Amex"),("37","Amex"),("6011","Discover"),("65","Discover"),("644","Discover"),("645","Discover"),("646","Discover"),("647","Discover"),("648","Discover"),("649","Discover"),
("50","Maestro"),("56","Maestro"),("57","Maestro"),("58","Maestro"),("63","Maestro"),("67","Maestro"),
("30","Diners"),("36","Diners"),("38","Diners"),("39","Diners"),
("35","JCB"),("62","UnionPay"),("7","Mir")]
def brand_of(num):
for pfx, b in BRANDS:
if num.startswith(pfx): return b
return "Unknown"
@app.route("/card", methods=["GET", "POST"])
def card():
result = ""
num = re.sub(r"\D", "", request.form.get("num", ""))[:19]
if num:
tags = []
ok = luhn_ok(num)
tags.append(('<span class="tag ok">LUHN VALID</span>' if ok else '<span class="tag bad">LUHN INVALID — fake/dead number</span>'))
brand = brand_of(num)
bin8 = num[:8]
bl = bin_lookup(bin8)
bank = (bl.get("bank") or {}).get("name", "—")
country = (bl.get("country") or {}).get("name", "—")
ctype = bl.get("type", "—")
prepaid = bl.get("prepaid", "—")
if not bl: tags.append('<span class="tag warn">BIN DB no data — structure-only result</span>')
flags = []
if ctype == "prepaid" or prepaid is True: flags.append("PREPAID — commonly flagged by merchants")
if ctype == "debit": flags.append("DEBIT")
if ctype == "credit": flags.append("CREDIT")
length = len(num)
rng = {"Visa":(13,16,19),"Mastercard":(16,),"Amex":(15,),}.get(brand, (13,15,16,19))
if length not in rng: tags.append(f'<span class="tag bad">LENGTH {length} WRONG for {brand}</span>')
else: tags.append(f'<span class="tag ok">length {length} valid for {brand}</span>')
result = f"""
{kv([("Brand",brand),("BIN",bin8),("Bank / Issuer",bank),("Country",country),("Type",str(ctype)),("Prepaid",str(prepaid))])}
<div class=card><b>Fraud &amp; structure flags</b><br>{' '.join(tags)}
{'<br>⚠ ' + ' · '.join(flags) if flags else ''}</div>
<div class=card style=color:var(--dim)>Nothing is stored. No charge, no auth, no $0 check — this is BIN + math validation only.
It cannot tell you if a card has available funds. Fraud "flagged" status lives at the issuer, not in any database we can legally query.</div>"""
body = f"""
<h1>CARD <span>CHECK</span></h1><p class=sub>Is it real? Luhn + BIN intelligence: issuer, brand, type, country, prepaid risk flags.</p>
<div class=card><form method=post><input id=cardnum name=num placeholder="4539 1488 0343 6467" style="width:70%" value="{num}" autocomplete=off inputmode=numeric> <button>Check</button></form>
<div style=color:var(--dim);font-size:.85rem;margin-top:.4rem>Paste anything — spaces, dashes, junk all stripped. Nothing stored.</div></div>
<script>
var cn=document.getElementById('cardnum');
cn.addEventListener('input',function(){{
var v=this.value.replace(/\\D/g,'').slice(0,19);this.value=v.replace(/(.{{4}})/g,'$1 ').trim()}});
</script>
{result}"""
return page("card", body)
def bin_lookup(bin8):
st, b = http(f"https://lookup.binlist.net/{bin8}", headers={"Accept-Version": "3"})
bl = jf(b) or {}
if not bl.get("bank") and not bl.get("type") and not bl.get("scheme"):
st, b = http(f"https://data.handyapi.com/bin/{bin8}")
h = jf(b) or {}
if h.get("Status") == "SUCCESS":
return {"bank": {"name": h.get("Issuer")}, "country": {"name": h.get("Country", {}).get("Name") if isinstance(h.get("Country"), dict) else h.get("Country")},
"type": str(h.get("Type", "")).lower() or None, "prepaid": "prepaid" in str(h.get("Type","")).lower() or None, "scheme": h.get("Scheme")}
return bl
@app.route("/api/card", methods=["POST"])
def api_card():
num = re.sub(r"\D", "", param("num") or "")[:19]
if not num: return jsonify({"ok": False, "error": "num required"})
ok = luhn_ok(num)
bl = bin_lookup(num[:8])
return jsonify({"ok": True, "luhn": ok, "brand": brand_of(num), "length_ok": len(num) in
{"Visa":(13,16,19),"Mastercard":(16,),"Amex":(15,)}.get(brand_of(num),(13,15,16,19)),
"bin": {"issuer": (bl.get("bank") or {}).get("name"), "country": (bl.get("country") or {}).get("name"),
"type": bl.get("type"), "prepaid": bl.get("prepaid")},
"flags": (["prepaid-risk"] if (bl.get("type")=="prepaid" or bl.get("prepaid") is True) else []) + (["luhn-invalid"] if not ok else [])})
# ---------- SMS ABUSE GUARD ----------
def sms_guard():
"""Return None if allowed, else a JSON-able reason string."""
con = db(); now = int(time.time())
ip = request.headers.get("X-Real-IP") or request.remote_addr or "?"
# balance: refuse if house SMSPool balance below $5
st, b = sms_api("request/balance")
bal = jf(b) or {}
try: bal = float(bal.get("balance", 0))
except Exception: bal = 0
if bal < 5: return f"house balance too low (${bal:.2f}) — rentals paused"
# per-IP: max 1 active rental, 3/hour, 8/day
row = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE status='active' AND purchase_id IN (SELECT purchase_id FROM sms_rentals WHERE created > ?)", (now-86400*7,)).fetchone()
# active count overall (any IP) cap 3 concurrent
act = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE status='active' AND expires > ?", (now,)).fetchone()["c"]
if act >= 3: return "too many active rentals right now — try again later"
h = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE created > ?", (now-3600,)).fetchone()["c"]
if h >= 6: return "hourly rental cap reached"
d = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE created > ?", (now-86400,)).fetchone()["c"]
if d >= 15: return "daily rental cap reached"
return None
# ---------- 3. SMS RENTALS ----------
SMSP = "https://api.smspool.net"
SERVICES = [("google","Google"),("discord","Discord"),("telegram","Telegram"),("whatsapp","WhatsApp"),("other","Other/Any")]
COUNTRIES = [("1","United States"),("2","United Kingdom"),("4","Netherlands"),("22","Russia"),("150","Germany")]
def sms_api(path, **kw):
if kw:
kw["key"] = SMSP_KEY
data = urllib.parse.urlencode(kw).encode()
return http(f"{SMSP}/{path}", data=data, method="POST")
return http(f"{SMSP}/{path}?key={SMSP_KEY}")
@app.route("/sms", methods=["GET", "POST"])
def sms():
msg, listing = "", ""
if request.method == "POST":
act = request.form.get("act")
if act == "rent":
guard = sms_guard()
if guard:
msg = f'<div class="card"><span class="tag warn">PAUSED</span> {guard}</div>'
else:
svc, ctry = request.form["service"], request.form["country"]
st, b = sms_api("purchase/sms", service=svc, country=ctry)
d = jf(b) or {}
if d.get("success") == 1:
con = db()
now = int(time.time())
con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)",
(d.get("number"), svc, ctry, str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800))
con.commit()
msg = f'<div class="card"><span class="tag ok">RENTED</span> Your number: <b id=bignum style="font-size:1.2rem;color:var(--acc)">+{d.get("number")}</b> <button style="padding:.2rem .6rem;font-size:.8rem" onclick="cp(\'+{d.get("number")}\')">copy</button> · expires in 30 min · order #{d.get("purchase_id")}</div>'
else:
msg = f'<div class="card"><span class="tag bad">RENT FAILED</span><br><pre>{b[:400]}</pre></div>'
elif act == "check":
pid = request.form["pid"]
st, b = sms_api("sms/check", orderid=pid)
d = jf(b) or {}
sms_txt = d.get("sms") or d.get("code") or ""
status = d.get("status", "?")
color = "ok" if sms_txt else "warn"
msg = f'<div class="card"><span class="tag {color}">STATUS: {status}</span> {"<b style=color:var(--ok)>" + str(sms_txt) + "</b>" if sms_txt else "no code yet — poll again in 10s"}</div>'
elif act == "cancel":
pid = request.form["pid"]
st, b = sms_api("sms/cancel", orderid=pid)
d = jf(b) or {}
ok = d.get("success") == 1
con = db(); con.execute("UPDATE sms_rentals SET status=? WHERE purchase_id=?", ("refunded" if ok else "cancel-failed", pid)); con.commit()
msg = f'<div class="card"><span class="tag {"ok" if ok else "bad"}">{"CANCELLED + REFUNDED" if ok else "CANCEL FAILED"}</span></div>'
st, b = sms_api("sms/instructions")
con = db()
hist = con.execute("SELECT * FROM sms_rentals ORDER BY id DESC LIMIT 8").fetchall()
hist_rows = "".join(f"<tr><td>+{h['phone']} <a href=# onclick=\"cp('+{h['phone']});return false\" style=color:var(--acc)>copy</a></td><td>{h['service']}</td><td>{h['status']}</td><td>#{h['purchase_id']}</td><td class=cdown data-exp={h['expires']}>…</td></tr>" for h in hist)
body = f"""
<h1>SMS <span>RENTAL</span></h1><p class=sub>Disposable numbers, 30-minute windows. Cancel before a code arrives = full refund.</p>
<div class="grid2">
<div class=card><b>Rent a number</b>
<form method=post><input type=hidden name=act value=rent>
<select name=service style="width:100%">{''.join(f'<option value={v}>{n}</option>' for v,n in SERVICES)}</select>
<select name=country style="width:100%;margin:.5rem 0">{''.join(f'<option value={v}>{n}</option>' for v,n in COUNTRIES)}</select>
<button>Rent — 30 min</button></form>
<div style=color:var(--dim);margin-top:.5rem;font-size:.85rem>Numbers auto-appear below. Codes auto-poll every 10s.</div></div>
<div class=card><b>Check / manage</b>
<form method=post><input type=hidden name=act value=check><input name=pid placeholder="order #" style="width:100%"><button style="margin:.5rem 0">Poll for code</button></form>
<form method=post><input type=hidden name=act value=cancel><input name=pid placeholder="order #" style="width:100%"><button style="background:var(--bad);color:#fff">Cancel &amp; refund</button></form></div>
</div>{msg}
<div class=card><b>Recent rentals</b><table><tr><th>Number</th><th>Service</th><th>Status</th><th>Order</th><th>Window</th></tr>{hist_rows or '<tr><td colspan=5 style=color:var(--dim)>none yet</td></tr>'}</table></div>
<script>
setInterval(function(){{
var els=document.querySelectorAll('.cdown');var now=Math.floor(Date.now()/1000);
els.forEach(function(e){{var s=e.dataset.exp-now;if(s>0){{var m=Math.floor(s/60);e.textContent=m+'m '+(s%60)+'s left'}}else e.textContent='expired'}});
}},1000);
var lastMsg='';
setInterval(function(){{
fetch('/api/sms/history').then(r=>r.json()).then(rows=>{{
rows.filter(r=>r.status==='active').forEach(r=>{{
fetch('/api/sms/check?pid='+r.purchase_id).then(x=>x.json()).then(d=>{{
if(d.sms||d.code){{toast('CODE: '+(d.sms||d.code));document.title='✉ CODE '+(d.sms||d.code);}}
}})}});
}})}},10000);
</script>
<div class=card style=color:var(--dim)>API: POST /api/sms/rent (service,country) · GET /api/sms/check?pid= · GET /api/sms/cancel?pid= · GET /api/sms/history</div>"""
return page("sms", body)
@app.route("/api/sms/rent", methods=["POST"])
def api_sms_rent():
guard = sms_guard()
if guard: return jsonify({"success": 0, "message": guard, "paused": True})
st, b = sms_api("purchase/sms", service=param("service"), country=param("country"))
d = jf(b) or {}
if d.get("success") == 1:
con = db(); now = int(time.time())
con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)",
(d.get("number"), param("service"), param("country"), str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800))
con.commit()
return jsonify(d)
@app.route("/api/sms/check", methods=["GET", "POST"])
def api_sms_check():
st, b = sms_api("sms/check", orderid=param("pid"))
return jf(b) or jsonify({"error": b[:200]})
@app.route("/api/sms/cancel", methods=["GET", "POST"])
def api_sms_cancel():
st, b = sms_api("sms/cancel", orderid=param("pid"))
return jf(b) or jsonify({"error": b[:200]})
@app.route("/api/sms/history")
def api_sms_history():
con = db(); now = int(time.time())
con.execute("UPDATE sms_rentals SET status='expired' WHERE status='active' AND expires < ?", (now,))
con.commit()
rows = con.execute("SELECT * FROM sms_rentals ORDER BY id DESC LIMIT 50").fetchall()
return jsonify([dict(r) for r in rows])
# ---------- 4. PROXY LAB ----------
@app.route("/proxy", methods=["GET", "POST"])
def proxy():
result = ""
if request.method == "POST" and request.form.get("act") == "test":
user, pw = request.form.get("user",""), request.form.get("pass","")
test_url = request.form.get("target", "http://ip-api.com/json/?fields=66846719")
pauth = base64.b64encode(f"{user}:{pw}".encode()).decode()
try:
pu = urllib.parse.urlparse(test_url if "://" in test_url else "http://"+test_url)
req_line = f"GET {pu.path or '/'} HTTP/1.1\r\nHost: {pu.hostname}\r\nConnection: close\r\n\r\n"
s = socket.create_connection((PLEIADES_GW.split(":")[0], int(PLEIADES_GW.split(":")[1])), timeout=15)
s.sendall(f"CONNECT {pu.hostname}:80 HTTP/1.1\r\nHost: {pu.hostname}:80\r\nProxy-Authorization: Basic {pauth}\r\n\r\n".encode())
resp = s.recv(4096)
if b"200" in resp.split(b"\r\n")[0]:
s.sendall(req_line.encode())
data = b""
while True:
c = s.recv(8192)
if not c: break
data += c
s.close()
body = data.split(b"\r\n\r\n",1)[-1].decode("utf-8","replace")
j = jf(body) or {}
con = db()
con.execute("INSERT INTO proxy_checks(user_key,egress_ip,geo,ok,ts) VALUES(?,?,?,?,?)",
(user[:12], j.get("query","?"), f"{j.get('country')}/{j.get('city')}", 1, int(time.time())))
con.commit()
result = f'<div class="card"><span class="tag ok">PROXY LIVE</span> Egress: <b style=color:var(--acc)>{j.get("query")}</b> — {j.get("country")} / {j.get("city")} · ISP {j.get("isp")} · tz {j.get("timezone")}</div>'
else:
con = db()
con.execute("INSERT INTO proxy_checks(user_key,egress_ip,geo,ok,ts) VALUES(?,?,?,?,?)", (user[:12], "", "", 0, int(time.time())))
con.commit()
result = f'<div class="card"><span class="tag bad">AUTH/TUNNEL FAILED</span><pre>{resp[:200]!r}</pre></div>'
except Exception as e:
result = f'<div class="card"><span class="tag bad">ERROR</span> {e}</div>'
body = f"""
<h1>PROXY <span>LAB</span></h1><p class=sub>Rent residential proxies on the Pleiades rail — your existing gateway <code>user:pass</code> works here, same keys as everywhere.</p>
<div class=card><form method=post><input type=hidden name=act value=test>
<label>Gateway user</label><br><input name=user style="width:100%" placeholder="gw_… or your Pleiades username"><br>
<label style=color:var(--dim)>Password</label><br><input name=pass type=password style="width:100%"><br>
<button style=margin-top:.6rem>Test egress now</button></form></div>
{result}
<div class=card><b>Geo session builder</b> — append these to your password to steer the egress:
<select id=geoK onchange="gb()"><option value="">none</option><option value="_region-us">region US</option><option value="_region-eu">region EU</option><option value="_country-gb">country GB</option><option value="_country-de">country DE</option><option value="_city-london">city London</option></select>
<select id=geoS onchange="gb()"><option value="">rotating</option><option value="_session-a7x9_lifetime-30m">sticky 30-min</option></select>
<div style=margin-top:.5rem><code id=geoOut style=color:var(--acc)>yourpassword</code> <button style="padding:.2rem .6rem;font-size:.8rem" onclick="cp(document.getElementById('geoOut').textContent)">copy</button></div>
<div style=color:var(--dim);font-size:.85rem;margin-top:.4rem>Chain them: <code>pass_region-us_session-x9k2_lifetime-30m</code>. Same gateway keys as the storefront.</div>
<script>function gb(){{var p='yourpassword'+document.getElementById('geoK').value+document.getElementById('geoS').value;document.getElementById('geoOut').textContent=p}}</script></div>
<div class=card><b>Rent more</b> — buy GB plans &amp; geo-targeted sessions at the storefront:
<a href="{PLEIADES_APP}" style=color:var(--acc)>{PLEIADES_APP}</a>.</div>
<div class=card style=color:var(--dim)>API: POST /api/proxy/test (user, pass) → egress IP + geo JSON.</div>"""
return page("proxy", body)
@app.route("/api/proxy/test", methods=["POST"])
def api_proxy_test():
user, pw = request.form.get("user",""), request.form.get("pass","")
pauth = base64.b64encode(f"{user}:{pw}".encode()).decode()
try:
s = socket.create_connection((PLEIADES_GW.split(":")[0], int(PLEIADES_GW.split(":")[1])), timeout=15)
s.sendall(f"CONNECT ip-api.com:80 HTTP/1.1\r\nHost: ip-api.com:80\r\nProxy-Authorization: Basic {pauth}\r\n\r\n".encode())
resp = s.recv(4096)
if b"200" not in resp.split(b"\r\n")[0]: return jsonify({"ok": False, "raw": resp[:120].decode("utf-8","replace")})
s.sendall(b"GET /json/?fields=66846719 HTTP/1.1\r\nHost: ip-api.com\r\nConnection: close\r\n\r\n")
data = b""
while True:
c = s.recv(8192)
if not c: break
data += c
s.close()
j = jf(data.split(b"\r\n\r\n",1)[-1].decode("utf-8","replace")) or {}
return jsonify({"ok": True, "egress": j})
except Exception as e:
return jsonify({"ok": False, "error": str(e)})
# ---------- 5. FREE TOOLS ----------
TOOLS_JS = """
function tab(n){document.querySelectorAll('.pane').forEach(p=>p.style.display='none');document.getElementById(n).style.display='block';
document.querySelectorAll('.tbtn').forEach(b=>b.classList.remove('on'));event.target.classList.add('on')}
async function dns(){const d=document.getElementById('dq').value;const o=await (await fetch('https://dns.google/resolve?name='+encodeURIComponent(d)+'&type=A')).json();document.getElementById('do').textContent=JSON.stringify(o,null,1)}
async function hdr(){const u=document.getElementById('hq').value;const r=await (await fetch('/api/hdr?url='+encodeURIComponent(u))).json();document.getElementById('ho').textContent=JSON.stringify(r,null,1)}
function jwt(){try{const t=document.getElementById('jq').value.trim().split('.');const d=s=>JSON.stringify(JSON.parse(atob(s.replace(/-/g,'+').replace(/_/g,'/'))),null,1);document.getElementById('jo').textContent='HEADER\\n'+d(t[0])+'\\n\\nPAYLOAD\\n'+d(t[1])+'\\n\\n(signature: '+t[2]+')'}catch(e){document.getElementById('jo').textContent='Invalid JWT: '+e}}
function genhash(){const i=document.getElementById('hq2').value;['md5','sha1','sha256','sha512'].forEach(a=>{document.getElementById('h_'+a).textContent=hashlib(a,i)})}
function hashlib(a,s){return a}
async function genhash2(){const i=document.getElementById('hq2').value;const r=await(await fetch('/api/hash?s='+encodeURIComponent(i))).json();for(const k of ['md5','sha1','sha256','sha512'])document.getElementById('h_'+k).textContent=r[k]}
function uuids(){let o='';for(let i=0;i<5;i++)o+=crypto.randomUUID()+'\\n';document.getElementById('uo').textContent=o}
function pwgen(){const l=+document.getElementById('pl').value||24;const cs='abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%^&*-_=+';const a=new Uint32Array(l);crypto.getRandomValues(a);document.getElementById('po').textContent=Array.from(a,x=>cs[x%cs.length]).join('')}
"""
@app.route("/api/hdr")
def api_hdr():
url = request.args.get("url","")
if "://" not in url: url = "http://" + url
try:
req = urllib.request.Request(url, headers={"User-Agent":"Auriga/1.0"})
with urllib.request.urlopen(req, timeout=12) as r:
return jsonify({"status": r.status, "final_url": r.url, "headers": dict(r.headers)})
except Exception as e:
return jsonify({"error": str(e)})
@app.route("/api/hash")
def api_hash():
s = request.args.get("s","").encode()
return jsonify({"md5": hashlib.md5(s).hexdigest(), "sha1": hashlib.sha1(s).hexdigest(),
"sha256": hashlib.sha256(s).hexdigest(), "sha512": hashlib.sha512(s).hexdigest()})
@app.route("/tools")
def tools():
body = f"""
<h1>FREE <span>TOOLS</span></h1><p class=sub>High-value, zero-cost, no signup. Agent-friendly APIs underneath each.</p>
<style>.tbtn.on{{background:var(--acc);color:#111}}</style>
<div style=margin-bottom:1rem>
<button class="tbtn on" onclick="tab('dns_p')">DNS Lookup</button>
<button class=tbtn onclick="tab('hdr_p')">HTTP Headers</button>
<button class=tbtn onclick="tab('jwt_p')">JWT Decoder</button>
<button class=tbtn onclick="tab('hash_p')">Hasher</button>
<button class=tbtn onclick="tab('gen_p')">Generators</button></div>
<script>{TOOLS_JS}</script>
<div id=dns_p class="card pane"><b>DNS Lookup</b> <span style=color:var(--dim)>(Google DoH)</span><br>
<input id=dq placeholder=thetempleofdoom.com style=width:70%><button onclick=dns()>Resolve</button>
<pre id=do style=white-space:pre-wrap></pre><div style=color:var(--dim)>API: /api/hdr style JSON via dns.google</div></div>
<div id=hdr_p class="card pane" style=display:none><b>HTTP Header Inspector</b><br>
<input id=hq placeholder=https://lynx.thetempleofdoom.com style=width:70%><button onclick=hdr()>Inspect</button>
<pre id=ho style=white-space:pre-wrap></pre><div style=color:var(--dim)>API: GET /api/hdr?url=…</div></div>
<div id=jwt_p class="card pane" style=display:none><b>JWT Decoder</b> (client-side, token never leaves your browser)<br>
<textarea id=jq rows=3 style="width:100%">paste eyJ…</textarea><button onclick=jwt()>Decode</button>
<pre id=jo style=white-space:pre-wrap></pre></div>
<div id=hash_p class="card pane" style=display:none><b>Hasher</b><br>
<input id=hq2 placeholder="any string" style=width:70%><button onclick=genhash2()>Hash</button>
<table><tr><th>md5</th><td id=h_md5></td></tr><tr><th>sha1</th><td id=h_sha1></td></tr>
<tr><th>sha256</th><td id=h_sha256></td></tr><tr><th>sha512</th><td id=h_sha512></td></tr></table>
<div style=color:var(--dim)>API: GET /api/hash?s=…</div></div>
<div id=gen_p class="card pane" style=display:none><b>Generators</b><br>
<button onclick=uuids()>5× UUIDv4</button><pre id=uo></pre>
<label>password length</label> <input id=pl value=24 style=width:80px><button onclick=pwgen()>Generate</button>
<pre id=po style="font-size:1.2rem;color:var(--acc)"></pre></div>"""
return page("tools", body)
@app.route("/")
def index():
st, b = http(f"http://ip-api.com/json/{request.headers.get('X-Real-IP') or request.remote_addr}?fields=66846719")
d = jf(b) or {}
con = db()
n_sms = con.execute("SELECT COUNT(*) c FROM sms_rentals").fetchone()["c"]
n_px = con.execute("SELECT COUNT(*) c FROM proxy_checks").fetchone()["c"]
body = f"""
<h1>AURIGA <span>TOOLBOX</span></h1>
<p class=sub>One page. Every network weapon you actually use. No signup, no fluff.</p>
<div class=grid2>
<div class=card><h3>◈ Whats-My-IP MAX</h3><p style=color:var(--dim)>You're connecting from <b style=color:var(--acc)>{d.get('query','?')}</b> — {d.get('city','')}, {d.get('country','')}. Full dump: geo, ASN, ISP, VPN flags, rDNS, headers.</p><a href=/ip><button>Open</button></a> <a href=/api/ip><button style=background:#232b45;color:var(--fg)>API</button></a></div>
<div class=card><h3>◈ Card Check</h3><p style=color:var(--dim)>Luhn + BIN: brand, issuer, country, type, prepaid risk flags. Nothing stored, nothing charged.</p><a href=/card><button>Open</button></a></div>
<div class=card><h3>◈ SMS Rental</h3><p style=color:var(--dim)>Disposable numbers, 30-minute windows, cancel = refund. {n_sms} rentals served.</p><a href=/sms><button>Open</button></a></div>
<div class=card><h3>◈ Proxy Lab</h3><p style=color:var(--dim)>Test + rent residential proxies. Same gateway keys as the other sites. {n_px} checks run.</p><a href=/proxy><button>Open</button></a></div>
<div class=card><h3>◈ Free Tools</h3><p style=color:var(--dim)>DNS, HTTP headers, JWT, hasher, UUID/password generators.</p><a href=/tools><button>Open</button></a></div>
<div class=card><h3>◈ API-first</h3><p style=color:var(--dim)>Every tool has a JSON API. Agents welcome — that's the point.</p></div>
</div>"""
return page("ip", body)
@app.route("/health")
def health(): return jsonify({"ok": True, "service": "auriga"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, threaded=True)