@fanboynz/network-scanner 2.0.25 → 2.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/fingerprint.js +5 -5
- package/lib/nettools.js +140 -92
- package/nwss.js +81 -50
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -223,7 +223,7 @@ When a page redirects to a new domain, first-party/third-party detection is base
|
|
|
223
223
|
| `whois_timeout_multiplier` | Number | `1.5` | Timeout increase multiplier per retry |
|
|
224
224
|
| `whois_use_fallback` | Boolean | `true` | Add TLD-specific fallback servers |
|
|
225
225
|
| `whois_retry_on_timeout` | Boolean | `true` | Retry on timeout errors |
|
|
226
|
-
| `whois_retry_on_error` | Boolean | `
|
|
226
|
+
| `whois_retry_on_error` | Boolean | `true` | Retry on connection/other errors |
|
|
227
227
|
| `dig` | Array | - | Check dig output for ALL specified terms (AND logic) |
|
|
228
228
|
| `dig-or` | Array | - | Check dig output for ANY specified term (OR logic) |
|
|
229
229
|
| `dig_subdomain` | Boolean | `false` | Use subdomain for dig lookup instead of root domain |
|
package/lib/fingerprint.js
CHANGED
|
@@ -59,7 +59,7 @@ const PRECOMPILED_MOCKS = Object.freeze({
|
|
|
59
59
|
postMessage: () => {},
|
|
60
60
|
disconnect: () => {}
|
|
61
61
|
}),
|
|
62
|
-
getManifest: () => Object.freeze({ name: "Chrome", version: "
|
|
62
|
+
getManifest: () => Object.freeze({ name: "Chrome", version: "141.0.0.0" }),
|
|
63
63
|
getURL: (path) => `chrome-extension://invalid/${path}`,
|
|
64
64
|
id: undefined
|
|
65
65
|
}),
|
|
@@ -91,9 +91,9 @@ const BUILT_IN_PROPERTIES = new Set([
|
|
|
91
91
|
// User agent collections with latest versions
|
|
92
92
|
const USER_AGENT_COLLECTIONS = {
|
|
93
93
|
chrome: [
|
|
94
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
95
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
96
|
-
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
94
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
|
|
95
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
|
|
96
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
|
|
97
97
|
],
|
|
98
98
|
firefox: [
|
|
99
99
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0",
|
|
@@ -535,7 +535,7 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
535
535
|
onMessage: { addListener: () => {}, removeListener: () => {} },
|
|
536
536
|
sendMessage: () => {},
|
|
537
537
|
connect: () => ({ onMessage: { addListener: () => {}, removeListener: () => {} }, postMessage: () => {}, disconnect: () => {} }),
|
|
538
|
-
getManifest: () => ({ name: "Chrome", version: "
|
|
538
|
+
getManifest: () => ({ name: "Chrome", version: "141.0.0.0" }),
|
|
539
539
|
getURL: (path) => `chrome-extension://invalid/${path}`,
|
|
540
540
|
id: undefined
|
|
541
541
|
},
|
package/lib/nettools.js
CHANGED
|
@@ -357,7 +357,7 @@ async function whoisLookup(domain, timeout = 10000, whoisServer = null, debugMod
|
|
|
357
357
|
* @param {number} whoisDelay - Delay in milliseconds before whois requests (default: 2000)
|
|
358
358
|
* @returns {Promise<Object>} Object with success status and output/error
|
|
359
359
|
*/
|
|
360
|
-
async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null, debugMode = false, retryOptions = {}, whoisDelay =
|
|
360
|
+
async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null, debugMode = false, retryOptions = {}, whoisDelay = 8000, logFunc = null) {
|
|
361
361
|
const {
|
|
362
362
|
maxRetries = 3,
|
|
363
363
|
timeoutMultiplier = 1.5,
|
|
@@ -367,7 +367,6 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
|
|
|
367
367
|
} = retryOptions;
|
|
368
368
|
|
|
369
369
|
let serversToTry = [];
|
|
370
|
-
let currentTimeout = timeout;
|
|
371
370
|
|
|
372
371
|
// Build list of servers to try
|
|
373
372
|
if (whoisServer) {
|
|
@@ -390,88 +389,124 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
|
|
|
390
389
|
}
|
|
391
390
|
|
|
392
391
|
let lastError = null;
|
|
393
|
-
let
|
|
392
|
+
let totalAttempts = 0;
|
|
393
|
+
let serversAttempted = [];
|
|
394
394
|
|
|
395
395
|
if (debugMode) {
|
|
396
396
|
if (logFunc) {
|
|
397
397
|
logFunc(`${messageColors.highlight('[whois-retry]')} Starting whois lookup for ${domain} with ${serversToTry.length} server(s) to try`);
|
|
398
398
|
logFunc(`${messageColors.highlight('[whois-retry]')} Servers: [${serversToTry.map(s => s || 'default').join(', ')}]`);
|
|
399
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries}, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`);
|
|
399
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries} per server, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`);
|
|
400
400
|
} else {
|
|
401
401
|
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Starting whois lookup for ${domain} with ${serversToTry.length} server(s) to try`));
|
|
402
402
|
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Servers: [${serversToTry.map(s => s || 'default').join(', ')}]`));
|
|
403
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries}, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`));
|
|
403
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Retry settings: maxRetries=${maxRetries} per server, timeoutMultiplier=${timeoutMultiplier}, retryOnTimeout=${retryOnTimeout}, retryOnError=${retryOnError}`));
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
|
|
408
|
-
|
|
407
|
+
// Try each server with retry logic
|
|
408
|
+
for (let serverIndex = 0; serverIndex < serversToTry.length; serverIndex++) {
|
|
409
|
+
const server = serversToTry[serverIndex];
|
|
410
|
+
let currentTimeout = timeout;
|
|
411
|
+
let retryCount = 0;
|
|
412
|
+
serversAttempted.push(server);
|
|
409
413
|
|
|
410
414
|
if (debugMode) {
|
|
411
415
|
const serverName = server || 'default';
|
|
412
416
|
if (logFunc) {
|
|
413
|
-
logFunc(`${messageColors.highlight('[whois-retry]')}
|
|
417
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Server ${serverIndex + 1}/${serversToTry.length}: ${serverName} (max ${maxRetries} attempts)`);
|
|
414
418
|
} else {
|
|
415
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')}
|
|
419
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Server ${serverIndex + 1}/${serversToTry.length}: ${serverName} (max ${maxRetries} attempts)`));
|
|
416
420
|
}
|
|
417
421
|
}
|
|
418
422
|
|
|
419
|
-
//
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
if (logFunc) {
|
|
424
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before retry attempt...`);
|
|
425
|
-
} else {
|
|
426
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before retry attempt...`));
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
await new Promise(resolve => setTimeout(resolve, whoisDelay));
|
|
430
|
-
}
|
|
423
|
+
// Retry this server up to maxRetries times
|
|
424
|
+
while (retryCount < maxRetries) {
|
|
425
|
+
totalAttempts++;
|
|
426
|
+
const attemptNum = retryCount + 1;
|
|
431
427
|
|
|
432
|
-
} else if (whoisDelay > 0) {
|
|
433
|
-
// Add initial delay on first attempt if configured
|
|
434
428
|
if (debugMode) {
|
|
429
|
+
const serverName = server || 'default';
|
|
435
430
|
if (logFunc) {
|
|
436
|
-
logFunc(`${messageColors.highlight('[whois-retry]')}
|
|
431
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Attempt ${attemptNum}/${maxRetries} on server ${serverName} (timeout: ${currentTimeout}ms)`);
|
|
437
432
|
} else {
|
|
438
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')}
|
|
433
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Attempt ${attemptNum}/${maxRetries} on server ${serverName} (timeout: ${currentTimeout}ms)`));
|
|
439
434
|
}
|
|
440
435
|
}
|
|
441
|
-
await new Promise(resolve => setTimeout(resolve, whoisDelay));
|
|
442
|
-
} else if (debugMode) {
|
|
443
|
-
// Log when delay is skipped due to whoisDelay being 0
|
|
444
|
-
if (logFunc) {
|
|
445
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`);
|
|
446
|
-
} else {
|
|
447
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`));
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
try {
|
|
452
|
-
const result = await whoisLookup(domain, currentTimeout, server, debugMode, logFunc);
|
|
453
436
|
|
|
454
|
-
|
|
437
|
+
// Add progressive delay between retries (but not before first attempt on any server)
|
|
438
|
+
if (retryCount > 0 && whoisDelay > 0) {
|
|
439
|
+
// Progressive delay: base delay * retry attempt number + extra delay
|
|
440
|
+
// Attempt 2: base delay * 1 + 4000ms = 8000ms + 4000ms = 12000ms
|
|
441
|
+
// Attempt 3: base delay * 2 + 6000ms = 16000ms + 6000ms = 22000ms
|
|
442
|
+
// Attempt 4+: base delay * 3 + 6000ms = 24000ms + 6000ms = 30000ms (if maxRetries > 3)
|
|
443
|
+
const delayMultiplier = Math.min(retryCount, 3);
|
|
444
|
+
const baseDelay = whoisDelay * delayMultiplier;
|
|
445
|
+
|
|
446
|
+
// Add extra delay based on retry attempt
|
|
447
|
+
let extraDelay = 0;
|
|
448
|
+
if (retryCount === 1) {
|
|
449
|
+
extraDelay = 4000; // Extra 4 seconds for 2nd attempt
|
|
450
|
+
} else if (retryCount >= 2) {
|
|
451
|
+
extraDelay = 6000; // Extra 6 seconds for 3rd+ attempts
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const actualDelay = baseDelay + extraDelay;
|
|
455
|
+
|
|
456
|
+
if (debugMode) {
|
|
457
|
+
if (logFunc) {
|
|
458
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${actualDelay}ms progressive delay before retry ${retryCount + 1} (base: ${baseDelay}ms + extra: ${extraDelay}ms)...`);
|
|
459
|
+
} else {
|
|
460
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${actualDelay}ms progressive delay before retry ${retryCount + 1} (base: ${baseDelay}ms + extra: ${extraDelay}ms)...`));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
await new Promise(resolve => setTimeout(resolve, actualDelay));
|
|
464
|
+
} else if (serverIndex > 0 && retryCount === 0 && whoisDelay > 0) {
|
|
465
|
+
// Add delay before trying a new server (but not the very first server)
|
|
455
466
|
if (debugMode) {
|
|
456
467
|
if (logFunc) {
|
|
457
|
-
logFunc(`${messageColors.highlight('[whois-retry]')}
|
|
468
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before trying new server...`);
|
|
458
469
|
} else {
|
|
459
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')}
|
|
470
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Adding ${whoisDelay}ms delay before trying new server...`));
|
|
460
471
|
}
|
|
461
472
|
}
|
|
473
|
+
await new Promise(resolve => setTimeout(resolve, whoisDelay));
|
|
474
|
+
} else if (debugMode && whoisDelay === 0) {
|
|
475
|
+
// Log when delay is skipped due to whoisDelay being 0
|
|
476
|
+
if (logFunc) {
|
|
477
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`);
|
|
478
|
+
} else {
|
|
479
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping delay (whoisDelay: ${whoisDelay}ms)`));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
try {
|
|
484
|
+
const result = await whoisLookup(domain, currentTimeout, server, debugMode, logFunc);
|
|
462
485
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
finalServer: result.whoisServer,
|
|
471
|
-
retriedAfterFailure: attemptCount > 1
|
|
486
|
+
if (result.success) {
|
|
487
|
+
if (debugMode) {
|
|
488
|
+
if (logFunc) {
|
|
489
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} SUCCESS on attempt ${attemptNum}/${maxRetries} for server ${result.whoisServer || 'default'} (total attempts: ${totalAttempts})`);
|
|
490
|
+
} else {
|
|
491
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} SUCCESS on attempt ${attemptNum}/${maxRetries} for server ${result.whoisServer || 'default'} (total attempts: ${totalAttempts})`));
|
|
492
|
+
}
|
|
472
493
|
}
|
|
473
|
-
|
|
474
|
-
|
|
494
|
+
|
|
495
|
+
// Add retry info to result
|
|
496
|
+
return {
|
|
497
|
+
...result,
|
|
498
|
+
retryInfo: {
|
|
499
|
+
totalAttempts: totalAttempts,
|
|
500
|
+
maxAttempts: serversToTry.length * maxRetries,
|
|
501
|
+
serversAttempted: serversAttempted,
|
|
502
|
+
finalServer: result.whoisServer,
|
|
503
|
+
retriedAfterFailure: totalAttempts > 1,
|
|
504
|
+
serverRetries: retryCount,
|
|
505
|
+
serverIndex: serverIndex
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
475
510
|
// Determine if we should retry based on error type
|
|
476
511
|
const shouldRetry = (result.isTimeout && retryOnTimeout) || (!result.isTimeout && retryOnError);
|
|
477
512
|
|
|
@@ -479,72 +514,85 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
|
|
|
479
514
|
const serverName = result.whoisServer || 'default';
|
|
480
515
|
const errorType = result.isTimeout ? 'TIMEOUT' : 'ERROR';
|
|
481
516
|
if (logFunc) {
|
|
482
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${
|
|
517
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${result.error}`);
|
|
483
518
|
} else {
|
|
484
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${
|
|
519
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} ${errorType} on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${result.error}`));
|
|
485
520
|
}
|
|
486
521
|
|
|
487
|
-
if (
|
|
522
|
+
if (retryCount < maxRetries - 1) {
|
|
488
523
|
if (shouldRetry) {
|
|
489
524
|
if (logFunc) {
|
|
490
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} Will retry
|
|
525
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Will retry attempt ${attemptNum + 1}/${maxRetries} on same server...`);
|
|
491
526
|
} else {
|
|
492
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Will retry
|
|
527
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Will retry attempt ${attemptNum + 1}/${maxRetries} on same server...`));
|
|
493
528
|
}
|
|
494
529
|
} else {
|
|
495
530
|
if (logFunc) {
|
|
496
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} Skipping retry (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`);
|
|
531
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Skipping retry on same server (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`);
|
|
497
532
|
} else {
|
|
498
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping retry (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`));
|
|
533
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Skipping retry on same server (retryOn${result.isTimeout ? 'Timeout' : 'Error'}=${shouldRetry})`));
|
|
499
534
|
}
|
|
500
535
|
}
|
|
536
|
+
} else if (serverIndex < serversToTry.length - 1) {
|
|
537
|
+
if (logFunc) {
|
|
538
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} Max retries reached for server, will try next server...`);
|
|
539
|
+
} else {
|
|
540
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} Max retries reached for server, will try next server...`));
|
|
541
|
+
}
|
|
501
542
|
}
|
|
502
543
|
}
|
|
503
544
|
|
|
504
545
|
lastError = result;
|
|
505
546
|
|
|
506
|
-
// If this is the last server or we shouldn't retry this error type, break
|
|
507
|
-
if (
|
|
547
|
+
// If this is the last retry for this server or we shouldn't retry this error type, break to next server
|
|
548
|
+
if (retryCount >= maxRetries - 1 || !shouldRetry) {
|
|
508
549
|
break;
|
|
509
550
|
}
|
|
510
551
|
|
|
511
|
-
// Increase timeout for next attempt
|
|
552
|
+
// Increase timeout for next retry attempt on same server
|
|
553
|
+
retryCount++;
|
|
512
554
|
currentTimeout = Math.round(currentTimeout * timeoutMultiplier);
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
555
|
+
|
|
556
|
+
} catch (error) {
|
|
557
|
+
if (debugMode) {
|
|
558
|
+
const serverName = server || 'default';
|
|
559
|
+
if (logFunc) {
|
|
560
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} EXCEPTION on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${error.message}`);
|
|
561
|
+
} else {
|
|
562
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} EXCEPTION on attempt ${attemptNum}/${maxRetries} with server ${serverName}: ${error.message}`));
|
|
563
|
+
}
|
|
521
564
|
}
|
|
565
|
+
|
|
566
|
+
lastError = {
|
|
567
|
+
success: false,
|
|
568
|
+
error: error.message,
|
|
569
|
+
domain: domain,
|
|
570
|
+
whoisServer: server,
|
|
571
|
+
isTimeout: error.message.includes('timeout'),
|
|
572
|
+
duration: 0
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
// For exceptions, only retry if it's a retryable error type
|
|
576
|
+
const isRetryableException = error.message.includes('timeout') ||
|
|
577
|
+
error.message.includes('ECONNRESET') ||
|
|
578
|
+
error.message.includes('ENOTFOUND');
|
|
579
|
+
|
|
580
|
+
if (retryCount >= maxRetries - 1 || !isRetryableException) {
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
retryCount++;
|
|
585
|
+
currentTimeout = Math.round(currentTimeout * timeoutMultiplier);
|
|
522
586
|
}
|
|
523
|
-
|
|
524
|
-
lastError = {
|
|
525
|
-
success: false,
|
|
526
|
-
error: error.message,
|
|
527
|
-
domain: domain,
|
|
528
|
-
whoisServer: server,
|
|
529
|
-
isTimeout: error.message.includes('timeout'),
|
|
530
|
-
duration: 0
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
// Continue to next server unless this is the last one
|
|
534
|
-
if (attemptCount >= serversToTry.length) {
|
|
535
|
-
break;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
currentTimeout = Math.round(currentTimeout * timeoutMultiplier);
|
|
539
587
|
}
|
|
540
588
|
}
|
|
541
589
|
|
|
542
590
|
// All attempts failed
|
|
543
591
|
if (debugMode) {
|
|
544
592
|
if (logFunc) {
|
|
545
|
-
logFunc(`${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${
|
|
593
|
+
logFunc(`${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${totalAttempts} attempts failed for ${domain} across ${serversAttempted.length} server(s)`);
|
|
546
594
|
} else {
|
|
547
|
-
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${
|
|
595
|
+
console.log(formatLogMessage('debug', `${messageColors.highlight('[whois-retry]')} FINAL FAILURE: All ${totalAttempts} attempts failed for ${domain} across ${serversAttempted.length} server(s)`));
|
|
548
596
|
}
|
|
549
597
|
if (lastError) {
|
|
550
598
|
if (logFunc) {
|
|
@@ -559,11 +607,11 @@ async function whoisLookupWithRetry(domain, timeout = 10000, whoisServer = null,
|
|
|
559
607
|
return {
|
|
560
608
|
...lastError,
|
|
561
609
|
retryInfo: {
|
|
562
|
-
totalAttempts:
|
|
563
|
-
maxAttempts: serversToTry.length,
|
|
564
|
-
serversAttempted:
|
|
610
|
+
totalAttempts: totalAttempts,
|
|
611
|
+
maxAttempts: serversToTry.length * maxRetries,
|
|
612
|
+
serversAttempted: serversAttempted,
|
|
565
613
|
finalServer: lastError?.whoisServer || null,
|
|
566
|
-
retriedAfterFailure:
|
|
614
|
+
retriedAfterFailure: totalAttempts > 1,
|
|
567
615
|
allAttemptsFailed: true
|
|
568
616
|
}
|
|
569
617
|
};
|
|
@@ -1357,4 +1405,4 @@ module.exports = {
|
|
|
1357
1405
|
getCommonWhoisServers,
|
|
1358
1406
|
suggestWhoisServers,
|
|
1359
1407
|
execWithTimeout // Export for testing
|
|
1360
|
-
};
|
|
1408
|
+
};
|
package/nwss.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// === Network scanner script (nwss.js) v2.0.
|
|
1
|
+
// === Network scanner script (nwss.js) v2.0.27 ===
|
|
2
2
|
|
|
3
3
|
// puppeteer for browser automation, fs for file system operations, psl for domain parsing.
|
|
4
4
|
// const pLimit = require('p-limit'); // Will be dynamically imported
|
|
@@ -56,7 +56,7 @@ function fastTimeout(ms) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// --- Configuration Constants ---
|
|
59
|
-
const TIMEOUTS = {
|
|
59
|
+
const TIMEOUTS = Object.freeze({
|
|
60
60
|
DEFAULT_PAGE: 35000, // Standard page load timeout (35s)
|
|
61
61
|
DEFAULT_NAVIGATION: 25000, // Navigation operation timeout
|
|
62
62
|
DEFAULT_NAVIGATION_REDUCED: 20000, // Reduced timeout for faster failures
|
|
@@ -71,21 +71,32 @@ const TIMEOUTS = {
|
|
|
71
71
|
CURL_HANDLER_DELAY: 3000, // Wait for async curl operations
|
|
72
72
|
PROTOCOL_TIMEOUT: 180000, // Chrome DevTools Protocol timeout
|
|
73
73
|
REDIRECT_JS_TIMEOUT: 5000 // JavaScript redirect detection timeout
|
|
74
|
-
};
|
|
74
|
+
});
|
|
75
75
|
|
|
76
|
-
const CACHE_LIMITS = {
|
|
76
|
+
const CACHE_LIMITS = Object.freeze({
|
|
77
77
|
DISK_CACHE_SIZE: 52428800, // 50MB
|
|
78
78
|
MEDIA_CACHE_SIZE: 52428800, // 50MB
|
|
79
79
|
DEFAULT_CACHE_PATH: '.cache',
|
|
80
80
|
DEFAULT_MAX_SIZE: 5000
|
|
81
|
-
};
|
|
81
|
+
});
|
|
82
82
|
|
|
83
|
-
const CONCURRENCY_LIMITS = {
|
|
83
|
+
const CONCURRENCY_LIMITS = Object.freeze({
|
|
84
84
|
MIN: 1,
|
|
85
85
|
MAX: 50,
|
|
86
86
|
DEFAULT: 6,
|
|
87
87
|
HIGH_CONCURRENCY_THRESHOLD: 12 // Auto-enable aggressive caching above this
|
|
88
|
-
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// V8 Optimization: Use Map for user agent lookups instead of object
|
|
91
|
+
const USER_AGENTS = Object.freeze(new Map([
|
|
92
|
+
['chrome', "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"],
|
|
93
|
+
['chrome_mac', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"],
|
|
94
|
+
['chrome_linux', "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"],
|
|
95
|
+
['firefox', "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/143.0"],
|
|
96
|
+
['firefox_mac', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/143.0"],
|
|
97
|
+
['firefox_linux', "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/143.0"],
|
|
98
|
+
['safari', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15"]
|
|
99
|
+
]));
|
|
89
100
|
|
|
90
101
|
const REALTIME_CLEANUP_THRESHOLD = 8; // Default pages to keep for realtime cleanup
|
|
91
102
|
|
|
@@ -132,7 +143,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
|
|
|
132
143
|
const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
|
|
133
144
|
|
|
134
145
|
// --- Script Configuration & Constants ---
|
|
135
|
-
const VERSION = '2.0.
|
|
146
|
+
const VERSION = '2.0.27'; // Script version
|
|
136
147
|
|
|
137
148
|
// get startTime
|
|
138
149
|
const startTime = Date.now();
|
|
@@ -1211,6 +1222,9 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1211
1222
|
'/usr/bin/chromium',
|
|
1212
1223
|
'/snap/bin/chromium'
|
|
1213
1224
|
];
|
|
1225
|
+
// V8 Optimization: Freeze the Chrome paths array since it's constant
|
|
1226
|
+
Object.freeze(systemChromePaths);
|
|
1227
|
+
|
|
1214
1228
|
|
|
1215
1229
|
let executablePath = null;
|
|
1216
1230
|
for (const chromePath of systemChromePaths) {
|
|
@@ -1387,12 +1401,28 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1387
1401
|
* @returns {Promise<object>} A promise that resolves to an object containing scan results.
|
|
1388
1402
|
*/
|
|
1389
1403
|
async function processUrl(currentUrl, siteConfig, browserInstance) {
|
|
1390
|
-
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1404
|
+
// V8 Optimization: Single destructuring to avoid multiple property lookups
|
|
1405
|
+
const {
|
|
1406
|
+
firstParty,
|
|
1407
|
+
thirdParty,
|
|
1408
|
+
subDomains,
|
|
1409
|
+
localhost,
|
|
1410
|
+
cloudflare_phish,
|
|
1411
|
+
cloudflare_bypass,
|
|
1412
|
+
flowproxy_detection,
|
|
1413
|
+
privoxy,
|
|
1414
|
+
pihole,
|
|
1415
|
+
even_blocked,
|
|
1416
|
+
comments,
|
|
1417
|
+
bypass_cache
|
|
1418
|
+
} = siteConfig;
|
|
1419
|
+
|
|
1420
|
+
const allowFirstParty = firstParty === true || firstParty === 1;
|
|
1421
|
+
const allowThirdParty = thirdParty === undefined || thirdParty === true || thirdParty === 1;
|
|
1422
|
+
const perSiteSubDomains = subDomains === 1 ? true : subDomainsMode;
|
|
1423
|
+
const siteLocalhostIP = localhost || null;
|
|
1424
|
+
const cloudflarePhishBypass = cloudflare_phish === true;
|
|
1425
|
+
const cloudflareBypass = cloudflare_bypass === true;
|
|
1396
1426
|
// Add redirect and same-page loop protection
|
|
1397
1427
|
const MAX_REDIRECT_DEPTH = siteConfig.max_redirects || 10;
|
|
1398
1428
|
const redirectHistory = new Set();
|
|
@@ -1401,14 +1431,14 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1401
1431
|
const MAX_SAME_PAGE_LOADS = 3;
|
|
1402
1432
|
let currentPageUrl = currentUrl;
|
|
1403
1433
|
|
|
1404
|
-
const sitePrivoxy =
|
|
1405
|
-
const sitePihole =
|
|
1406
|
-
const flowproxyDetection =
|
|
1434
|
+
const sitePrivoxy = privoxy === true;
|
|
1435
|
+
const sitePihole = pihole === true;
|
|
1436
|
+
const flowproxyDetection = flowproxy_detection === true;
|
|
1407
1437
|
|
|
1408
|
-
const evenBlocked =
|
|
1438
|
+
const evenBlocked = even_blocked === true;
|
|
1409
1439
|
// Log site-level comments if debug mode is enabled
|
|
1410
|
-
if (forceDebug &&
|
|
1411
|
-
const siteComments = Array.isArray(
|
|
1440
|
+
if (forceDebug && comments) {
|
|
1441
|
+
const siteComments = Array.isArray(comments) ? comments : [comments];
|
|
1412
1442
|
console.log(formatLogMessage('debug', `Site comments for ${currentUrl}: ${siteComments.length} item(s)`));
|
|
1413
1443
|
siteComments.forEach((comment, idx) =>
|
|
1414
1444
|
console.log(formatLogMessage('debug', ` Site comment ${idx + 1}: ${comment}`))
|
|
@@ -1416,11 +1446,11 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1416
1446
|
}
|
|
1417
1447
|
|
|
1418
1448
|
// Log bypass_cache setting if enabled
|
|
1419
|
-
if (forceDebug &&
|
|
1449
|
+
if (forceDebug && bypass_cache === true) {
|
|
1420
1450
|
console.log(formatLogMessage('debug', `Cache bypass enabled for all URLs in site: ${currentUrl}`));
|
|
1421
1451
|
}
|
|
1422
1452
|
|
|
1423
|
-
if (
|
|
1453
|
+
if (firstParty === 0 && thirdParty === 0) {
|
|
1424
1454
|
console.warn(`⚠ Skipping ${currentUrl} because both firstParty and thirdParty are disabled.`);
|
|
1425
1455
|
return { url: currentUrl, rules: [], success: false, skipped: true };
|
|
1426
1456
|
}
|
|
@@ -1475,14 +1505,14 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1475
1505
|
let finalUrlAfterRedirect = null;
|
|
1476
1506
|
|
|
1477
1507
|
// Enhanced error types for Puppeteer 23.x compatibility
|
|
1478
|
-
const CRITICAL_BROWSER_ERRORS = [
|
|
1508
|
+
const CRITICAL_BROWSER_ERRORS = Object.freeze([
|
|
1479
1509
|
'Protocol error',
|
|
1480
1510
|
'Target closed',
|
|
1481
1511
|
'Browser has been closed',
|
|
1482
1512
|
'Browser protocol broken',
|
|
1483
1513
|
'Browser process exited',
|
|
1484
1514
|
'Browser disconnected'
|
|
1485
|
-
];
|
|
1515
|
+
]);
|
|
1486
1516
|
|
|
1487
1517
|
try {
|
|
1488
1518
|
|
|
@@ -1907,29 +1937,30 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1907
1937
|
|
|
1908
1938
|
// Client Hints protection for Chrome user agents
|
|
1909
1939
|
if (siteConfig.userAgent && siteConfig.userAgent.toLowerCase().includes('chrome')) {
|
|
1940
|
+
const userAgentKey = siteConfig.userAgent.toLowerCase();
|
|
1910
1941
|
let platform = 'Windows';
|
|
1911
1942
|
let platformVersion = '15.0.0';
|
|
1912
1943
|
let arch = 'x86';
|
|
1913
1944
|
|
|
1914
|
-
if (
|
|
1945
|
+
if (userAgentKey === 'chrome_mac') {
|
|
1915
1946
|
platform = 'macOS';
|
|
1916
|
-
platformVersion = '13.5.0';
|
|
1947
|
+
platformVersion = '13.5.0';
|
|
1917
1948
|
arch = 'arm';
|
|
1918
|
-
} else if (
|
|
1949
|
+
} else if (userAgentKey === 'chrome_linux') {
|
|
1919
1950
|
platform = 'Linux';
|
|
1920
1951
|
platformVersion = '6.5.0';
|
|
1921
1952
|
arch = 'x86';
|
|
1922
1953
|
}
|
|
1923
|
-
|
|
1954
|
+
|
|
1924
1955
|
await page.setExtraHTTPHeaders({
|
|
1925
|
-
'Sec-CH-UA': '"Chromium";v="
|
|
1956
|
+
'Sec-CH-UA': '"Chromium";v="141", "Not=A?Brand";v="24", "Google Chrome";v="141"',
|
|
1926
1957
|
'Sec-CH-UA-Platform': `"${platform}"`,
|
|
1927
1958
|
'Sec-CH-UA-Platform-Version': `"${platformVersion}"`,
|
|
1928
1959
|
'Sec-CH-UA-Mobile': '?0',
|
|
1929
1960
|
'Sec-CH-UA-Arch': `"${arch}"`,
|
|
1930
1961
|
'Sec-CH-UA-Bitness': '"64"',
|
|
1931
|
-
'Sec-CH-UA-Full-Version': '"
|
|
1932
|
-
'Sec-CH-UA-Full-Version-List': '"Chromium";v="
|
|
1962
|
+
'Sec-CH-UA-Full-Version': '"141.0.7390.55"',
|
|
1963
|
+
'Sec-CH-UA-Full-Version-List': '"Chromium";v="141.0.7390.55", "Not=A?Brand";v="24.0.0.0", "Google Chrome";v="141.0.7390.55"'
|
|
1933
1964
|
});
|
|
1934
1965
|
}
|
|
1935
1966
|
} catch (fingerprintErr) {
|
|
@@ -1959,16 +1990,7 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
1959
1990
|
// Get user agent for curl if needed
|
|
1960
1991
|
let curlUserAgent = '';
|
|
1961
1992
|
if (useCurl && siteConfig.userAgent) {
|
|
1962
|
-
|
|
1963
|
-
chrome: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
1964
|
-
chrome_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
1965
|
-
chrome_linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
1966
|
-
firefox: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/143.0",
|
|
1967
|
-
firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/143.0",
|
|
1968
|
-
firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/143.0",
|
|
1969
|
-
safari: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15"
|
|
1970
|
-
};
|
|
1971
|
-
curlUserAgent = userAgents[siteConfig.userAgent.toLowerCase()] || '';
|
|
1993
|
+
curlUserAgent = USER_AGENTS.get(siteConfig.userAgent.toLowerCase()) || '';
|
|
1972
1994
|
}
|
|
1973
1995
|
|
|
1974
1996
|
if (useCurl && forceDebug) {
|
|
@@ -3487,20 +3509,29 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
3487
3509
|
// Temporarily store the pLimit function
|
|
3488
3510
|
const originalLimit = limit;
|
|
3489
3511
|
|
|
3490
|
-
//
|
|
3491
|
-
|
|
3512
|
+
// V8 Optimization: Calculate total URLs first to pre-allocate array
|
|
3513
|
+
let totalUrls = 0;
|
|
3492
3514
|
for (const site of sites) {
|
|
3493
3515
|
const urlsToProcess = Array.isArray(site.url) ? site.url : [site.url];
|
|
3494
|
-
urlsToProcess.
|
|
3495
|
-
|
|
3516
|
+
totalUrls += urlsToProcess.length;
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
// Pre-allocate array with exact size to prevent multiple reallocations
|
|
3520
|
+
const allTasks = new Array(totalUrls);
|
|
3521
|
+
let taskIndex = 0;
|
|
3522
|
+
|
|
3523
|
+
// Populate the pre-allocated array
|
|
3524
|
+
for (const site of sites) {
|
|
3525
|
+
const urlsToProcess = Array.isArray(site.url) ? site.url : [site.url];
|
|
3526
|
+
for (const url of urlsToProcess) {
|
|
3527
|
+
allTasks[taskIndex++] = {
|
|
3496
3528
|
url,
|
|
3497
3529
|
config: { ...site, _originalUrl: url }, // Preserve original URL for CDP domain checking
|
|
3498
|
-
taskId:
|
|
3499
|
-
}
|
|
3500
|
-
}
|
|
3530
|
+
taskId: taskIndex - 1 // For tracking
|
|
3531
|
+
};
|
|
3532
|
+
}
|
|
3501
3533
|
}
|
|
3502
|
-
|
|
3503
|
-
const totalUrls = allTasks.length;
|
|
3534
|
+
|
|
3504
3535
|
|
|
3505
3536
|
let results = [];
|
|
3506
3537
|
let processedUrlCount = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanboynz/network-scanner",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.27",
|
|
4
4
|
"description": "A Puppeteer-based network scanner for analyzing web traffic, generating adblock filter rules, and identifying third-party requests. Features include fingerprint spoofing, Cloudflare bypass, content analysis with curl/grep, and multiple output formats.",
|
|
5
5
|
"main": "nwss.js",
|
|
6
6
|
"scripts": {
|