Non è stato possibile recuperare i dettagli RIPE per questo indirizzo.
{% endif %}
"""
import ipaddress
from flask import Flask, request, render_template_string
# ...
def _is_private_ip(ip: str) -> bool:
try:
return ipaddress.ip_address(ip).is_private
except ValueError:
# se non è un IP valido, lo consideriamo "non utilizzabile"
return True
def get_client_ip():
"""
Prova a determinare l'IP pubblico del client:
- prende la lista da X-Forwarded-For
- sceglie il primo IP NON privato (non 10.x/192.168/172.16/127.x ecc.)
- fallback su X-Real-IP
- fallback su request.remote_addr
"""
# 1) X-Forwarded-For: "client, proxy1, proxy2..."
xff = request.headers.get("X-Forwarded-For", "")
if xff:
parts = [p.strip() for p in xff.split(",") if p.strip()]
# cerco il primo IP pubblico nella lista
for ip in parts:
if not _is_private_ip(ip):
return ip
# se proprio non trovo nulla di pubblico, prendo il primo
if parts:
return parts[0]
# 2) X-Real-IP
xri = request.headers.get("X-Real-IP")
if xri and not _is_private_ip(xri):
return xri.strip()
# 3) Fallback: remote_addr così com'è
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)
@app.route("/debug")
def debug():
from flask import jsonify
return jsonify(
remote_addr=request.remote_addr,
x_forwarded_for=request.headers.get("X-Forwarded-For"),
x_real_ip=request.headers.get("X-Real-IP"),
all_headers=dict(request.headers),
)