@fanboynz/network-scanner 2.0.12 → 2.0.14
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/lib/fingerprint.js +233 -4
- package/nwss.js +18 -9
- package/package.json +1 -1
package/lib/fingerprint.js
CHANGED
|
@@ -399,6 +399,10 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
399
399
|
const automationProps = [
|
|
400
400
|
'callPhantom', '_phantom', '__nightmare', '_selenium', '__selenium_unwrapped',
|
|
401
401
|
'__webdriver_evaluate', '__driver_evaluate', '__webdriver_script_function',
|
|
402
|
+
'__fxdriver_evaluate', '__fxdriver_unwrapped', '__webdriver_script_fn',
|
|
403
|
+
'phantomjs', '_Selenium_IDE_Recorder', 'callSelenium', '_selenium',
|
|
404
|
+
'__phantomas', '__selenium_evaluate', '__driver_unwrapped',
|
|
405
|
+
'webdriver-evaluate', '__webdriverFunc', 'driver-evaluate', '__driver-evaluate', '__selenium-evaluate',
|
|
402
406
|
'spawn', 'emit', 'Buffer', 'domAutomation', 'domAutomationController'
|
|
403
407
|
];
|
|
404
408
|
|
|
@@ -449,15 +453,38 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
449
453
|
let plugins = [];
|
|
450
454
|
if (userAgent.includes('Chrome')) {
|
|
451
455
|
plugins = [
|
|
452
|
-
{
|
|
453
|
-
|
|
456
|
+
{
|
|
457
|
+
name: 'Chrome PDF Plugin',
|
|
458
|
+
description: 'Portable Document Format',
|
|
459
|
+
filename: 'internal-pdf-viewer',
|
|
460
|
+
length: 1,
|
|
461
|
+
version: ''
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: 'Chrome PDF Viewer',
|
|
465
|
+
description: '',
|
|
466
|
+
filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai',
|
|
467
|
+
length: 1,
|
|
468
|
+
version: ''
|
|
469
|
+
}
|
|
454
470
|
];
|
|
455
471
|
} else if (userAgent.includes('Firefox')) {
|
|
456
472
|
plugins = [
|
|
457
|
-
{
|
|
473
|
+
{
|
|
474
|
+
name: 'PDF.js',
|
|
475
|
+
description: 'Portable Document Format',
|
|
476
|
+
filename: 'internal-pdf-js',
|
|
477
|
+
length: 2,
|
|
478
|
+
version: '5.4.70'
|
|
479
|
+
}
|
|
458
480
|
];
|
|
481
|
+
} else if (userAgent.includes('Safari')) {
|
|
482
|
+
// Safari typically has no plugins in modern versions
|
|
483
|
+
plugins = [];
|
|
459
484
|
}
|
|
460
|
-
|
|
485
|
+
// Create array-like object with length property
|
|
486
|
+
const pluginsArray = Object.assign(plugins, { length: plugins.length });
|
|
487
|
+
safeDefinePropertyLocal(navigator, 'plugins', { get: () => pluginsArray });
|
|
461
488
|
}, 'plugins spoofing');
|
|
462
489
|
|
|
463
490
|
// Spoof languages
|
|
@@ -482,6 +509,69 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
482
509
|
safeDefinePropertyLocal(navigator, 'product', { get: () => product });
|
|
483
510
|
}, 'vendor/product spoofing');
|
|
484
511
|
|
|
512
|
+
// Enhanced OS fingerprinting protection based on actual user agent content
|
|
513
|
+
safeExecute(() => {
|
|
514
|
+
let osType = 'windows';
|
|
515
|
+
let browserType = 'chrome';
|
|
516
|
+
|
|
517
|
+
// Detect OS from user agent string patterns
|
|
518
|
+
if (userAgent.includes('Macintosh') || userAgent.includes('Mac OS X')) {
|
|
519
|
+
osType = 'mac';
|
|
520
|
+
} else if (userAgent.includes('X11; Linux') || userAgent.includes('Ubuntu')) {
|
|
521
|
+
osType = 'linux';
|
|
522
|
+
} else if (userAgent.includes('Windows NT')) {
|
|
523
|
+
osType = 'windows';
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Detect browser type
|
|
527
|
+
if (userAgent.includes('Firefox/')) {
|
|
528
|
+
browserType = 'firefox';
|
|
529
|
+
} else if (userAgent.includes('Safari/') && !userAgent.includes('Chrome/')) {
|
|
530
|
+
browserType = 'safari';
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Apply OS-specific navigator properties
|
|
534
|
+
if (osType === 'windows') {
|
|
535
|
+
if (browserType === 'firefox') {
|
|
536
|
+
safeDefinePropertyLocal(navigator, 'oscpu', { get: () => 'Windows NT 10.0; Win64; x64' });
|
|
537
|
+
safeDefinePropertyLocal(navigator, 'buildID', { get: () => '20100101' });
|
|
538
|
+
}
|
|
539
|
+
if (window.screen) {
|
|
540
|
+
safeDefinePropertyLocal(window.screen, 'fontSmoothingEnabled', { get: () => true });
|
|
541
|
+
}
|
|
542
|
+
} else if (osType === 'mac') {
|
|
543
|
+
if (browserType === 'firefox') {
|
|
544
|
+
safeDefinePropertyLocal(navigator, 'oscpu', { get: () => 'Intel Mac OS X 10.15' });
|
|
545
|
+
safeDefinePropertyLocal(navigator, 'buildID', { get: () => '20100101' });
|
|
546
|
+
}
|
|
547
|
+
} else if (osType === 'linux') {
|
|
548
|
+
if (browserType === 'firefox') {
|
|
549
|
+
safeDefinePropertyLocal(navigator, 'oscpu', { get: () => 'Linux x86_64' });
|
|
550
|
+
safeDefinePropertyLocal(navigator, 'buildID', { get: () => '20100101' });
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}, 'enhanced OS fingerprinting protection');
|
|
554
|
+
|
|
555
|
+
// Screen resolution fingerprinting protection
|
|
556
|
+
safeExecute(() => {
|
|
557
|
+
// Common realistic resolutions to avoid fingerprinting
|
|
558
|
+
const commonResolutions = [
|
|
559
|
+
{ width: 1920, height: 1080 },
|
|
560
|
+
{ width: 2560, height: 1440 },
|
|
561
|
+
{ width: 3840, height: 2160 },
|
|
562
|
+
{ width: 1280, height: 720 },
|
|
563
|
+
{ width: 1366, height: 768 },
|
|
564
|
+
{ width: 1440, height: 900 },
|
|
565
|
+
{ width: 1536, height: 864 }
|
|
566
|
+
];
|
|
567
|
+
const resolution = commonResolutions[Math.floor(Math.random() * commonResolutions.length)];
|
|
568
|
+
|
|
569
|
+
safeDefinePropertyLocal(window.screen, 'width', { get: () => resolution.width });
|
|
570
|
+
safeDefinePropertyLocal(window.screen, 'height', { get: () => resolution.height });
|
|
571
|
+
safeDefinePropertyLocal(window.screen, 'availWidth', { get: () => resolution.width });
|
|
572
|
+
safeDefinePropertyLocal(window.screen, 'availHeight', { get: () => resolution.height - 40 });
|
|
573
|
+
}, 'screen resolution protection');
|
|
574
|
+
|
|
485
575
|
// Spoof MIME types
|
|
486
576
|
safeExecute(() => {
|
|
487
577
|
let mimeTypes = [];
|
|
@@ -567,6 +657,134 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
|
|
|
567
657
|
}
|
|
568
658
|
}, 'WebGL spoofing');
|
|
569
659
|
|
|
660
|
+
// Permissions API spoofing
|
|
661
|
+
safeExecute(() => {
|
|
662
|
+
if (navigator.permissions?.query) {
|
|
663
|
+
const originalQuery = navigator.permissions.query;
|
|
664
|
+
navigator.permissions.query = function(descriptor) {
|
|
665
|
+
return Promise.resolve({ state: Math.random() > 0.5 ? 'granted' : 'prompt' });
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
}, 'permissions API spoofing');
|
|
669
|
+
|
|
670
|
+
// Media Device Spoofing
|
|
671
|
+
safeExecute(() => {
|
|
672
|
+
if (navigator.mediaDevices?.enumerateDevices) {
|
|
673
|
+
navigator.mediaDevices.enumerateDevices = function() {
|
|
674
|
+
return Promise.resolve([
|
|
675
|
+
{ deviceId: 'default', kind: 'audioinput', label: 'Default - Microphone (Realtek Audio)', groupId: 'group1' },
|
|
676
|
+
{ deviceId: 'default', kind: 'audiooutput', label: 'Default - Speakers (Realtek Audio)', groupId: 'group1' },
|
|
677
|
+
{ deviceId: 'default', kind: 'videoinput', label: 'HD WebCam (USB Camera)', groupId: 'group2' }
|
|
678
|
+
]);
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
}, 'media device spoofing');
|
|
682
|
+
|
|
683
|
+
// Fetch Request Headers Normalization
|
|
684
|
+
safeExecute(() => {
|
|
685
|
+
const originalFetch = window.fetch;
|
|
686
|
+
window.fetch = function(url, options = {}) {
|
|
687
|
+
const headers = { ...(options.headers || {}) };
|
|
688
|
+
|
|
689
|
+
// Add common browser headers if missing
|
|
690
|
+
if (!headers['Accept']) {
|
|
691
|
+
headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
|
|
692
|
+
}
|
|
693
|
+
if (!headers['Accept-Language']) {
|
|
694
|
+
headers['Accept-Language'] = 'en-US,en;q=0.5';
|
|
695
|
+
}
|
|
696
|
+
if (!headers['Accept-Encoding']) {
|
|
697
|
+
headers['Accept-Encoding'] = 'gzip, deflate, br';
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
return originalFetch.call(this, url, { ...options, headers });
|
|
701
|
+
};
|
|
702
|
+
}, 'fetch headers normalization');
|
|
703
|
+
|
|
704
|
+
// Image Loading Pattern Obfuscation
|
|
705
|
+
safeExecute(() => {
|
|
706
|
+
const originalImageSrc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
|
|
707
|
+
if (originalImageSrc) {
|
|
708
|
+
Object.defineProperty(HTMLImageElement.prototype, 'src', {
|
|
709
|
+
set: function(value) {
|
|
710
|
+
// Add random delay to image loading (0-50ms)
|
|
711
|
+
setTimeout(() => {
|
|
712
|
+
originalImageSrc.set.call(this, value);
|
|
713
|
+
}, Math.random() * 50);
|
|
714
|
+
},
|
|
715
|
+
get: originalImageSrc.get,
|
|
716
|
+
configurable: true
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
}, 'image loading obfuscation');
|
|
720
|
+
|
|
721
|
+
// CSS Media Query Spoofing
|
|
722
|
+
safeExecute(() => {
|
|
723
|
+
const originalMatchMedia = window.matchMedia;
|
|
724
|
+
window.matchMedia = function(query) {
|
|
725
|
+
const result = originalMatchMedia.call(this, query);
|
|
726
|
+
// Add slight randomization to avoid fingerprinting for device queries
|
|
727
|
+
if (query.includes('device-width') || query.includes('device-height') ||
|
|
728
|
+
query.includes('aspect-ratio') || query.includes('color-gamut')) {
|
|
729
|
+
Object.defineProperty(result, 'matches', {
|
|
730
|
+
get: () => Math.random() > 0.1 ? originalMatchMedia.call(window, query).matches : !originalMatchMedia.call(window, query).matches,
|
|
731
|
+
configurable: true
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
return result;
|
|
735
|
+
};
|
|
736
|
+
}, 'CSS media query spoofing');
|
|
737
|
+
|
|
738
|
+
// Enhanced WebRTC Spoofing
|
|
739
|
+
safeExecute(() => {
|
|
740
|
+
if (window.RTCPeerConnection) {
|
|
741
|
+
const OriginalRTC = window.RTCPeerConnection;
|
|
742
|
+
window.RTCPeerConnection = function(...args) {
|
|
743
|
+
const pc = new OriginalRTC(...args);
|
|
744
|
+
const originalCreateOffer = pc.createOffer;
|
|
745
|
+
pc.createOffer = function() {
|
|
746
|
+
return Promise.reject(new Error('WebRTC disabled'));
|
|
747
|
+
};
|
|
748
|
+
return pc;
|
|
749
|
+
};
|
|
750
|
+
Object.setPrototypeOf(window.RTCPeerConnection, OriginalRTC);
|
|
751
|
+
}
|
|
752
|
+
}, 'WebRTC spoofing');
|
|
753
|
+
|
|
754
|
+
// Font fingerprinting protection
|
|
755
|
+
safeExecute(() => {
|
|
756
|
+
// Standardize available fonts to common system fonts
|
|
757
|
+
const standardFonts = [
|
|
758
|
+
'Arial', 'Helvetica', 'Times New Roman', 'Times', 'Courier New', 'Courier',
|
|
759
|
+
'Verdana', 'Georgia', 'Palatino', 'Garamond', 'Bookman', 'Comic Sans MS',
|
|
760
|
+
'Trebuchet MS', 'Arial Black', 'Impact', 'Tahoma', 'Lucida Console'
|
|
761
|
+
];
|
|
762
|
+
|
|
763
|
+
// Override font detection methods
|
|
764
|
+
const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
|
|
765
|
+
const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
|
|
766
|
+
|
|
767
|
+
if (originalOffsetWidth && originalOffsetHeight) {
|
|
768
|
+
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
|
|
769
|
+
get: function() {
|
|
770
|
+
if (this.style && this.style.fontFamily) {
|
|
771
|
+
return Math.floor(originalOffsetWidth.get.call(this) + (Math.random() - 0.5) * 2);
|
|
772
|
+
}
|
|
773
|
+
return originalOffsetWidth.get.call(this);
|
|
774
|
+
},
|
|
775
|
+
configurable: true
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
}, 'font fingerprinting protection');
|
|
779
|
+
|
|
780
|
+
// Performance timing obfuscation
|
|
781
|
+
safeExecute(() => {
|
|
782
|
+
const originalNow = performance.now;
|
|
783
|
+
performance.now = function() {
|
|
784
|
+
return originalNow.call(this) + (Math.random() - 0.5) * 2; // +/- 1ms variation
|
|
785
|
+
};
|
|
786
|
+
}, 'performance timing obfuscation');
|
|
787
|
+
|
|
570
788
|
// Canvas fingerprinting protection
|
|
571
789
|
safeExecute(() => {
|
|
572
790
|
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
|
@@ -811,6 +1029,17 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
|
|
|
811
1029
|
// Memory spoofing
|
|
812
1030
|
safeDefinePropertyLocal(navigator, 'deviceMemory', { get: () => spoof.deviceMemory });
|
|
813
1031
|
safeDefinePropertyLocal(navigator, 'hardwareConcurrency', { get: () => spoof.hardwareConcurrency });
|
|
1032
|
+
|
|
1033
|
+
// Connection type spoofing
|
|
1034
|
+
safeDefinePropertyLocal(navigator, 'connection', {
|
|
1035
|
+
get: () => ({
|
|
1036
|
+
effectiveType: ['slow-2g', '2g', '3g', '4g'][Math.floor(Math.random() * 4)],
|
|
1037
|
+
type: Math.random() > 0.5 ? 'cellular' : 'wifi',
|
|
1038
|
+
saveData: Math.random() > 0.8,
|
|
1039
|
+
downlink: 1.5 + Math.random() * 8,
|
|
1040
|
+
rtt: 50 + Math.random() * 200
|
|
1041
|
+
})
|
|
1042
|
+
});
|
|
814
1043
|
|
|
815
1044
|
// Screen properties spoofing
|
|
816
1045
|
['width', 'height', 'availWidth', 'availHeight', 'colorDepth', 'pixelDepth'].forEach(prop => {
|
package/nwss.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// === Network scanner script (nwss.js) v2.0.
|
|
1
|
+
// === Network scanner script (nwss.js) v2.0.14 ===
|
|
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
|
|
@@ -130,7 +130,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
|
|
|
130
130
|
const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
|
|
131
131
|
|
|
132
132
|
// --- Script Configuration & Constants ---
|
|
133
|
-
const VERSION = '2.0.
|
|
133
|
+
const VERSION = '2.0.14'; // Script version
|
|
134
134
|
|
|
135
135
|
// get startTime
|
|
136
136
|
const startTime = Date.now();
|
|
@@ -2025,9 +2025,9 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
2025
2025
|
chrome: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
2026
2026
|
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",
|
|
2027
2027
|
chrome_linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
|
|
2028
|
-
firefox: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/
|
|
2029
|
-
firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/
|
|
2030
|
-
firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/
|
|
2028
|
+
firefox: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/143.0",
|
|
2029
|
+
firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/143.0",
|
|
2030
|
+
firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/143.0",
|
|
2031
2031
|
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"
|
|
2032
2032
|
};
|
|
2033
2033
|
curlUserAgent = userAgents[siteConfig.userAgent.toLowerCase()] || '';
|
|
@@ -3278,11 +3278,20 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
3278
3278
|
|
|
3279
3279
|
if (forceDebug) console.log(formatLogMessage('debug', `Standard reload #${i} completed for ${currentUrl}`));
|
|
3280
3280
|
} catch (standardReloadErr) {
|
|
3281
|
-
//
|
|
3282
|
-
|
|
3281
|
+
// Categorize errors into expected vs unexpected
|
|
3282
|
+
const isExpectedError = standardReloadErr.message.includes('timeout') ||
|
|
3283
|
+
standardReloadErr.message.includes('detached Frame') ||
|
|
3284
|
+
standardReloadErr.message.includes('Attempted to use detached') ||
|
|
3285
|
+
standardReloadErr.message.includes('Navigating frame was detached') ||
|
|
3286
|
+
standardReloadErr.message.includes('document invalid') ||
|
|
3287
|
+
standardReloadErr.message.includes('Page document invalid');
|
|
3288
|
+
|
|
3289
|
+
if (!isExpectedError) {
|
|
3290
|
+
// Only warn for truly unexpected errors
|
|
3283
3291
|
console.warn(messageColors.warn(`[standard reload #${i} failed] ${currentUrl}: ${standardReloadErr.message}`));
|
|
3284
3292
|
} else if (forceDebug) {
|
|
3285
|
-
|
|
3293
|
+
// Expected errors only shown in debug mode
|
|
3294
|
+
console.log(formatLogMessage('debug', `[reload #${i}] Expected error for ${currentUrl}: ${standardReloadErr.message}`));
|
|
3286
3295
|
}
|
|
3287
3296
|
|
|
3288
3297
|
// Check if this is a persistent failure that should skip remaining reloads
|
|
@@ -3993,4 +4002,4 @@ function setupFrameHandling(page, forceDebug) {
|
|
|
3993
4002
|
if (forceDebug) console.log(formatLogMessage('debug', `About to exit process...`));
|
|
3994
4003
|
process.exit(0);
|
|
3995
4004
|
|
|
3996
|
-
})();
|
|
4005
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanboynz/network-scanner",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.14",
|
|
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": {
|