Fix agent detection: real client IP via CF header, tablet/iPad support, subnet fallback match

This commit is contained in:
2026-05-30 03:23:12 +00:00
parent 62c7878615
commit e08b80a6c6
2 changed files with 45 additions and 19 deletions
+3 -1
View File
@@ -213,7 +213,9 @@ switch ($agentAction) {
foreach ($agents as &$a) { foreach ($agents as &$a) {
$a['capabilities'] = json_decode($a['capabilities'] ?? '[]', true); $a['capabilities'] = json_decode($a['capabilities'] ?? '[]', true);
} }
agent_ok(['agents' => $agents, 'my_ip' => $_SERVER['REMOTE_ADDR'] ?? '']); $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
$realIp = trim(explode(',', $realIp)[0]);
agent_ok(['agents' => $agents, 'my_ip' => $realIp]);
// ── LATEST METRICS (for dashboard display) ─────────────────────────────── // ── LATEST METRICS (for dashboard display) ───────────────────────────────
case 'status': case 'status':
+42 -18
View File
@@ -1741,12 +1741,16 @@ function speak(text) {
// ── AGENT DETECTION & BROWSER INSTALL ───────────────────────────────── // ── AGENT DETECTION & BROWSER INSTALL ─────────────────────────────────
let _agentOnline = false; let _agentOnline = false;
let _myAgent = null;
function detectOS() { function detectOS() {
const ua = navigator.userAgent; const ua = navigator.userAgent;
const p = (navigator.platform || '').toLowerCase(); const p = (navigator.platform || '').toLowerCase();
if (p.includes('mac')) return 'mac'; // Tablets — check before desktop OS (iPads spoof MacIntel)
if (/iPad|Android/.test(ua) || (p.includes('mac') && navigator.maxTouchPoints > 1)) return 'tablet';
if (/iPhone/.test(ua)) return 'tablet';
if (p.includes('win') || ua.includes('Windows')) return 'windows'; if (p.includes('win') || ua.includes('Windows')) return 'windows';
if (p.includes('mac') || ua.includes('Macintosh')) return 'mac';
if (p.includes('linux') || ua.includes('Linux')) return 'linux'; if (p.includes('linux') || ua.includes('Linux')) return 'linux';
return 'unknown'; return 'unknown';
} }
@@ -1765,12 +1769,19 @@ async function checkAgentStatus() {
const cnt = document.getElementById('net-agent-count'); const cnt = document.getElementById('net-agent-count');
if (cnt) cnt.textContent = online.length + ' AGENT' + (online.length !== 1 ? 'S' : '') + ' ONLINE'; if (cnt) cnt.textContent = online.length + ' AGENT' + (online.length !== 1 ? 'S' : '') + ' ONLINE';
const myIp = data.my_ip || ''; const myIp = data.my_ip || '';
const myAgent = online.find(a => a.ip_address === myIp); // Match by exact IP first, then by same /24 subnet (handles NAT behind same router)
_agentOnline = !!myAgent; const mySubnet = myIp.split('.').slice(0,3).join('.');
_myAgent = online.find(a => a.ip_address === myIp)
|| online.find(a => a.ip_address && a.ip_address.startsWith(mySubnet + '.'));
_agentOnline = !!_myAgent;
if (btn) { if (btn) {
if (_agentOnline) { const isTablet = detectOS() === 'tablet';
if (isTablet) {
btn.title = 'JARVIS Agent — not available for tablets';
btn.style.opacity = '0.5';
} else if (_agentOnline) {
btn.classList.add('agent-online'); btn.classList.add('agent-online');
btn.title = 'Agent active: ' + myAgent.hostname; btn.title = 'Agent active: ' + _myAgent.hostname;
} else { } else {
btn.classList.remove('agent-online'); btn.classList.remove('agent-online');
btn.title = 'Click to install JARVIS Agent on this machine'; btn.title = 'Click to install JARVIS Agent on this machine';
@@ -1885,24 +1896,35 @@ function openAgentModal() {
const baseUrl = 'https://jarvis.orbishosting.com/agent'; const baseUrl = 'https://jarvis.orbishosting.com/agent';
const jUrl = 'https://jarvis.orbishosting.com'; const jUrl = 'https://jarvis.orbishosting.com';
if (_agentOnline) { if (os === 'tablet') {
title.textContent = '● JARVIS — TABLET / MOBILE';
content.innerHTML =
'<div style="color:var(--cyan);font-size:0.75rem;margin-bottom:12px">✓ You\'re viewing JARVIS on a tablet or mobile device.</div>' +
'<div style="color:var(--text-dim);font-size:0.65rem;line-height:1.6">The JARVIS Agent runs on desktop and server platforms (Windows, macOS, Linux).<br><br>' +
'Tablets and phones can browse the full JARVIS dashboard but do not need an agent installed — all data comes from your other monitored machines.</div>';
} else if (_agentOnline) {
title.textContent = '● AGENT CONNECTED'; title.textContent = '● AGENT CONNECTED';
content.innerHTML = '<div style="color:var(--green);font-size:0.75rem;margin-bottom:12px">✓ JARVIS Agent is running on this machine.</div>' + content.innerHTML =
'<div style="color:var(--text-dim);font-size:0.65rem">Reporting: CPU · Memory · Disk · Services · Uptime</div>'; '<div style="color:var(--green);font-size:0.75rem;margin-bottom:12px">✓ JARVIS Agent is active on this machine.</div>' +
'<div style="color:var(--text-dim);font-size:0.65rem;line-height:1.8">' +
'<b style="color:var(--text)">Host:</b> ' + (_myAgent?.hostname||'—') + '<br>' +
'<b style="color:var(--text)">IP:</b> ' + (_myAgent?.ip_address||'—') + '<br>' +
'<b style="color:var(--text)">Type:</b> ' + (_myAgent?.agent_type||'—').toUpperCase() + '<br>' +
'<b style="color:var(--text)">Reporting:</b> CPU · Memory · Disk · Services · Uptime</div>';
} else { } else {
const inst = { const inst = {
windows: {
label:'Windows',
cmd:'# Run PowerShell as Administrator:\nSet-ExecutionPolicy Bypass -Scope Process -Force\nInvoke-WebRequest -Uri "'+baseUrl+'/install-windows.ps1" -OutFile "$env:TEMP\\install.ps1"\n& "$env:TEMP\\install.ps1" -JarvisUrl '+jUrl+' -Key '+regKey,
dl: baseUrl+'/install-windows.ps1',
note:'Run PowerShell as Administrator. Installs as a Windows Task Scheduler service.'
},
mac: { mac: {
label:'macOS', label:'macOS',
cmd:'bash <(curl -sSL '+baseUrl+'/install-mac.sh) \\\n --jarvis-url '+jUrl+' \\\n --key '+regKey, cmd:'bash <(curl -sSL '+baseUrl+'/install-mac.sh) \\\n --jarvis-url '+jUrl+' \\\n --key '+regKey,
dl: baseUrl+'/install-mac.sh', dl: baseUrl+'/install-mac.sh',
note:'Run in Terminal. Installs as a launchd background service.' note:'Run in Terminal. Installs as a launchd background service.'
}, },
windows: {
label:'Windows',
cmd:'# Run PowerShell as Administrator:\nSet-ExecutionPolicy Bypass -Scope Process\nInvoke-WebRequest -Uri "'+baseUrl+'/install-windows.ps1" -OutFile install.ps1\n.\\install-windows.ps1 -JarvisUrl '+jUrl+' -Key '+regKey,
dl: baseUrl+'/install-windows.ps1',
note:'Run PowerShell as Administrator. Installs as Task Scheduler service.'
},
linux: { linux: {
label:'Linux', label:'Linux',
cmd:'curl -sSL '+baseUrl+'/install.sh | sudo bash -s -- \\\n --jarvis-url '+jUrl+' \\\n --key '+regKey, cmd:'curl -sSL '+baseUrl+'/install.sh | sudo bash -s -- \\\n --jarvis-url '+jUrl+' \\\n --key '+regKey,
@@ -1911,18 +1933,20 @@ function openAgentModal() {
}, },
unknown: { unknown: {
label:'Your System', label:'Your System',
cmd:'# Download from JARVIS server:\nhttps://jarvis.orbishosting.com/agent/', cmd:'# Browse installers:\nhttps://jarvis.orbishosting.com/agent/',
dl: 'https://jarvis.orbishosting.com/agent/', dl: 'https://jarvis.orbishosting.com/agent/',
note:'Select your platform from the GitHub repo.' note:'Choose your platform installer from the JARVIS agent directory.'
} }
}; };
const i = inst[os] || inst.unknown; const i = inst[os] || inst.unknown;
title.textContent = '● INSTALL AGENT · ' + i.label.toUpperCase(); const osBadge = {windows:'🪟 WINDOWS', mac:'🍎 MACOS', linux:'🐧 LINUX', unknown:'❓ UNKNOWN'}[os] || os.toUpperCase();
title.textContent = '● INSTALL AGENT · ' + (inst[os] ? inst[os].label.toUpperCase() : 'YOUR SYSTEM');
content.innerHTML = content.innerHTML =
'<div style="color:var(--cyan);font-size:0.65rem;letter-spacing:1px;margin-bottom:8px">DETECTED: ' + osBadge + '</div>' +
'<div style="color:var(--text-dim);font-size:0.65rem;margin-bottom:12px">'+i.note+'</div>' + '<div style="color:var(--text-dim);font-size:0.65rem;margin-bottom:12px">'+i.note+'</div>' +
'<pre id="agentCmdPre">'+i.cmd+'</pre>' + '<pre id="agentCmdPre">'+i.cmd+'</pre>' +
'<a class="agent-dl-btn" href="'+i.dl+'" target="_blank">↓ DOWNLOAD INSTALLER</a>' + '<a class="agent-dl-btn" href="'+i.dl+'" target="_blank">↓ DOWNLOAD INSTALLER</a>' +
'<div style="color:var(--text-dim);font-size:0.6rem;margin-top:16px;opacity:0.7">After install, this indicator turns green within 30 seconds.</div>'; '<div style="color:var(--text-dim);font-size:0.6rem;margin-top:16px;opacity:0.7">After install, the AGENT indicator turns green within 30 seconds.</div>';
} }
modal.classList.add('open'); modal.classList.add('open');
} }