@push.rocks/smartmta 5.1.2 → 5.2.0
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/changelog.md +14 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/index.d.ts +3 -0
- package/dist_ts/index.js +4 -0
- package/dist_ts/logger.d.ts +17 -0
- package/dist_ts/logger.js +76 -0
- package/dist_ts/mail/core/classes.bouncemanager.d.ts +185 -0
- package/dist_ts/mail/core/classes.bouncemanager.js +569 -0
- package/dist_ts/mail/core/classes.email.d.ts +291 -0
- package/dist_ts/mail/core/classes.email.js +802 -0
- package/dist_ts/mail/core/classes.emailvalidator.d.ts +61 -0
- package/dist_ts/mail/core/classes.emailvalidator.js +184 -0
- package/dist_ts/mail/core/classes.templatemanager.d.ts +95 -0
- package/dist_ts/mail/core/classes.templatemanager.js +240 -0
- package/dist_ts/mail/core/index.d.ts +4 -0
- package/dist_ts/mail/core/index.js +6 -0
- package/dist_ts/mail/delivery/classes.delivery.queue.d.ts +163 -0
- package/dist_ts/mail/delivery/classes.delivery.queue.js +488 -0
- package/dist_ts/mail/delivery/classes.delivery.system.d.ts +160 -0
- package/dist_ts/mail/delivery/classes.delivery.system.js +630 -0
- package/dist_ts/mail/delivery/classes.unified.rate.limiter.d.ts +200 -0
- package/dist_ts/mail/delivery/classes.unified.rate.limiter.js +820 -0
- package/dist_ts/mail/delivery/index.d.ts +4 -0
- package/dist_ts/mail/delivery/index.js +6 -0
- package/dist_ts/mail/delivery/interfaces.d.ts +140 -0
- package/dist_ts/mail/delivery/interfaces.js +17 -0
- package/dist_ts/mail/index.d.ts +7 -0
- package/dist_ts/mail/index.js +12 -0
- package/dist_ts/mail/routing/classes.dkim.manager.d.ts +25 -0
- package/dist_ts/mail/routing/classes.dkim.manager.js +127 -0
- package/dist_ts/mail/routing/classes.dns.manager.d.ts +79 -0
- package/dist_ts/mail/routing/classes.dns.manager.js +415 -0
- package/dist_ts/mail/routing/classes.domain.registry.d.ts +54 -0
- package/dist_ts/mail/routing/classes.domain.registry.js +119 -0
- package/dist_ts/mail/routing/classes.email.action.executor.d.ts +33 -0
- package/dist_ts/mail/routing/classes.email.action.executor.js +137 -0
- package/dist_ts/mail/routing/classes.email.router.d.ts +171 -0
- package/dist_ts/mail/routing/classes.email.router.js +494 -0
- package/dist_ts/mail/routing/classes.unified.email.server.d.ts +241 -0
- package/dist_ts/mail/routing/classes.unified.email.server.js +935 -0
- package/dist_ts/mail/routing/index.d.ts +7 -0
- package/dist_ts/mail/routing/index.js +9 -0
- package/dist_ts/mail/routing/interfaces.d.ts +187 -0
- package/dist_ts/mail/routing/interfaces.js +2 -0
- package/dist_ts/mail/security/classes.dkimcreator.d.ts +72 -0
- package/dist_ts/mail/security/classes.dkimcreator.js +360 -0
- package/dist_ts/mail/security/classes.spfverifier.d.ts +62 -0
- package/dist_ts/mail/security/classes.spfverifier.js +87 -0
- package/dist_ts/mail/security/index.d.ts +2 -0
- package/dist_ts/mail/security/index.js +4 -0
- package/dist_ts/paths.d.ts +14 -0
- package/dist_ts/paths.js +39 -0
- package/dist_ts/plugins.d.ts +24 -0
- package/dist_ts/plugins.js +28 -0
- package/dist_ts/security/classes.contentscanner.d.ts +130 -0
- package/dist_ts/security/classes.contentscanner.js +338 -0
- package/dist_ts/security/classes.ipreputationchecker.d.ts +73 -0
- package/dist_ts/security/classes.ipreputationchecker.js +263 -0
- package/dist_ts/security/classes.rustsecuritybridge.d.ts +398 -0
- package/dist_ts/security/classes.rustsecuritybridge.js +484 -0
- package/dist_ts/security/classes.securitylogger.d.ts +140 -0
- package/dist_ts/security/classes.securitylogger.js +235 -0
- package/dist_ts/security/index.d.ts +4 -0
- package/dist_ts/security/index.js +5 -0
- package/package.json +6 -1
- package/readme.md +52 -9
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +3 -0
- package/ts/logger.ts +91 -0
- package/ts/mail/core/classes.bouncemanager.ts +731 -0
- package/ts/mail/core/classes.email.ts +942 -0
- package/ts/mail/core/classes.emailvalidator.ts +239 -0
- package/ts/mail/core/classes.templatemanager.ts +320 -0
- package/ts/mail/core/index.ts +5 -0
- package/ts/mail/delivery/classes.delivery.queue.ts +645 -0
- package/ts/mail/delivery/classes.delivery.system.ts +816 -0
- package/ts/mail/delivery/classes.unified.rate.limiter.ts +1053 -0
- package/ts/mail/delivery/index.ts +5 -0
- package/ts/mail/delivery/interfaces.ts +167 -0
- package/ts/mail/index.ts +17 -0
- package/ts/mail/routing/classes.dkim.manager.ts +157 -0
- package/ts/mail/routing/classes.dns.manager.ts +573 -0
- package/ts/mail/routing/classes.domain.registry.ts +139 -0
- package/ts/mail/routing/classes.email.action.executor.ts +175 -0
- package/ts/mail/routing/classes.email.router.ts +575 -0
- package/ts/mail/routing/classes.unified.email.server.ts +1207 -0
- package/ts/mail/routing/index.ts +9 -0
- package/ts/mail/routing/interfaces.ts +202 -0
- package/ts/mail/security/classes.dkimcreator.ts +447 -0
- package/ts/mail/security/classes.spfverifier.ts +126 -0
- package/ts/mail/security/index.ts +3 -0
- package/ts/paths.ts +48 -0
- package/ts/plugins.ts +53 -0
- package/ts/security/classes.contentscanner.ts +400 -0
- package/ts/security/classes.ipreputationchecker.ts +315 -0
- package/ts/security/classes.rustsecuritybridge.ts +943 -0
- package/ts/security/classes.securitylogger.ts +299 -0
- package/ts/security/index.ts +40 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as paths from '../paths.js';
|
|
3
|
+
import { logger } from '../logger.js';
|
|
4
|
+
import { Email } from '../mail/core/classes.email.js';
|
|
5
|
+
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from './classes.securitylogger.js';
|
|
6
|
+
import { RustSecurityBridge } from './classes.rustsecuritybridge.js';
|
|
7
|
+
import { LRUCache } from 'lru-cache';
|
|
8
|
+
/**
|
|
9
|
+
* Threat categories
|
|
10
|
+
*/
|
|
11
|
+
export var ThreatCategory;
|
|
12
|
+
(function (ThreatCategory) {
|
|
13
|
+
ThreatCategory["SPAM"] = "spam";
|
|
14
|
+
ThreatCategory["PHISHING"] = "phishing";
|
|
15
|
+
ThreatCategory["MALWARE"] = "malware";
|
|
16
|
+
ThreatCategory["EXECUTABLE"] = "executable";
|
|
17
|
+
ThreatCategory["SUSPICIOUS_LINK"] = "suspicious_link";
|
|
18
|
+
ThreatCategory["MALICIOUS_MACRO"] = "malicious_macro";
|
|
19
|
+
ThreatCategory["XSS"] = "xss";
|
|
20
|
+
ThreatCategory["SENSITIVE_DATA"] = "sensitive_data";
|
|
21
|
+
ThreatCategory["BLACKLISTED_CONTENT"] = "blacklisted_content";
|
|
22
|
+
ThreatCategory["CUSTOM_RULE"] = "custom_rule";
|
|
23
|
+
})(ThreatCategory || (ThreatCategory = {}));
|
|
24
|
+
/**
|
|
25
|
+
* Content Scanner for detecting malicious email content
|
|
26
|
+
*/
|
|
27
|
+
export class ContentScanner {
|
|
28
|
+
static instance;
|
|
29
|
+
scanCache;
|
|
30
|
+
options;
|
|
31
|
+
/**
|
|
32
|
+
* Default options for the content scanner
|
|
33
|
+
*/
|
|
34
|
+
static DEFAULT_OPTIONS = {
|
|
35
|
+
maxCacheSize: 10000,
|
|
36
|
+
cacheTTL: 24 * 60 * 60 * 1000, // 24 hours
|
|
37
|
+
scanSubject: true,
|
|
38
|
+
scanBody: true,
|
|
39
|
+
scanAttachments: true,
|
|
40
|
+
maxAttachmentSizeToScan: 10 * 1024 * 1024, // 10MB
|
|
41
|
+
scanAttachmentNames: true,
|
|
42
|
+
blockExecutables: true,
|
|
43
|
+
blockMacros: true,
|
|
44
|
+
customRules: [],
|
|
45
|
+
minThreatScore: 30, // Minimum score to consider content as a threat
|
|
46
|
+
highThreatScore: 70 // Score above which content is considered high threat
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Constructor for the ContentScanner
|
|
50
|
+
* @param options Configuration options
|
|
51
|
+
*/
|
|
52
|
+
constructor(options = {}) {
|
|
53
|
+
// Merge with default options
|
|
54
|
+
this.options = {
|
|
55
|
+
...ContentScanner.DEFAULT_OPTIONS,
|
|
56
|
+
...options
|
|
57
|
+
};
|
|
58
|
+
// Initialize cache
|
|
59
|
+
this.scanCache = new LRUCache({
|
|
60
|
+
max: this.options.maxCacheSize,
|
|
61
|
+
ttl: this.options.cacheTTL,
|
|
62
|
+
});
|
|
63
|
+
logger.log('info', 'ContentScanner initialized');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the singleton instance of the scanner
|
|
67
|
+
* @param options Configuration options
|
|
68
|
+
* @returns Singleton scanner instance
|
|
69
|
+
*/
|
|
70
|
+
static getInstance(options = {}) {
|
|
71
|
+
if (!ContentScanner.instance) {
|
|
72
|
+
ContentScanner.instance = new ContentScanner(options);
|
|
73
|
+
}
|
|
74
|
+
return ContentScanner.instance;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Scan an email for malicious content.
|
|
78
|
+
* Delegates text/subject/html/filename pattern scanning to Rust.
|
|
79
|
+
* Binary attachment scanning (PE headers, VBA macros) stays in TS.
|
|
80
|
+
* @param email The email to scan
|
|
81
|
+
* @returns Scan result
|
|
82
|
+
*/
|
|
83
|
+
async scanEmail(email) {
|
|
84
|
+
try {
|
|
85
|
+
// Generate a cache key from the email
|
|
86
|
+
const cacheKey = this.generateCacheKey(email);
|
|
87
|
+
// Check cache first
|
|
88
|
+
const cachedResult = this.scanCache.get(cacheKey);
|
|
89
|
+
if (cachedResult) {
|
|
90
|
+
logger.log('info', `Using cached scan result for email ${email.getMessageId()}`);
|
|
91
|
+
return cachedResult;
|
|
92
|
+
}
|
|
93
|
+
// Delegate text/subject/html/filename scanning to Rust
|
|
94
|
+
const bridge = RustSecurityBridge.getInstance();
|
|
95
|
+
const rustResult = await bridge.scanContent({
|
|
96
|
+
subject: this.options.scanSubject ? email.subject : undefined,
|
|
97
|
+
textBody: this.options.scanBody ? email.text : undefined,
|
|
98
|
+
htmlBody: this.options.scanBody ? email.html : undefined,
|
|
99
|
+
attachmentNames: this.options.scanAttachmentNames
|
|
100
|
+
? email.attachments?.map(a => a.filename) ?? []
|
|
101
|
+
: [],
|
|
102
|
+
});
|
|
103
|
+
const result = {
|
|
104
|
+
isClean: true,
|
|
105
|
+
threatScore: rustResult.threatScore,
|
|
106
|
+
threatType: rustResult.threatType ?? undefined,
|
|
107
|
+
threatDetails: rustResult.threatDetails ?? undefined,
|
|
108
|
+
scannedElements: rustResult.scannedElements,
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
};
|
|
111
|
+
// Attachment binary scanning stays in TS (PE headers, macro detection)
|
|
112
|
+
if (this.options.scanAttachments && email.attachments?.length > 0) {
|
|
113
|
+
for (const attachment of email.attachments) {
|
|
114
|
+
this.scanAttachmentBinary(attachment, result);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Apply custom rules (TS-only, runtime-configured)
|
|
118
|
+
this.applyCustomRules(email, result);
|
|
119
|
+
// Determine if the email is clean based on threat score
|
|
120
|
+
result.isClean = result.threatScore < this.options.minThreatScore;
|
|
121
|
+
// Save to cache
|
|
122
|
+
this.scanCache.set(cacheKey, result);
|
|
123
|
+
// Log high threat findings
|
|
124
|
+
if (result.threatScore >= this.options.highThreatScore) {
|
|
125
|
+
this.logHighThreatFound(email, result);
|
|
126
|
+
}
|
|
127
|
+
else if (!result.isClean) {
|
|
128
|
+
this.logThreatFound(email, result);
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.log('error', `Error scanning email: ${error.message}`, {
|
|
134
|
+
messageId: email.getMessageId(),
|
|
135
|
+
error: error.stack
|
|
136
|
+
});
|
|
137
|
+
// Return a safe default with error indication
|
|
138
|
+
return {
|
|
139
|
+
isClean: true,
|
|
140
|
+
threatScore: 0,
|
|
141
|
+
scannedElements: ['error'],
|
|
142
|
+
timestamp: Date.now(),
|
|
143
|
+
threatType: 'scan_error',
|
|
144
|
+
threatDetails: `Scan error: ${error.message}`
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Generate a cache key from an email
|
|
150
|
+
* @param email The email to generate a key for
|
|
151
|
+
* @returns Cache key
|
|
152
|
+
*/
|
|
153
|
+
generateCacheKey(email) {
|
|
154
|
+
// Use message ID if available
|
|
155
|
+
if (email.getMessageId()) {
|
|
156
|
+
return `email:${email.getMessageId()}`;
|
|
157
|
+
}
|
|
158
|
+
// Fallback to a hash of key content
|
|
159
|
+
const contentToHash = [
|
|
160
|
+
email.from,
|
|
161
|
+
email.subject || '',
|
|
162
|
+
email.text?.substring(0, 1000) || '',
|
|
163
|
+
email.html?.substring(0, 1000) || '',
|
|
164
|
+
email.attachments?.length || 0
|
|
165
|
+
].join(':');
|
|
166
|
+
return `email:${plugins.crypto.createHash('sha256').update(contentToHash).digest('hex')}`;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Scan attachment binary content for PE headers and VBA macros.
|
|
170
|
+
* This stays in TS because it accesses raw Buffer data (too large for IPC).
|
|
171
|
+
* @param attachment The attachment to scan
|
|
172
|
+
* @param result The scan result to update
|
|
173
|
+
*/
|
|
174
|
+
scanAttachmentBinary(attachment, result) {
|
|
175
|
+
if (!attachment.content) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Skip large attachments
|
|
179
|
+
if (attachment.content.length > this.options.maxAttachmentSizeToScan) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const filename = attachment.filename.toLowerCase();
|
|
183
|
+
// Check for PE headers (Windows executables disguised with non-.exe extensions)
|
|
184
|
+
if (attachment.content.length > 64 &&
|
|
185
|
+
attachment.content[0] === 0x4D &&
|
|
186
|
+
attachment.content[1] === 0x5A) { // 'MZ' header
|
|
187
|
+
result.threatScore += 80;
|
|
188
|
+
result.threatType = ThreatCategory.EXECUTABLE;
|
|
189
|
+
result.threatDetails = `Attachment contains executable code: ${filename}`;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
// Check for VBA macro indicators in Office documents
|
|
193
|
+
if (this.options.blockMacros && this.likelyContainsMacros(attachment)) {
|
|
194
|
+
result.threatScore += 60;
|
|
195
|
+
result.threatType = ThreatCategory.MALICIOUS_MACRO;
|
|
196
|
+
result.threatDetails = `Attachment appears to contain macros: ${filename}`;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Apply custom rules (runtime-configured patterns) to the email.
|
|
201
|
+
* These stay in TS because they are configured at runtime.
|
|
202
|
+
* @param email The email to check
|
|
203
|
+
* @param result The scan result to update
|
|
204
|
+
*/
|
|
205
|
+
applyCustomRules(email, result) {
|
|
206
|
+
if (!this.options.customRules.length) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const textsToCheck = [];
|
|
210
|
+
if (email.subject)
|
|
211
|
+
textsToCheck.push(email.subject);
|
|
212
|
+
if (email.text)
|
|
213
|
+
textsToCheck.push(email.text);
|
|
214
|
+
if (email.html)
|
|
215
|
+
textsToCheck.push(email.html);
|
|
216
|
+
for (const rule of this.options.customRules) {
|
|
217
|
+
const pattern = rule.pattern instanceof RegExp ? rule.pattern : new RegExp(rule.pattern, 'i');
|
|
218
|
+
for (const text of textsToCheck) {
|
|
219
|
+
if (pattern.test(text)) {
|
|
220
|
+
result.threatScore += rule.score;
|
|
221
|
+
result.threatType = rule.type;
|
|
222
|
+
result.threatDetails = rule.description;
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Extract text from a binary buffer for scanning
|
|
230
|
+
* @param buffer Binary content
|
|
231
|
+
* @returns Extracted text (may be partial)
|
|
232
|
+
*/
|
|
233
|
+
extractTextFromBuffer(buffer) {
|
|
234
|
+
try {
|
|
235
|
+
// Limit the amount we convert to avoid memory issues
|
|
236
|
+
const sampleSize = Math.min(buffer.length, 100 * 1024); // 100KB max sample
|
|
237
|
+
const sample = buffer.slice(0, sampleSize);
|
|
238
|
+
// Try to convert to string, filtering out non-printable chars
|
|
239
|
+
return sample.toString('utf8')
|
|
240
|
+
.replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, '') // Remove control chars
|
|
241
|
+
.replace(/\uFFFD/g, ''); // Remove replacement char
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
logger.log('warn', `Error extracting text from buffer: ${error.message}`);
|
|
245
|
+
return '';
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Check if an Office document likely contains macros
|
|
250
|
+
* @param attachment The attachment to check
|
|
251
|
+
* @returns Whether the file likely contains macros
|
|
252
|
+
*/
|
|
253
|
+
likelyContainsMacros(attachment) {
|
|
254
|
+
const content = this.extractTextFromBuffer(attachment.content);
|
|
255
|
+
const macroIndicators = [
|
|
256
|
+
/vbaProject\.bin/i,
|
|
257
|
+
/Microsoft VBA/i,
|
|
258
|
+
/\bVBA\b/,
|
|
259
|
+
/Auto_Open/i,
|
|
260
|
+
/AutoExec/i,
|
|
261
|
+
/DocumentOpen/i,
|
|
262
|
+
/AutoOpen/i,
|
|
263
|
+
/\bExecute\(/i,
|
|
264
|
+
/\bShell\(/i,
|
|
265
|
+
/\bCreateObject\(/i
|
|
266
|
+
];
|
|
267
|
+
for (const indicator of macroIndicators) {
|
|
268
|
+
if (indicator.test(content)) {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Log a high threat finding to the security logger
|
|
276
|
+
* @param email The email containing the threat
|
|
277
|
+
* @param result The scan result
|
|
278
|
+
*/
|
|
279
|
+
logHighThreatFound(email, result) {
|
|
280
|
+
SecurityLogger.getInstance().logEvent({
|
|
281
|
+
level: SecurityLogLevel.ERROR,
|
|
282
|
+
type: SecurityEventType.MALWARE,
|
|
283
|
+
message: `High threat content detected in email from ${email.from} to ${email.to.join(', ')}`,
|
|
284
|
+
details: {
|
|
285
|
+
messageId: email.getMessageId(),
|
|
286
|
+
threatType: result.threatType,
|
|
287
|
+
threatDetails: result.threatDetails,
|
|
288
|
+
threatScore: result.threatScore,
|
|
289
|
+
scannedElements: result.scannedElements,
|
|
290
|
+
subject: email.subject
|
|
291
|
+
},
|
|
292
|
+
success: false,
|
|
293
|
+
domain: email.getFromDomain()
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Log a threat finding to the security logger
|
|
298
|
+
* @param email The email containing the threat
|
|
299
|
+
* @param result The scan result
|
|
300
|
+
*/
|
|
301
|
+
logThreatFound(email, result) {
|
|
302
|
+
SecurityLogger.getInstance().logEvent({
|
|
303
|
+
level: SecurityLogLevel.WARN,
|
|
304
|
+
type: SecurityEventType.SPAM,
|
|
305
|
+
message: `Suspicious content detected in email from ${email.from} to ${email.to.join(', ')}`,
|
|
306
|
+
details: {
|
|
307
|
+
messageId: email.getMessageId(),
|
|
308
|
+
threatType: result.threatType,
|
|
309
|
+
threatDetails: result.threatDetails,
|
|
310
|
+
threatScore: result.threatScore,
|
|
311
|
+
scannedElements: result.scannedElements,
|
|
312
|
+
subject: email.subject
|
|
313
|
+
},
|
|
314
|
+
success: false,
|
|
315
|
+
domain: email.getFromDomain()
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get threat level description based on score
|
|
320
|
+
* @param score Threat score
|
|
321
|
+
* @returns Threat level description
|
|
322
|
+
*/
|
|
323
|
+
static getThreatLevel(score) {
|
|
324
|
+
if (score < 20) {
|
|
325
|
+
return 'none';
|
|
326
|
+
}
|
|
327
|
+
else if (score < 40) {
|
|
328
|
+
return 'low';
|
|
329
|
+
}
|
|
330
|
+
else if (score < 70) {
|
|
331
|
+
return 'medium';
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
return 'high';
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb250ZW50c2Nhbm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3NlY3VyaXR5L2NsYXNzZXMuY29udGVudHNjYW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxLQUFLLEtBQUssTUFBTSxhQUFhLENBQUM7QUFDckMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFdEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFxQ3JDOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksY0FXWDtBQVhELFdBQVksY0FBYztJQUN4QiwrQkFBYSxDQUFBO0lBQ2IsdUNBQXFCLENBQUE7SUFDckIscUNBQW1CLENBQUE7SUFDbkIsMkNBQXlCLENBQUE7SUFDekIscURBQW1DLENBQUE7SUFDbkMscURBQW1DLENBQUE7SUFDbkMsNkJBQVcsQ0FBQTtJQUNYLG1EQUFpQyxDQUFBO0lBQ2pDLDZEQUEyQyxDQUFBO0lBQzNDLDZDQUEyQixDQUFBO0FBQzdCLENBQUMsRUFYVyxjQUFjLEtBQWQsY0FBYyxRQVd6QjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFDakIsTUFBTSxDQUFDLFFBQVEsQ0FBaUI7SUFDaEMsU0FBUyxDQUFnQztJQUN6QyxPQUFPLENBQW1DO0lBRWxEOztPQUVHO0lBQ0ssTUFBTSxDQUFVLGVBQWUsR0FBcUM7UUFDMUUsWUFBWSxFQUFFLEtBQUs7UUFDbkIsUUFBUSxFQUFFLEVBQUUsR0FBRyxFQUFF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
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reputation check result information
|
|
3
|
+
*/
|
|
4
|
+
export interface IReputationResult {
|
|
5
|
+
score: number;
|
|
6
|
+
isSpam: boolean;
|
|
7
|
+
isProxy: boolean;
|
|
8
|
+
isTor: boolean;
|
|
9
|
+
isVPN: boolean;
|
|
10
|
+
country?: string;
|
|
11
|
+
asn?: string;
|
|
12
|
+
org?: string;
|
|
13
|
+
blacklists?: string[];
|
|
14
|
+
timestamp: number;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reputation threshold scores
|
|
19
|
+
*/
|
|
20
|
+
export declare enum ReputationThreshold {
|
|
21
|
+
HIGH_RISK = 20,// Score below this is considered high risk
|
|
22
|
+
MEDIUM_RISK = 50,// Score below this is considered medium risk
|
|
23
|
+
LOW_RISK = 80
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* IP type classifications
|
|
27
|
+
*/
|
|
28
|
+
export declare enum IPType {
|
|
29
|
+
RESIDENTIAL = "residential",
|
|
30
|
+
DATACENTER = "datacenter",
|
|
31
|
+
PROXY = "proxy",
|
|
32
|
+
TOR = "tor",
|
|
33
|
+
VPN = "vpn",
|
|
34
|
+
UNKNOWN = "unknown"
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Options for the IP Reputation Checker
|
|
38
|
+
*/
|
|
39
|
+
export interface IIPReputationOptions {
|
|
40
|
+
maxCacheSize?: number;
|
|
41
|
+
cacheTTL?: number;
|
|
42
|
+
dnsblServers?: string[];
|
|
43
|
+
highRiskThreshold?: number;
|
|
44
|
+
mediumRiskThreshold?: number;
|
|
45
|
+
lowRiskThreshold?: number;
|
|
46
|
+
enableLocalCache?: boolean;
|
|
47
|
+
enableDNSBL?: boolean;
|
|
48
|
+
enableIPInfo?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* IP reputation checker — delegates DNSBL lookups to the Rust security bridge.
|
|
52
|
+
* Retains LRU caching and disk persistence in TypeScript.
|
|
53
|
+
*/
|
|
54
|
+
export declare class IPReputationChecker {
|
|
55
|
+
private static instance;
|
|
56
|
+
private reputationCache;
|
|
57
|
+
private options;
|
|
58
|
+
private storageManager?;
|
|
59
|
+
private static readonly DEFAULT_OPTIONS;
|
|
60
|
+
constructor(options?: IIPReputationOptions, storageManager?: any);
|
|
61
|
+
static getInstance(options?: IIPReputationOptions, storageManager?: any): IPReputationChecker;
|
|
62
|
+
/**
|
|
63
|
+
* Check an IP address's reputation via the Rust bridge
|
|
64
|
+
*/
|
|
65
|
+
checkReputation(ip: string): Promise<IReputationResult>;
|
|
66
|
+
private createErrorResult;
|
|
67
|
+
private isValidIPAddress;
|
|
68
|
+
private logReputationCheck;
|
|
69
|
+
private saveCache;
|
|
70
|
+
private loadCache;
|
|
71
|
+
static getRiskLevel(score: number): 'high' | 'medium' | 'low' | 'trusted';
|
|
72
|
+
updateStorageManager(storageManager: any): void;
|
|
73
|
+
}
|