from flask import Flask, request, render_template_string
import requests
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
RIPESTAT_BASE = "https://stat.ripe.net/data"
HTML_TEMPLATE = """
{% if show_logo %}
{% endif %}
IP & RIPE Lookup
Il tuo IP pubblico è:
{{ ip }}
{% if ripe %}
Informazioni RIPE
{% 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 %}
{% if ripe.reverse_dns %}
Reverse DNS: {{ ripe.reverse_dns }}
{% endif %}
{% if ripe.geoloc %}
GeoLocation:
{% if ripe.geoloc.code %}

{% endif %}
{{ ripe.geoloc.country }}
{% endif %}
{% if ripe.abuse %}
Abuse Contact: {{ ripe.abuse }}
{% endif %}
Dati ottenuti tramite RIPEstat Data API.
{% else %}
Informazioni RIPE
Non è stato possibile recuperare i dettagli RIPE per questo indirizzo.
{% endif %}
"""
def get_client_ip():
"""Determina l'IP reale del client dietro proxy / load balancer."""
xff = request.headers.get("X-Forwarded-For", "")
if xff:
parts = [p.strip() for p in xff.split(",") if p.strip()]
if parts:
return parts[0]
xri = request.headers.get("X-Real-IP")
if xri:
return xri.strip()
return request.remote_addr or "Sconosciuto"
def fetch_ripe_info(ip: str):
"""Recupera informazioni RIPEstat estese per l'IP."""
info = {
"prefix": None,
"asns": [],
"holder": None,
"routing_status": None,
"reverse_dns": None,
"geoloc": None,
"abuse": None,
}
try:
# 1. Network info (prefisso + ASN)
ni = requests.get(
f"{RIPESTAT_BASE}/network-info/data.json",
params={"resource": ip},
timeout=2,
).json().get("data", {})
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(
f"{RIPESTAT_BASE}/as-overview/data.json",
params={"resource": asns[0]},
timeout=2,
).json().get("data", {})
info["holder"] = ao.get("holder")
# 3. Routing status / visibility
rs = requests.get(
f"{RIPESTAT_BASE}/routing-status/data.json",
params={"resource": ip},
timeout=2,
).json().get("data", {})
info["routing_status"] = rs.get("status")
# 4. Reverse DNS
rd = 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
# 5. GeoLocation
gl = 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"),
}
# 6. Abuse Contact
ac = 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
except Exception:
# In caso di errore lasciamo info parziali / vuote
pass
return info
@app.route("/")
def index():
ip = get_client_ip()
ripe_info = fetch_ripe_info(ip) if ip != "Sconosciuto" else None
return render_template_string(
HTML_TEMPLATE,
ip=ip,
ripe=ripe_info,
show_logo=True,
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)