Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,21 @@ def _ping(host: str) -> float | None:
return None


def _get_client_ip(request: Request) -> str:
"""Retrieve the real client IP from the request.

Checks common proxy headers (``CF-Connecting-IP`` and ``X-Forwarded-For``)
before falling back to ``request.client.host``.
"""
cf_ip = request.headers.get("cf-connecting-ip")
if cf_ip:
return cf_ip
forwarded = request.headers.get("x-forwarded-for")
if forwarded:
return forwarded.split(",")[0].strip()
return request.client.host


@app.get("/admin/login", response_class=HTMLResponse, include_in_schema=False)
def login_form(request: Request):
return templates.TemplateResponse("login.html", {"request": request})
Expand All @@ -209,7 +224,7 @@ def register(
{"request": request, "error": "Username already exists"},
status_code=400,
)
ip = request.client.host or "0.0.0.0"
ip = _get_client_ip(request) or "0.0.0.0"
last = ip.split(".")[-1]
password = f"nodeprobe{last}"
user = models.User(
Expand Down Expand Up @@ -290,7 +305,7 @@ def probe_page(request: Request, db: Session = Depends(get_db)):
``/tests`` API which aggregates records from the last ten minutes.
"""

client_ip = request.client.host
client_ip = _get_client_ip(request)
data = {"client_ip": client_ip, "test_target": "default"}

ping_ms = _ping(client_ip)
Expand Down Expand Up @@ -367,7 +382,7 @@ def create_test(
record: schemas.TestRecordCreate, request: Request, db: Session = Depends(get_db)
):
data = record.dict()
client_ip = request.client.host
client_ip = _get_client_ip(request)
data.setdefault("client_ip", client_ip)

if not data.get("location") or not data.get("asn") or not data.get("isp"):
Expand Down
10 changes: 10 additions & 0 deletions backend/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ def test_homepage_handles_null_client_ip():
db.close()


def test_homepage_uses_forwarded_for_header():
ip = "127.0.0.2"
res = client.get("/probe", headers={"X-Forwarded-For": ip})
assert res.status_code == 200
res_records = client.get("/tests")
data = res_records.json()
ips = [r.get("client_ip") for r in data.get("records", [])]
assert ip in ips


def test_ping_endpoint_localhost():
res = client.get("/ping", params={"host": "127.0.0.1", "count": 1})
data = res.json()
Expand Down