mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
102 lines
2.7 KiB
JavaScript
102 lines
2.7 KiB
JavaScript
// IP Resolver Helper
|
|
// Purpose: Resolves client IP addresses from request/socket metadata and proxy headers. Scope: Normalizes IP extraction so auth/logging services use consistent address values.
|
|
const net = require('net');
|
|
|
|
function extractForwardedIp(value) {
|
|
if (typeof value === 'string' && value.trim()) {
|
|
return value.split(',')[0].trim();
|
|
}
|
|
if (Array.isArray(value) && value.length) {
|
|
return String(value[0]).trim();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function normalizeIp(value) {
|
|
if (!value) return null;
|
|
let ip = String(value).trim();
|
|
if (!ip) return null;
|
|
if (ip.startsWith('::ffff:')) {
|
|
ip = ip.slice(7);
|
|
}
|
|
if (ip.includes('%')) {
|
|
ip = ip.split('%')[0];
|
|
}
|
|
return ip.trim() || null;
|
|
}
|
|
|
|
function isPrivateIpv4(ip) {
|
|
const parts = ip.split('.').map((part) => Number(part));
|
|
if (parts.length !== 4 || parts.some((part) => Number.isNaN(part))) {
|
|
return false;
|
|
}
|
|
const [a, b] = parts;
|
|
if (a === 10) return true;
|
|
if (a === 127) return true;
|
|
if (a === 192 && b === 168) return true;
|
|
return a === 172 && b >= 16 && b <= 31;
|
|
}
|
|
|
|
function isPrivateIpv6(ip) {
|
|
const lower = ip.toLowerCase();
|
|
if (lower === '::1') return true;
|
|
if (lower.startsWith('fc') || lower.startsWith('fd')) return true; // fc00::/7
|
|
return (
|
|
lower.startsWith('fe8') ||
|
|
lower.startsWith('fe9') ||
|
|
lower.startsWith('fea') ||
|
|
lower.startsWith('feb')
|
|
); // fe80::/10
|
|
}
|
|
|
|
function isLocalNetwork(ip) {
|
|
const normalized = normalizeIp(ip);
|
|
if (!normalized) return false;
|
|
const version = net.isIP(normalized);
|
|
if (version === 4) {
|
|
return isPrivateIpv4(normalized);
|
|
}
|
|
if (version === 6) {
|
|
return isPrivateIpv6(normalized);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function getSocketIp(socket) {
|
|
if (!socket) return null;
|
|
const headers = socket.handshake?.headers || {};
|
|
const forwarded = extractForwardedIp(headers['x-forwarded-for']);
|
|
if (forwarded) return forwarded;
|
|
const realIp = headers['x-real-ip'];
|
|
if (typeof realIp === 'string' && realIp.trim()) {
|
|
return realIp.trim();
|
|
}
|
|
return (
|
|
socket.handshake?.address ||
|
|
socket.conn?.remoteAddress ||
|
|
socket.request?.connection?.remoteAddress ||
|
|
null
|
|
);
|
|
}
|
|
|
|
function getRequestIp(req, override) {
|
|
const fromOverride = extractForwardedIp(override);
|
|
if (fromOverride) return fromOverride;
|
|
if (!req) return null;
|
|
const headers = req.headers || {};
|
|
const forwarded = extractForwardedIp(headers['x-forwarded-for']);
|
|
if (forwarded) return forwarded;
|
|
const realIp = headers['x-real-ip'];
|
|
if (typeof realIp === 'string' && realIp.trim()) {
|
|
return realIp.trim();
|
|
}
|
|
return req.ip || req.connection?.remoteAddress || null;
|
|
}
|
|
|
|
module.exports = {
|
|
getSocketIp,
|
|
getRequestIp,
|
|
isLocalNetwork,
|
|
normalizeIp,
|
|
};
|