honeyweb-core 2.0.4 → 2.0.5

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 (2) hide show
  1. package/package.json +1 -1
  2. package/utils/dns-verify.js +109 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "honeyweb-core",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Production-ready honeypot middleware with behavioral analysis, bot fingerprinting, and AI threat intelligence",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -2,10 +2,102 @@
2
2
 
3
3
  const dns = require('dns').promises;
4
4
  const LRUCache = require('./cache');
5
+ const https = require('https');
6
+
7
+ // Known bot IP ranges (fallback when DNS fails on Windows)
8
+ const BOT_IP_RANGES = {
9
+ 'googlebot.com': null, // Will be fetched dynamically
10
+ 'google.com': null,
11
+ 'search.msn.com': null,
12
+ 'slack.com': null,
13
+ 'facebook.com': null,
14
+ 'twitter.com': null,
15
+ 'linkedin.com': null,
16
+ 'apple.com': null,
17
+ 'duckduckgo.com': null
18
+ };
5
19
 
6
20
  class DNSVerifier {
7
21
  constructor(cacheTTL = 86400000) {
8
22
  this.cache = new LRUCache(500, cacheTTL);
23
+ this.ipRangesCache = null;
24
+ this.ipRangesCacheTime = 0;
25
+ this.ipRangesCacheTTL = 86400000; // 24 hours
26
+ }
27
+
28
+ // Fetch Googlebot IP ranges from Google's official API
29
+ async fetchGooglebotRanges() {
30
+ const now = Date.now();
31
+ if (this.ipRangesCache && (now - this.ipRangesCacheTime) < this.ipRangesCacheTTL) {
32
+ return this.ipRangesCache;
33
+ }
34
+
35
+ return new Promise((resolve, reject) => {
36
+ https.get('https://developers.google.com/search/apis/ipranges/googlebot.json', (res) => {
37
+ let data = '';
38
+ res.on('data', chunk => data += chunk);
39
+ res.on('end', () => {
40
+ try {
41
+ const json = JSON.parse(data);
42
+ const ranges = json.prefixes
43
+ .filter(p => p.ipv4Prefix)
44
+ .map(p => p.ipv4Prefix);
45
+ this.ipRangesCache = ranges;
46
+ this.ipRangesCacheTime = now;
47
+ resolve(ranges);
48
+ } catch (err) {
49
+ reject(err);
50
+ }
51
+ });
52
+ }).on('error', reject);
53
+ });
54
+ }
55
+
56
+ // Check if IP is in CIDR range
57
+ ipInRange(ip, cidr) {
58
+ const [range, bits] = cidr.split('/');
59
+ const mask = ~(2 ** (32 - parseInt(bits)) - 1);
60
+
61
+ const ipNum = ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet), 0) >>> 0;
62
+ const rangeNum = range.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet), 0) >>> 0;
63
+
64
+ return (ipNum & mask) === (rangeNum & mask);
65
+ }
66
+
67
+ // Fallback verification using IP ranges
68
+ async verifyByIpRange(ip, expectedDomain) {
69
+ // Only support Googlebot for now
70
+ if (!expectedDomain.includes('google')) {
71
+ return { verified: false, hostname: null, error: 'IP range verification only available for Google' };
72
+ }
73
+
74
+ try {
75
+ const ranges = await this.fetchGooglebotRanges();
76
+ const inRange = ranges.some(cidr => this.ipInRange(ip, cidr));
77
+
78
+ if (inRange) {
79
+ return {
80
+ verified: true,
81
+ hostname: 'googlebot.com (verified by IP range)',
82
+ error: null,
83
+ method: 'ip-range'
84
+ };
85
+ } else {
86
+ return {
87
+ verified: false,
88
+ hostname: null,
89
+ error: 'IP not in Googlebot ranges',
90
+ method: 'ip-range'
91
+ };
92
+ }
93
+ } catch (err) {
94
+ return {
95
+ verified: false,
96
+ hostname: null,
97
+ error: `IP range check failed: ${err.message}`,
98
+ method: 'ip-range'
99
+ };
100
+ }
9
101
  }
10
102
 
11
103
  async verify(ip, expectedDomain) {
@@ -13,10 +105,17 @@ class DNSVerifier {
13
105
  if (this.cache.has(cacheKey)) return this.cache.get(cacheKey);
14
106
 
15
107
  try {
16
- // Reverse DNS: IP -> hostname
108
+ // Try DNS verification first
17
109
  const hostnames = await dns.reverse(ip);
18
110
 
19
111
  if (!hostnames || hostnames.length === 0) {
112
+ // DNS failed - try IP range fallback for Google
113
+ if (expectedDomain.includes('google')) {
114
+ const rangeResult = await this.verifyByIpRange(ip, expectedDomain);
115
+ this.cache.set(cacheKey, rangeResult);
116
+ return rangeResult;
117
+ }
118
+
20
119
  const result = { verified: false, hostname: null, error: 'No reverse DNS record found' };
21
120
  this.cache.set(cacheKey, result);
22
121
  return result;
@@ -39,11 +138,18 @@ class DNSVerifier {
39
138
  return result;
40
139
  }
41
140
 
42
- const result = { verified: true, hostname, error: null };
141
+ const result = { verified: true, hostname, error: null, method: 'dns' };
43
142
  this.cache.set(cacheKey, result);
44
143
  return result;
45
144
 
46
145
  } catch (err) {
146
+ // DNS lookup failed - try IP range fallback for Google
147
+ if (expectedDomain.includes('google')) {
148
+ const rangeResult = await this.verifyByIpRange(ip, expectedDomain);
149
+ this.cache.set(cacheKey, rangeResult, 300000);
150
+ return rangeResult;
151
+ }
152
+
47
153
  const result = { verified: false, hostname: null, error: err.message };
48
154
  this.cache.set(cacheKey, result, 300000);
49
155
  return result;
@@ -52,6 +158,7 @@ class DNSVerifier {
52
158
 
53
159
  clearCache() {
54
160
  this.cache.clear();
161
+ this.ipRangesCache = null;
55
162
  }
56
163
  }
57
164