Files
portspoof_concentrator/api/frequent_ips.php
2026-03-16 11:02:43 -04:00

93 lines
3.2 KiB
PHP

<?php
/**
* GET /api/frequent_ips.php
*
* Returns all source IPs with a total connection count >= the configured
* threshold (frequent_ip_threshold setting, default 5), sorted highest first.
*
* Authentication (any one of):
* - Active web session (logged-in browser)
* - Authorization: Bearer <TRIGGER_TOKEN>
* - ?token=<TRIGGER_TOKEN>
*
* Optional query parameters:
* threshold int Override the configured minimum connection count
* since string YYYYMMDDHHmmss (e.g. "20260315000000"); only IPs
* with a last_seen >= this value are returned
*/
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/functions.php';
header('Content-Type: application/json');
// ── Auth ──────────────────────────────────────────────────────────────────────
$session_ok = false;
if (auth_enabled()) {
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$session_ok = !empty($_SESSION['authenticated']);
}
$token_ok = false;
if (TRIGGER_TOKEN !== '') {
$provided = '';
if (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
if (isset($requestHeaders['authorization'])) {
$authToken = $requestHeaders['authorization'];
$provided = substr($authToken, 7);
}
}
$auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (str_starts_with($auth_header, 'Bearer ')) {
$provided = substr($auth_header, 7);
}
if ($provided === '' && isset($_REQUEST['token'])) {
$provided = $_REQUEST['token'];
}
$token_ok = $provided !== '' && hash_equals(TRIGGER_TOKEN, $provided);
}
if (!$session_ok && !$token_ok) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
// ── Query ─────────────────────────────────────────────────────────────────────
$configured_threshold = max(1, (int)get_setting('frequent_ip_threshold', '5'));
$threshold = isset($_GET['threshold'])
? max(1, (int)$_GET['threshold'])
: $configured_threshold;
$since = null;
if (isset($_GET['since']) && $_GET['since'] !== '') {
$dt = DateTime::createFromFormat('YmdHis', $_GET['since']);
if ($dt === false) {
http_response_code(400);
echo json_encode(['error' => 'Invalid since parameter; expected YYYYMMDDHHmmss e.g. 20260315000000']);
exit;
}
$since = $dt->format('Y-m-d H:i:s');
}
$rows = frequent_ips($threshold, $since);
echo json_encode([
'threshold' => $threshold,
'configured_threshold' => $configured_threshold,
'since' => $since,
'count' => count($rows),
'ips' => array_map(fn($r) => [
'src_ip' => $r['src_ip'],
'total_connections' => (int)$r['total_connections'],
'first_seen' => $r['first_seen'],
'last_seen' => $r['last_seen'],
], $rows),
], JSON_PRETTY_PRINT);