secutorpro's picture
🐳 06/08 - 16:52 - {  "$schema": "https://opencode.ai/config.jsonc",  "mcp": {    "hf-mcp-server": {      "type": "remote",      "url": "https://huggingface.co/mcp?login",      "enabled": true    }  }
8d409ab verified
Raw History Blame Contribute Delete
6.41 kB
<?php
// =====================================================
// SentinelAI - Server-side API Proxy
// Routes all external API calls through the backend to
// avoid exposing API keys or direct endpoints in the browser.
// =====================================================
header('Content-Type: application/json');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: no-referrer');
$allowedServices = [
'lookupIP',
'searchCVEs',
'getCVE',
'resolveDomain',
'lookupIPNinjas',
'whoisLookup',
'dnsLookupNinjas',
'shortenURL',
'generatePassword',
];
$input = json_decode((string) file_get_contents('php://input'), true) ?: [];
$service = $_REQUEST['service'] ?? ($input['service'] ?? '');
if (!in_array($service, $allowedServices, true)) {
http_response_code(400);
echo json_encode(['error' => 'Invalid or missing service']);
exit;
}
// --- Secrets (move to environment variables in production) ---
function envOrDefault(string $key, string $default = ''): string {
$value = getenv($key);
return ($value !== false && $value !== '') ? $value : $default;
}
$apiNinjasKey = envOrDefault('SENTINEL_API_NINJAS_KEY', 'qOAsqB3zCY08kez2FC5nebZFiD3QDcVOmeShndAB');
// --- HTTP helper ---
function httpGet(string $url, array $headers = []): array {
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_USERAGENT => 'SentinelAI-Proxy/2.0',
]);
$body = curl_exec($ch);
$err = curl_error($ch);
$code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || $err !== '') {
return ['error' => "cURL error: {$err}", 'httpCode' => $code];
}
return ['body' => $body, 'httpCode' => $code];
}
// Fallback for hosts without cURL
$opts = [
'http' => [
'method' => 'GET',
'header' => implode("\r\n", array_merge(['User-Agent: SentinelAI-Proxy/2.0'], $headers)),
'timeout' => 20,
],
'ssl' => ['verify_peer' => true],
];
$context = stream_context_create($opts);
$body = @file_get_contents($url, false, $context);
if ($body === false) {
$status = $http_response_header[0] ?? 'HTTP/1.0 0 Error';
return ['error' => 'HTTP request failed: ' . $status, 'httpCode' => 0];
}
return ['body' => $body, 'httpCode' => 200];
}
function outputJsonError(int $code, string $message): void {
http_response_code($code);
echo json_encode(['error' => $message]);
exit;
}
// --- Input helpers ---
$keyword = $_REQUEST['keyword'] ?? ($input['keyword'] ?? '');
$limit = (int) ($_REQUEST['limit'] ?? ($input['limit'] ?? 20));
$limit = max(1, min(50, $limit));
$ip = $_REQUEST['ip'] ?? ($input['ip'] ?? '');
$ip = filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '';
$domain = $_REQUEST['domain'] ?? ($input['domain'] ?? '');
$domain = preg_replace('/[^a-zA-Z0-9.\-]/', '', $domain);
$cveId = $_REQUEST['cveId'] ?? ($input['cveId'] ?? '');
$cveId = preg_replace('/[^A-Za-z0-9\-]/', '', $cveId);
$address = $_REQUEST['address'] ?? ($input['address'] ?? '8.8.8.8');
$address = filter_var($address, FILTER_VALIDATE_IP) ? $address : '8.8.8.8';
$url = $_REQUEST['url'] ?? ($input['url'] ?? '');
$length = max(4, min(50, (int) ($_REQUEST['length'] ?? ($input['length'] ?? 16))));
// --- Dispatch ---
$result = null;
switch ($service) {
case 'lookupIP':
$targetUrl = $ip !== '' ? "https://ipinfo.io/{$ip}/json" : 'https://ipinfo.io/json';
$result = httpGet($targetUrl);
break;
case 'searchCVEs':
if ($keyword === '') {
outputJsonError(400, 'Missing keyword');
}
$targetUrl = 'https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=' . rawurlencode($keyword) . '&resultsPerPage=' . $limit;
$result = httpGet($targetUrl);
break;
case 'getCVE':
if ($cveId === '') {
outputJsonError(400, 'Missing cveId');
}
$targetUrl = 'https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=' . rawurlencode($cveId);
$result = httpGet($targetUrl);
break;
case 'resolveDomain':
if ($domain === '') {
outputJsonError(400, 'Missing domain');
}
$targetUrl = 'https://dns.google/resolve?name=' . rawurlencode($domain) . '&type=A';
$result = httpGet($targetUrl);
break;
case 'lookupIPNinjas':
$targetUrl = 'https://api.api-ninjas.com/v1/iplookup?address=' . rawurlencode($address);
$result = httpGet($targetUrl, ['X-Api-Key: ' . $apiNinjasKey]);
break;
case 'whoisLookup':
if ($domain === '') {
outputJsonError(400, 'Missing domain');
}
$targetUrl = 'https://api.api-ninjas.com/v1/whois?domain=' . rawurlencode($domain);
$result = httpGet($targetUrl, ['X-Api-Key: ' . $apiNinjasKey]);
break;
case 'dnsLookupNinjas':
if ($domain === '') {
outputJsonError(400, 'Missing domain');
}
$targetUrl = 'https://api.api-ninjas.com/v1/dnslookup?domain=' . rawurlencode($domain);
$result = httpGet($targetUrl, ['X-Api-Key: ' . $apiNinjasKey]);
break;
case 'shortenURL':
if ($url === '') {
outputJsonError(400, 'Missing url');
}
$targetUrl = 'https://api.api-ninjas.com/v1/shortenurl?url=' . rawurlencode($url);
$result = httpGet($targetUrl, ['X-Api-Key: ' . $apiNinjasKey]);
break;
case 'generatePassword':
$targetUrl = 'https://api.api-ninjas.com/v1/passwordgenerator?length=' . $length;
$result = httpGet($targetUrl, ['X-Api-Key: ' . $apiNinjasKey]);
break;
}
if ($result === null) {
outputJsonError(500, 'Proxy dispatch failed');
}
if (isset($result['error'])) {
outputJsonError(502, $result['error']);
}
// Forward JSON if possible, otherwise raw body
$decoded = json_decode($result['body'], true);
if (json_last_error() === JSON_ERROR_NONE) {
echo json_encode($decoded);
} else {
echo $result['body'];
}