@fanboynz/network-scanner 1.0.40 → 1.0.42

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.
Files changed (3) hide show
  1. package/lib/nettools.js +176 -36
  2. package/nwss.js +2 -2
  3. package/package.json +1 -1
package/lib/nettools.js CHANGED
@@ -725,9 +725,23 @@ function createNetToolsHandler(config) {
725
725
  const hasDig = digTerms && Array.isArray(digTerms) && digTerms.length > 0;
726
726
  const hasDigOr = digOrTerms && Array.isArray(digOrTerms) && digOrTerms.length > 0;
727
727
 
728
- // Add deduplication cache for nettools lookups
729
- const processedDomains = new Set();
730
-
728
+ // Add separate deduplication caches for different lookup types
729
+ const processedWhoisDomains = new Set();
730
+ const processedDigDomains = new Set();
731
+ // Add whois resolution caching to avoid redundant whois lookups
732
+ const whoisResultCache = new Map();
733
+ const WHOIS_CACHE_TTL = 900000; // 15 minutes cache TTL (whois data changes less frequently)
734
+ const MAX_CACHE_SIZE = 400; // Larger cache for whois due to longer TTL
735
+ // Size Memory
736
+ // 100 ~900KB
737
+ // 200 1.8MB
738
+ // 300 2.6MB
739
+ // 400 3.4MB
740
+ // 500 4.2MB
741
+ // Add DNS resolution caching to avoid redundant dig lookups
742
+ const digResultCache = new Map();
743
+ const DIG_CACHE_TTL = 300000; // 5 minutes cache TTL
744
+ const DIG_MAX_CACHE_SIZE = 400; // Smaller cache for dig due to shorter TTL
731
745
 
732
746
  return async function handleNetToolsCheck(domain, originalDomain) {
733
747
  // Helper function to log to BOTH console and debug file
@@ -761,18 +775,25 @@ function createNetToolsHandler(config) {
761
775
  }
762
776
  }
763
777
 
764
- // Skip if we've already processed this domain
765
- if (processedDomains.has(domain)) {
778
+ // Determine which domain will be used for dig lookup
779
+ const digDomain = digSubdomain && originalDomain ? originalDomain : domain;
780
+
781
+ // Check if we need to perform any lookups
782
+ const needsWhoisLookup = (hasWhois || hasWhoisOr) && !processedWhoisDomains.has(domain);
783
+ const needsDigLookup = (hasDig || hasDigOr) && !processedDigDomains.has(digDomain);
784
+
785
+ // Skip if we don't need to perform any lookups
786
+ if (!needsWhoisLookup && !needsDigLookup) {
766
787
  if (forceDebug) {
767
- logToConsoleAndFile(`${messageColors.highlight('[nettools]')} Skipping duplicate lookup for ${domain}`);
788
+ logToConsoleAndFile(`${messageColors.highlight('[nettools]')} Skipping duplicate lookups for ${domain} (whois: ${!needsWhoisLookup}, dig: ${!needsDigLookup})`);
768
789
  }
769
790
  return;
770
791
  }
771
792
 
772
- // Mark domain as being processed
773
- processedDomains.add(domain);
793
+
774
794
  if (forceDebug) {
775
- logToConsoleAndFile(`${messageColors.highlight('[nettools]')} Processing new domain: ${domain} (${processedDomains.size} total processed)`);
795
+ const totalProcessed = processedWhoisDomains.size + processedDigDomains.size;
796
+ logToConsoleAndFile(`${messageColors.highlight('[nettools]')} Processing domain: ${domain} (whois: ${needsWhoisLookup}, dig: ${needsDigLookup}) (${totalProcessed} total processed)`);
776
797
  }
777
798
 
778
799
  // Log site-specific whois delay if different from default
@@ -816,6 +837,7 @@ function createNetToolsHandler(config) {
816
837
  logToConsoleAndFile(`${messageColors.highlight('[nettools]')} digSubdomain setting: ${digSubdomain}`);
817
838
  logToConsoleAndFile(`${messageColors.highlight('[nettools]')} domain parameter: ${domain}`);
818
839
  logToConsoleAndFile(`${messageColors.highlight('[nettools]')} originalDomain parameter: ${originalDomain}`);
840
+ logToConsoleAndFile(`${messageColors.highlight('[nettools]')} Final digDomain will be: ${digDomain}`);
819
841
  if (whoisServer) {
820
842
  const serverInfo = Array.isArray(whoisServer)
821
843
  ? `randomized from [${whoisServer.join(', ')}]`
@@ -824,13 +846,6 @@ function createNetToolsHandler(config) {
824
846
  }
825
847
  }
826
848
 
827
- // Determine which domain to use for dig lookup
828
- const digDomain = digSubdomain && originalDomain ? originalDomain : domain;
829
-
830
- if (forceDebug) {
831
- logToConsoleAndFile(`${messageColors.highlight('[nettools]')} Final digDomain will be: ${digDomain}`);
832
- }
833
-
834
849
  // Enhanced dry run logging
835
850
  if (dryRunCallback && forceDebug) {
836
851
  logToConsoleAndFile(`${messageColors.highlight('[nettools-dryrun]')} Processing ${domain} (original: ${originalDomain})`);
@@ -863,15 +878,47 @@ function createNetToolsHandler(config) {
863
878
  }
864
879
 
865
880
  // Perform whois lookup if either whois or whois-or is configured
866
- if (hasWhois || hasWhoisOr) {
881
+ if (needsWhoisLookup) {
882
+ // Mark whois domain as being processed
883
+ processedWhoisDomains.add(domain);
884
+
885
+ // Check whois cache first - cache key includes server for accuracy
867
886
  const selectedServer = selectWhoisServer(whoisServer, whoisServerMode);
887
+ const whoisCacheKey = `${domain}-${selectedServer || 'default'}`;
888
+ const now = Date.now();
889
+ let whoisResult = null;
868
890
 
869
- if (forceDebug) {
870
- const serverInfo = selectedServer ? ` using server ${selectedServer}` : ' using default server';
871
- logToConsoleAndFile(`${messageColors.highlight('[whois]')} Performing whois lookup for ${domain}${serverInfo}`);
891
+ if (whoisResultCache.has(whoisCacheKey)) {
892
+ const cachedEntry = whoisResultCache.get(whoisCacheKey);
893
+ if (now - cachedEntry.timestamp < WHOIS_CACHE_TTL) {
894
+ if (forceDebug) {
895
+ const age = Math.round((now - cachedEntry.timestamp) / 1000);
896
+ const serverInfo = selectedServer ? ` (server: ${selectedServer})` : ' (default server)';
897
+ logToConsoleAndFile(`${messageColors.highlight('[whois-cache]')} Using cached result for ${domain}${serverInfo} [age: ${age}s]`);
898
+ }
899
+ whoisResult = {
900
+ ...cachedEntry.result,
901
+ // Add cache metadata
902
+ fromCache: true,
903
+ cacheAge: now - cachedEntry.timestamp,
904
+ originalTimestamp: cachedEntry.timestamp
905
+ };
906
+ } else {
907
+ // Cache expired, remove it
908
+ whoisResultCache.delete(whoisCacheKey);
909
+ if (forceDebug) {
910
+ logToConsoleAndFile(`${messageColors.highlight('[whois-cache]')} Cache expired for ${domain}, performing fresh lookup`);
911
+ }
912
+ }
872
913
  }
873
-
874
- try {
914
+
915
+ // Perform fresh lookup if not cached
916
+ if (!whoisResult) {
917
+ if (forceDebug) {
918
+ const serverInfo = selectedServer ? ` using server ${selectedServer}` : ' using default server';
919
+ logToConsoleAndFile(`${messageColors.highlight('[whois]')} Performing fresh whois lookup for ${domain}${serverInfo}`);
920
+ }
921
+
875
922
  // Configure retry options based on site config or use defaults
876
923
  const retryOptions = {
877
924
  maxRetries: siteConfig.whois_max_retries || 2,
@@ -881,7 +928,47 @@ function createNetToolsHandler(config) {
881
928
  retryOnError: siteConfig.whois_retry_on_error === true // Default false
882
929
  };
883
930
 
884
- const whoisResult = await whoisLookupWithRetry(domain, 8000, whoisServer, forceDebug, retryOptions, whoisDelay, logToConsoleAndFile);
931
+ try {
932
+ whoisResult = await whoisLookupWithRetry(domain, 8000, whoisServer, forceDebug, retryOptions, whoisDelay, logToConsoleAndFile);
933
+
934
+ // Cache successful results (and certain types of failures)
935
+ if (whoisResult.success ||
936
+ (whoisResult.error && !whoisResult.isTimeout &&
937
+ !whoisResult.error.toLowerCase().includes('connection') &&
938
+ !whoisResult.error.toLowerCase().includes('network'))) {
939
+
940
+ whoisResultCache.set(whoisCacheKey, {
941
+ result: whoisResult,
942
+ timestamp: now
943
+ });
944
+
945
+ if (forceDebug) {
946
+ const cacheType = whoisResult.success ? 'successful' : 'failed';
947
+ const serverInfo = selectedServer ? ` (server: ${selectedServer})` : ' (default server)';
948
+ logToConsoleAndFile(`${messageColors.highlight('[whois-cache]')} Cached ${cacheType} result for ${domain}${serverInfo}`);
949
+ }
950
+ }
951
+ } catch (whoisError) {
952
+ // Handle exceptions from whois lookup
953
+ if (forceDebug) {
954
+ logToConsoleAndFile(`${messageColors.highlight('[whois]')} Exception during lookup for ${domain}: ${whoisError.message}`);
955
+ logToConsoleAndFile(`${messageColors.highlight('[whois]')} Exception type: ${whoisError.constructor.name}`);
956
+ if (whoisError.stack) {
957
+ logToConsoleAndFile(`${messageColors.highlight('[whois]')} Stack trace: ${whoisError.stack.split('\n').slice(0, 3).join(' -> ')}`);
958
+ }
959
+ }
960
+
961
+ // Log whois exceptions in dry run mode
962
+ if (dryRunCallback && forceDebug) {
963
+ logToConsoleAndFile(`${messageColors.highlight('[whois-dryrun]')} Exception: ${whoisError.message}`);
964
+ }
965
+ // Continue with dig if configured
966
+ whoisResult = null; // Ensure we don't process a null result
967
+ }
968
+ }
969
+
970
+ // Process whois result (whether from cache or fresh lookup)
971
+ if (whoisResult) {
885
972
 
886
973
  if (whoisResult.success) {
887
974
  // Check AND terms if configured
@@ -891,6 +978,7 @@ function createNetToolsHandler(config) {
891
978
  dryRunCallback(domain, 'whois', 'AND logic', whoisTerms.join(', '), 'All terms found in whois data', {
892
979
  server: whoisResult.whoisServer || 'default',
893
980
  duration: whoisResult.duration,
981
+ fromCache: whoisResult.fromCache || false,
894
982
  retryAttempts: whoisResult.retryInfo?.totalAttempts || 1
895
983
  });
896
984
  }
@@ -908,6 +996,7 @@ function createNetToolsHandler(config) {
908
996
  dryRunCallback(domain, 'whois', 'OR logic', matchedTerm, 'Term found in whois data', {
909
997
  server: whoisResult.whoisServer || 'default',
910
998
  duration: whoisResult.duration,
999
+ fromCache: whoisResult.fromCache || false,
911
1000
  retryAttempts: whoisResult.retryInfo?.totalAttempts || 1
912
1001
  });
913
1002
  }
@@ -920,7 +1009,9 @@ function createNetToolsHandler(config) {
920
1009
  if (forceDebug) {
921
1010
  const serverUsed = whoisResult.whoisServer ? ` (server: ${whoisResult.whoisServer})` : ' (default server)';
922
1011
  const retryInfo = whoisResult.retryInfo ? ` [${whoisResult.retryInfo.totalAttempts}/${whoisResult.retryInfo.maxAttempts} attempts]` : '';
923
- logToConsoleAndFile(`${messageColors.highlight('[whois]')} Lookup completed for ${domain}${serverUsed} in ${whoisResult.duration}ms${retryInfo}`);
1012
+ const cacheInfo = whoisResult.fromCache ? ` [CACHED - ${Math.round(whoisResult.cacheAge / 1000)}s old]` : '';
1013
+ const duration = whoisResult.fromCache ? `cached in 0ms` : `in ${whoisResult.duration}ms`;
1014
+ logToConsoleAndFile(`${messageColors.highlight('[whois]')} Lookup completed for ${domain}${serverUsed} ${duration}${retryInfo}${cacheInfo}`);
924
1015
 
925
1016
  if (whoisResult.retryInfo && whoisResult.retryInfo.retriedAfterFailure) {
926
1017
  logToConsoleAndFile(`${messageColors.highlight('[whois]')} Success after retry - servers attempted: [${whoisResult.retryInfo.serversAttempted.map(s => s || 'default').join(', ')}]`);
@@ -996,25 +1087,29 @@ function createNetToolsHandler(config) {
996
1087
  }
997
1088
  // Don't return early - continue with dig if configured
998
1089
  }
999
- } catch (whoisError) {
1000
- if (forceDebug) {
1001
- logToConsoleAndFile(`${messageColors.highlight('[whois]')} Exception during lookup for ${domain}: ${whoisError.message}`);
1002
- logToConsoleAndFile(`${messageColors.highlight('[whois]')} Exception type: ${whoisError.constructor.name}`);
1003
- if (whoisError.stack) {
1004
- logToConsoleAndFile(`${messageColors.highlight('[whois]')} Stack trace: ${whoisError.stack.split('\n').slice(0, 3).join(' -> ')}`);
1090
+ }
1091
+
1092
+ // Periodic whois cache cleanup to prevent memory leaks
1093
+ if (whoisResultCache.size > MAX_CACHE_SIZE) {
1094
+ const now = Date.now();
1095
+ let cleanedCount = 0;
1096
+ for (const [key, entry] of whoisResultCache.entries()) {
1097
+ if (now - entry.timestamp > WHOIS_CACHE_TTL) {
1098
+ whoisResultCache.delete(key);
1099
+ cleanedCount++;
1005
1100
  }
1006
1101
  }
1007
-
1008
- // Log whois exceptions in dry run mode
1009
- if (dryRunCallback && forceDebug) {
1010
- logToConsoleAndFile(`${messageColors.highlight('[whois-dryrun]')} Exception: ${whoisError.message}`);
1102
+ if (forceDebug && cleanedCount > 0) {
1103
+ logToConsoleAndFile(`${messageColors.highlight('[whois-cache]')} Cleaned ${cleanedCount} expired entries, cache size: ${whoisResultCache.size}`);
1011
1104
  }
1012
- // Continue with dig if configured
1013
1105
  }
1014
1106
  }
1015
1107
 
1016
1108
  // Perform dig lookup if configured
1017
- if (hasDig || hasDigOr) {
1109
+ if (needsDigLookup) {
1110
+ // Mark dig domain as being processed
1111
+ processedDigDomains.add(digDomain);
1112
+
1018
1113
  if (forceDebug) {
1019
1114
  const digTypes = [];
1020
1115
  if (hasDig) digTypes.push('dig-and');
@@ -1023,7 +1118,37 @@ function createNetToolsHandler(config) {
1023
1118
  }
1024
1119
 
1025
1120
  try {
1121
+ // Check dig cache first to avoid redundant dig operations
1122
+ const digCacheKey = `${digDomain}-${digRecordType}`;
1123
+ const now = Date.now();
1124
+ let digResult = null;
1125
+
1126
+ if (digResultCache.has(digCacheKey)) {
1127
+ const cachedEntry = digResultCache.get(digCacheKey);
1128
+ if (now - cachedEntry.timestamp < DIG_CACHE_TTL) {
1129
+ if (forceDebug) {
1130
+ logToConsoleAndFile(`${messageColors.highlight('[dig-cache]')} Using cached result for ${digDomain} (${digRecordType}) [age: ${Math.round((now - cachedEntry.timestamp) / 1000)}s]`);
1131
+ }
1132
+ digResult = cachedEntry.result;
1133
+ } else {
1134
+ // Cache expired, remove it
1135
+ digResultCache.delete(digCacheKey);
1136
+ }
1137
+ }
1138
+
1139
+ if (!digResult) {
1026
1140
  const digResult = await digLookup(digDomain, digRecordType, 5000); // 5 second timeout for dig
1141
+
1142
+ // Cache the result for future use
1143
+ digResultCache.set(digCacheKey, {
1144
+ result: digResult,
1145
+ timestamp: now
1146
+ });
1147
+
1148
+ if (forceDebug && digResult.success) {
1149
+ logToConsoleAndFile(`${messageColors.highlight('[dig-cache]')} Cached new result for ${digDomain} (${digRecordType})`);
1150
+ }
1151
+ }
1027
1152
 
1028
1153
  if (digResult.success) {
1029
1154
  // Check AND terms if configured
@@ -1083,6 +1208,21 @@ function createNetToolsHandler(config) {
1083
1208
  logToConsoleAndFile(`${messageColors.highlight('[dig-dryrun]')} Exception: ${digError.message}`);
1084
1209
  }
1085
1210
  }
1211
+
1212
+ // Periodic dig cache cleanup to prevent memory leaks
1213
+ if (digResultCache.size > DIG_MAX_CACHE_SIZE) {
1214
+ const now = Date.now();
1215
+ let cleanedCount = 0;
1216
+ for (const [key, entry] of digResultCache.entries()) {
1217
+ if (now - entry.timestamp > DIG_CACHE_TTL) {
1218
+ digResultCache.delete(key);
1219
+ cleanedCount++;
1220
+ }
1221
+ }
1222
+ if (forceDebug && cleanedCount > 0) {
1223
+ logToConsoleAndFile(`${messageColors.highlight('[dig-cache]')} Cleaned ${cleanedCount} expired entries, cache size: ${digResultCache.size}`);
1224
+ }
1225
+ }
1086
1226
  }
1087
1227
 
1088
1228
  // Domain matches if any of these conditions are true:
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v1.0.40 ===
1
+ // === Network scanner script (nwss.js) v1.0.42 ===
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
@@ -33,7 +33,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
33
33
  const { monitorBrowserHealth, isBrowserHealthy } = require('./lib/browserhealth');
34
34
 
35
35
  // --- Script Configuration & Constants ---
36
- const VERSION = '1.0.40'; // Script version
36
+ const VERSION = '1.0.42'; // Script version
37
37
 
38
38
  // get startTime
39
39
  const startTime = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "1.0.40",
3
+ "version": "1.0.42",
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": {