From 12c66668837732f7c3b80df4b07c3cf07f892fbe Mon Sep 17 00:00:00 2001 From: it00147 Date: Tue, 2 Dec 2025 17:10:50 +0000 Subject: [PATCH] Improved version --- app.py | 216 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 169 insertions(+), 47 deletions(-) diff --git a/app.py b/app.py index 86d970b..886e7b6 100644 --- a/app.py +++ b/app.py @@ -53,12 +53,6 @@ HTML_TEMPLATE = """ {% if ripe.holder %}
Provider: {{ ripe.holder }}
{% endif %} - {% if ripe.prefix %} -
Prefisso annunciato: {{ ripe.prefix }}
- {% endif %} - {% if ripe.asns %} -
ASN: {{ ripe.asns | join(', ') }}
- {% endif %} {% if ripe.routing_status %}
Routing Status: {{ ripe.routing_status }}
{% endif %} @@ -78,6 +72,26 @@ HTML_TEMPLATE = """
Abuse Contact: {{ ripe.abuse }}
{% endif %} + {% if ripe.netname %} +
Netname: {{ ripe.netname }}
+ {% endif %} + + {% if ripe.org_name %} +
Organisation: {{ ripe.org_name }}
+ {% endif %} + + {% if ripe.rir %} +
RIR: {{ ripe.rir }}
+ {% endif %} + + {% if ripe.block %} +
IP Block: {{ ripe.block }}
+ {% endif %} + + {% if ripe.rir %} +
RIR: {{ ripe.rir }}
+ {% endif %} +
Dati ottenuti tramite RIPEstat Data API.
{% else %}
Informazioni RIPE
@@ -160,9 +174,9 @@ def get_client_ip(): return request.remote_addr or "Sconosciuto" - def fetch_ripe_info(ip: str): - """Recupera informazioni RIPEstat estese per l'IP.""" + """Recupera informazioni RIPEstat estese per l'IP, compatibili col template.""" + info = { "prefix": None, "asns": [], @@ -171,76 +185,173 @@ def fetch_ripe_info(ip: str): "reverse_dns": None, "geoloc": None, "abuse": None, + # campi extra che stai già usando in pagina + "block": None, + "rir": None, + "country": None, # non usato ora in UI + "country_whois": None, # usato in "Country (WHOIS)" + "netname": None, # usato in "Netname" + "org_name": None, + "raw": {}, # solo per debug } try: - # 1. Network info (prefisso + ASN) - ni = requests.get( + # 0) PREFIX-OVERVIEW: blocco IP + RIR + stato announced/routed + po_resp = requests.get( + f"{RIPESTAT_BASE}/prefix-overview/data.json", + params={"resource": ip}, + timeout=2, + ) + po = po_resp.json().get("data", {}) + info["raw"]["prefix_overview"] = po + + if po: + # es: 77.43.64.0/18 + info["block"] = po.get("resource") + # es: block.desc = "RIPE NCC (Status: ALLOCATED)" + block = po.get("block") or {} + desc = block.get("desc") + if desc: + # prendiamo la parte prima della parentesi + info["rir"] = desc.split("(")[0].strip() + + # announced / routed (bool) + info["routing_status"] = None + if po.get("announced") is not None: + info["routing_status"] = "Announced" if po.get("announced") else "Not announced" + + # prefix principale + if not info["prefix"]: + info["prefix"] = po.get("resource") + + # 1) NETWORK-INFO: prefisso + ASNs + ni_resp = requests.get( f"{RIPESTAT_BASE}/network-info/data.json", params={"resource": ip}, timeout=2, - ).json().get("data", {}) + ) + ni = ni_resp.json().get("data", {}) + info["raw"]["network_info"] = ni - info["prefix"] = ni.get("prefix") - asns = ni.get("asns") or [] - info["asns"] = [f"AS{a}" for a in asns] + if ni: + if not info["prefix"]: + info["prefix"] = ni.get("prefix") + asns = ni.get("asns") or [] + info["asns"] = [f"AS{a}" for a in asns] - # 2. AS overview (holder/provider) - if asns: - ao = requests.get( + # 2) AS-OVERVIEW: holder/provider (es: "AS-IRIDEOS - Retelit Digital Services S.p.A.") + if ni and ni.get("asns"): + ao_resp = requests.get( f"{RIPESTAT_BASE}/as-overview/data.json", - params={"resource": asns[0]}, + params={"resource": ni["asns"][0]}, timeout=2, - ).json().get("data", {}) - info["holder"] = ao.get("holder") + ) + ao = ao_resp.json().get("data", {}) + info["raw"]["as_overview"] = ao + if ao: + info["holder"] = ao.get("holder") or info["holder"] - # 3. Routing status / visibility - rs = requests.get( + # 3) ROUTING-STATUS: origin AS + visibilità + rs_resp = requests.get( f"{RIPESTAT_BASE}/routing-status/data.json", - params={"resource": ip}, + params={"resource": info["prefix"] or ip}, timeout=2, - ).json().get("data", {}) - info["routing_status"] = rs.get("status") + ) + rs = rs_resp.json().get("data", {}) + info["raw"]["routing_status"] = rs - # 4. Reverse DNS - rd = requests.get( + if rs: + origins = rs.get("origins") or [] + origin_as = None + if origins: + origin_as = origins[0].get("origin") + v4 = (rs.get("visibility") or {}).get("v4") or {} + peers = v4.get("ris_peers_seeing") + total = v4.get("total_ris_peers") + + if origin_as and peers is not None and total is not None: + info["routing_status"] = f"Origin AS{origin_as}, visibility {peers}/{total} peers" + elif origin_as: + info["routing_status"] = f"Origin AS{origin_as}" + + # 4) REVERSE-DNS + rd_resp = requests.get( f"{RIPESTAT_BASE}/reverse-dns/data.json", params={"resource": ip}, timeout=2, - ).json().get("data", {}).get("result", []) - info["reverse_dns"] = rd[0].get("name") if rd else None + ) + rd = rd_resp.json().get("data", {}).get("result", []) + info["raw"]["reverse_dns"] = rd + if rd: + info["reverse_dns"] = rd[0].get("name") - # 5. GeoLocation - gl = requests.get( + # 5) GEOLOC (usa located_resources → locations) + gl_resp = requests.get( f"{RIPESTAT_BASE}/geoloc/data.json", params={"resource": ip}, timeout=2, - ).json().get("data", {}) - country = None - if gl.get("locations"): - country = gl["locations"][0].get("country", {}) - if country: - info["geoloc"] = { - "country": country.get("name"), - "code": country.get("code"), - } + ) + gl = gl_resp.json().get("data", {}) + info["raw"]["geoloc"] = gl - # 6. Abuse Contact - ac = requests.get( + located_resources = gl.get("located_resources") or [] + if located_resources: + first_res = located_resources[0] + locs = first_res.get("locations") or [] + if locs: + loc0 = locs[0] + city = loc0.get("city") + country_code = loc0.get("country") + # flagsapi vuole il codice (es: IT) + label = country_code + if city and country_code: + label = f"{city}, {country_code}" + + info["geoloc"] = { + "country": label, + "code": country_code, + } + + # 6) ABUSE CONTACT (abuse_contacts, non emails) + ac_resp = requests.get( f"{RIPESTAT_BASE}/abuse-contact-finder/data.json", params={"resource": ip}, timeout=2, - ).json().get("data", {}) - emails = ac.get("emails") or [] - info["abuse"] = emails[0] if emails else None + ) + ac = ac_resp.json().get("data", {}) + info["raw"]["abuse"] = ac + + abuse_contacts = ac.get("abuse_contacts") or [] + if abuse_contacts: + info["abuse"] = abuse_contacts[0] + + # 7) WHOIS: netname, country (WHOIS), org / descr + whois_resp = requests.get( + f"{RIPESTAT_BASE}/whois/data.json", + params={"resource": ip}, + timeout=3, + ) + whois = whois_resp.json().get("data", {}) + info["raw"]["whois"] = whois + + records = whois.get("records") or [] + for block in records: + for entry in block: + k = entry.get("key", "").lower() + v = entry.get("value", "") + + if k == "netname" and not info["netname"]: + info["netname"] = v + elif k == "country" and not info["country_whois"]: + info["country_whois"] = v + elif k in ("org-name", "organisation", "descr") and not info["org_name"]: + info["org_name"] = v except Exception: - # In caso di errore lasciamo info parziali / vuote pass return info - @app.route("/") def index(): ip = get_client_ip() @@ -261,5 +372,16 @@ def debug(): all_headers=dict(request.headers), ) +@app.route("/ripe-debug") +def ripe_debug(): + from flask import jsonify + ip = get_client_ip() + ripe_info = fetch_ripe_info(ip) if ip != "Sconosciuto" else None + return jsonify({ + "ip": ip, + "ripe": ripe_info, + }) + + if __name__ == "__main__": app.run(host="0.0.0.0", port=8000)