From e6ee946cc3713acb9f80a95c2cea14d5a0e7efee Mon Sep 17 00:00:00 2001 From: MrUnknownDE Date: Sat, 29 Mar 2025 16:46:21 +0100 Subject: [PATCH] switch mac-lookup lib to oui --- backend/package-lock.json | 75 +++++++++------------------------------ backend/package.json | 2 +- backend/server.js | 47 ++++++++++++------------ 3 files changed, 42 insertions(+), 82 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 2a5b43f..c611fc4 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -14,26 +14,12 @@ "dotenv": "^16.4.7", "express": "^4.21.2", "express-rate-limit": "^7.5.0", - "mac-lookup": "^1.0.1", + "oui": "^13.0.5", "pino": "^9.6.0", "pino-pretty": "^13.0.0", "whois-json": "^2.0.4" } }, - "node_modules/@fast-csv/parse": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", - "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", - "dependencies": { - "@types/node": "^14.0.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.groupby": "^4.6.0", - "lodash.isfunction": "^3.0.9", - "lodash.isnil": "^4.0.0", - "lodash.isundefined": "^3.0.1", - "lodash.uniq": "^4.5.0" - } - }, "node_modules/@maxmind/geoip2-node": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@maxmind/geoip2-node/-/geoip2-node-6.0.0.tgz", @@ -42,11 +28,6 @@ "maxmind": "^4.2.0" } }, - "node_modules/@types/node": { - "version": "14.18.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==" - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -746,36 +727,6 @@ "node": ">=8" } }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==" - }, - "node_modules/lodash.groupby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==" - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" - }, - "node_modules/lodash.isnil": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==" - }, - "node_modules/lodash.isundefined": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, "node_modules/lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -789,14 +740,6 @@ "lower-case": "^1.1.2" } }, - "node_modules/mac-lookup": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mac-lookup/-/mac-lookup-1.0.1.tgz", - "integrity": "sha512-EZOUg4d/xg9l66cvBpG1PI8hYHvFd2nPID3asVGwvOk+Gse/LWCELcqEaWRh6Ws8HsroA9GGAzDdR3nMfTnVgQ==", - "dependencies": { - "@fast-csv/parse": "^4.3.0" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -956,6 +899,22 @@ "wrappy": "1" } }, + "node_modules/oui": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/oui/-/oui-13.0.5.tgz", + "integrity": "sha512-bAXoXcLrl3SweuEuh8aWpdTsfHka6B7Gh1SxsTZMXtWi9QSxQk7CupxWlP2QQ4olTDifaWAiQbROMxfarAQZlQ==", + "dependencies": { + "oui-data": "^1.1.76" + }, + "bin": { + "oui": "bin/oui.js" + } + }, + "node_modules/oui-data": { + "version": "1.1.314", + "resolved": "https://registry.npmjs.org/oui-data/-/oui-data-1.1.314.tgz", + "integrity": "sha512-F8r1LwdAucn6Fgq1KECZPMCpMgXPdhCblFOY/eQ6S83x5lfQQK9aRRIpz7dH6iQeAeqoSP1b4I8z4lqUaTwAvg==" + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", diff --git a/backend/package.json b/backend/package.json index 8cc9b54..b1c89f2 100644 --- a/backend/package.json +++ b/backend/package.json @@ -15,7 +15,7 @@ "dotenv": "^16.4.7", "express": "^4.21.2", "express-rate-limit": "^7.5.0", - "mac-lookup": "^1.0.1", + "oui": "^13.0.5", "pino": "^9.6.0", "pino-pretty": "^13.0.0", "whois-json": "^2.0.4" diff --git a/backend/server.js b/backend/server.js index 9cdae0c..e9c3b0c 100644 --- a/backend/server.js +++ b/backend/server.js @@ -9,7 +9,7 @@ const dns = require('dns').promises; const pino = require('pino'); // Logging library const rateLimit = require('express-rate-limit'); // Rate limiting middleware const whois = require('whois-json'); // Hinzugefügt für WHOIS -const macLookup = require('mac-lookup'); // Hinzugefügt für MAC Lookup +const oui = require('oui'); // Ersetzt mac-lookup // --- Logger Initialisierung --- const logger = pino({ @@ -99,6 +99,7 @@ function isValidMac(mac) { return false; } // Erlaubt Formate wie 00:1A:2B:3C:4D:5E, 00-1A-2B-3C-4D-5E, 001A.2B3C.4D5E + // oui() validiert intern, aber eine Vorabprüfung schadet nicht. const macRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$|^([0-9A-Fa-f]{4}\.){2}([0-9A-Fa-f]{4})$/; return macRegex.test(mac.trim()); } @@ -278,13 +279,12 @@ async function initialize() { asnReader = await geoip.Reader.open(asnDbPath); logger.info('MaxMind databases loaded successfully.'); - // Lade MAC-Lookup Daten (asynchron) - logger.info('Loading MAC address lookup data...'); - await macLookup.load(); // Lädt die Daten beim Start - logger.info('MAC address lookup data loaded.'); + // Kein explizites Laden mehr für 'oui' nötig. + // Die Daten werden bei der ersten Verwendung automatisch geladen/aktualisiert. + logger.info('MAC address lookup data (oui) will be loaded on first use.'); } catch (error) { - logger.fatal({ error: error.message, stack: error.stack }, 'Could not initialize databases or MAC data. Exiting.'); + logger.fatal({ error: error.message, stack: error.stack }, 'Could not initialize MaxMind databases. Exiting.'); process.exit(1); } } @@ -314,9 +314,9 @@ const generalLimiter = rateLimit({ app.use('/api/ping', generalLimiter); app.use('/api/traceroute', generalLimiter); app.use('/api/lookup', generalLimiter); -app.use('/api/dns-lookup', generalLimiter); // Neu -app.use('/api/whois-lookup', generalLimiter); // Neu -app.use('/api/mac-lookup', generalLimiter); // Neu +app.use('/api/dns-lookup', generalLimiter); +app.use('/api/whois-lookup', generalLimiter); +app.use('/api/mac-lookup', generalLimiter); // --- Routen --- @@ -668,13 +668,13 @@ app.get('/api/dns-lookup', async (req, res) => { if (!isValidDomain(domain)) { logger.warn({ requestIp, domain }, 'Invalid domain for DNS lookup'); - return res.status(400).json({ error: 'Invalid domain name provided.' }); + return res.status(400).json({ success: false, error: 'Invalid domain name provided.' }); } const validTypes = ['A', 'AAAA', 'MX', 'TXT', 'NS', 'CNAME', 'SOA', 'SRV', 'PTR', 'ANY']; if (!validTypes.includes(type)) { logger.warn({ requestIp, domain, type }, 'Invalid record type for DNS lookup'); - return res.status(400).json({ error: `Invalid record type provided. Valid types are: ${validTypes.join(', ')}` }); + return res.status(400).json({ success: false, error: `Invalid record type provided. Valid types are: ${validTypes.join(', ')}` }); } try { @@ -729,7 +729,7 @@ app.get('/api/whois-lookup', async (req, res) => { // Einfache Validierung: Muss entweder eine gültige IP oder eine Domain sein if (!isValidIp(query) && !isValidDomain(query)) { logger.warn({ requestIp, query }, 'Invalid query for WHOIS lookup'); - return res.status(400).json({ error: 'Invalid domain name or IP address provided for WHOIS lookup.' }); + return res.status(400).json({ success: false, error: 'Invalid domain name or IP address provided for WHOIS lookup.' }); } try { @@ -752,22 +752,22 @@ app.get('/api/whois-lookup', async (req, res) => { } }); -// MAC Address Lookup Endpunkt -app.get('/api/mac-lookup', async (req, res) => { +// MAC Address Lookup Endpunkt (mit 'oui' Bibliothek) +app.get('/api/mac-lookup', async (req, res) => { // async ist hier nicht unbedingt nötig, aber schadet nicht const macRaw = req.query.mac; const mac = typeof macRaw === 'string' ? macRaw.trim() : macRaw; const requestIp = req.ip || req.socket.remoteAddress; logger.info({ requestIp, mac }, 'MAC lookup request received'); - if (!isValidMac(mac)) { - logger.warn({ requestIp, mac }, 'Invalid MAC address for lookup'); - return res.status(400).json({ error: 'Invalid MAC address format provided.' }); + if (!isValidMac(mac)) { // Vorabprüfung beibehalten + logger.warn({ requestIp, mac }, 'Invalid MAC address format for lookup'); + return res.status(400).json({ success: false, error: 'Invalid MAC address format provided.' }); } try { - // mac-lookup verwendet eine lokale Datenbank, sollte schnell sein - const vendor = await macLookup.lookup(mac); // lookup ist jetzt async + // oui() lädt die DB bei Bedarf und gibt den Vendor-String oder null zurück + const vendor = oui(mac); // Einfacher Aufruf if (vendor) { logger.info({ requestIp, mac, vendor }, 'MAC lookup successful'); @@ -778,7 +778,8 @@ app.get('/api/mac-lookup', async (req, res) => { } } catch (error) { - // Fehler sollten nur auftreten, wenn die DB nicht geladen wurde oder die Eingabe ungültig ist (sollte durch isValidMac abgefangen werden) + // Fehler können auftreten, wenn die interne DB nicht geladen werden kann + // oder die Eingabe trotz Regex ungültig ist (sollte selten sein) logger.error({ requestIp, mac, error: error.message }, 'MAC lookup failed'); res.status(500).json({ success: false, error: `MAC lookup failed: ${error.message}` }); } @@ -802,9 +803,9 @@ initialize().then(() => { logger.info(` http://localhost:${PORT}/api/ping?targetIp=`); logger.info(` http://localhost:${PORT}/api/traceroute?targetIp=`); logger.info(` http://localhost:${PORT}/api/lookup?targetIp=`); - logger.info(` http://localhost:${PORT}/api/dns-lookup?domain=&type=`); // Neu - logger.info(` http://localhost:${PORT}/api/whois-lookup?query=`); // Neu - logger.info(` http://localhost:${PORT}/api/mac-lookup?mac=`); // Neu + logger.info(` http://localhost:${PORT}/api/dns-lookup?domain=&type=`); + logger.info(` http://localhost:${PORT}/api/whois-lookup?query=`); + logger.info(` http://localhost:${PORT}/api/mac-lookup?mac=`); logger.info(` http://localhost:${PORT}/api/version`); }); }).catch(error => {