diff --git a/server/geo-service.js b/server/geo-service.js index dc6e360..5b003b8 100644 --- a/server/geo-service.js +++ b/server/geo-service.js @@ -33,38 +33,49 @@ async function getLocation(target) { // Normalize target (strip port if present) const cleanTarget = target.split(':')[0]; - // Resolve domain to IP if needed - let cleanIp = cleanTarget; - if (net.isIP(cleanTarget) === 0) { - try { - console.log(`[Geo Service] Resolving domain to IP: ${cleanTarget}`); - const lookup = await dns.lookup(cleanTarget); - cleanIp = lookup.address; - } catch (err) { - console.error(`[Geo Service] DNS resolution failed for ${cleanTarget}:`, err.message); - return null; - } - } - - // Skip local/reserved IPs - if (isLocalIp(cleanIp)) { - return null; - } - - // Check database first + // 1. Check if we already have this IP/Domain in DB (FASTEST) try { - const [rows] = await db.query('SELECT * FROM server_locations WHERE ip = ?', [cleanIp]); + const [rows] = await db.query('SELECT * FROM server_locations WHERE ip = ?', [cleanTarget]); if (rows.length > 0) { - // Check if data is stale (e.g., older than 30 days) const data = rows[0]; const age = Date.now() - new Date(data.last_updated).getTime(); if (age < 30 * 24 * 60 * 60 * 1000) { return normalizeGeo(data); } } + } catch (err) { + // console.error(`[Geo Service] DB check failed for ${cleanTarget}`); + } - // Resolve via ipinfo.io - console.log(`[Geo Service] Resolving location for IP: ${cleanIp}`); + // 2. Resolve domain to IP if needed + let cleanIp = cleanTarget; + if (net.isIP(cleanTarget) === 0) { + try { + const lookup = await dns.lookup(cleanTarget); + cleanIp = lookup.address; + + // Secondary DB check with resolved IP + const [rows] = await db.query('SELECT * FROM server_locations WHERE ip = ?', [cleanIp]); + if (rows.length > 0) { + return normalizeGeo(rows[0]); + } + } catch (err) { + // Quiet DNS failure for tokens (legacy bug mitigation) + if (!/^[0-9a-f]{16}$/i.test(cleanTarget)) { + console.error(`[Geo Service] DNS resolution failed for ${cleanTarget}:`, err.message); + } + return null; + } + } + + // 3. Skip local/reserved IPs + if (isLocalIp(cleanIp)) { + return null; + } + + // 4. Resolve via ipinfo.io (LAST RESORT) + try { + console.log(`[Geo Service] API lookup (ipinfo.io) for: ${cleanIp}`); const url = `https://ipinfo.io/${cleanIp}/json${ipInfoToken ? `?token=${ipInfoToken}` : ''}`; const response = await axios.get(url, { timeout: 5000 }); const geo = normalizeGeo(response.data);