@riavzon/bot-detector-create 1.0.11 → 1.0.13
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/dist/create.js +3 -3
- package/package.json +4 -1
- package/eslint.config.mjs +0 -6
- package/src/create.ts +0 -59
- package/src/default.ts +0 -276
- package/tsconfig.json +0 -10
- package/tsdown.config.ts +0 -10
package/dist/create.js
CHANGED
|
@@ -7,7 +7,7 @@ import { spawn } from "node:child_process";
|
|
|
7
7
|
//#region src/default.ts
|
|
8
8
|
const defaultStore = { main: {
|
|
9
9
|
driver: "sqlite",
|
|
10
|
-
name: "./bot_detector
|
|
10
|
+
name: "./bot_detector"
|
|
11
11
|
} };
|
|
12
12
|
const mainContent = `import './botDetectorConfig.js';
|
|
13
13
|
import express from 'express';
|
|
@@ -42,7 +42,7 @@ await defineConfiguration({
|
|
|
42
42
|
store: {
|
|
43
43
|
main: {
|
|
44
44
|
driver: 'sqlite',
|
|
45
|
-
name: './bot_detector
|
|
45
|
+
name: './bot_detector',
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
48
|
|
|
@@ -58,7 +58,7 @@ await defineConfiguration({
|
|
|
58
58
|
setNewComputedScore: false,
|
|
59
59
|
|
|
60
60
|
// ─── Whitelist (IPv4, IPv6, or CIDR) ───────────────────────────────────────
|
|
61
|
-
whiteList: [],
|
|
61
|
+
whiteList: ['127.0.0.1', '::1'],
|
|
62
62
|
|
|
63
63
|
// ─── Re-check interval for returning visitors ──────────────────────────────
|
|
64
64
|
checksTimeRateControl: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riavzon/bot-detector-create",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Sergio contact@riavzon.com",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/Sergo706/botDetector/issues"
|
|
15
15
|
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
16
19
|
"keywords": [
|
|
17
20
|
"bot-detection",
|
|
18
21
|
"express-middleware",
|
package/eslint.config.mjs
DELETED
package/src/create.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
-
|
|
4
|
-
import consola from 'consola';
|
|
5
|
-
import { defineCommand, runMain } from 'citty';
|
|
6
|
-
import fs from 'node:fs/promises';
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import { spawn } from 'node:child_process';
|
|
9
|
-
import { content, mainContent, defaultStore } from './default.js';
|
|
10
|
-
|
|
11
|
-
function run(cmd: string, args: string[]): Promise<void> {
|
|
12
|
-
return new Promise((resolve, reject) => {
|
|
13
|
-
const child = spawn(cmd, args, { stdio: 'inherit', shell: true });
|
|
14
|
-
child.on('close', code => {
|
|
15
|
-
if (code === 0) { resolve(); } else { reject(new Error(`${cmd} exited with code ${String(code)}`)); }
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const start = defineCommand({
|
|
21
|
-
meta: {
|
|
22
|
-
name: 'Create Bot Detector',
|
|
23
|
-
description: 'Quick starter for @riavzon/bot-detector'
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
async run() {
|
|
27
|
-
const output = path.resolve(process.cwd(), 'botDetectorConfig.ts');
|
|
28
|
-
|
|
29
|
-
consola.start('Installing dependencies...');
|
|
30
|
-
await run('npm', ['install', 'express', 'cookie-parser', 'better-sqlite3']);
|
|
31
|
-
|
|
32
|
-
consola.start('Installing @riavzon/bot-detector...');
|
|
33
|
-
await run('npm', ['install', '@riavzon/bot-detector']);
|
|
34
|
-
|
|
35
|
-
consola.start('Fetching data sources...');
|
|
36
|
-
await run('npx', ['@riavzon/bot-detector', 'init']);
|
|
37
|
-
|
|
38
|
-
consola.start('Writing botDetectorConfig.ts...');
|
|
39
|
-
await fs.writeFile(output, content, 'utf-8');
|
|
40
|
-
await fs.writeFile(path.resolve(process.cwd(), 'mainBotDetector.ts'), mainContent, 'utf-8');
|
|
41
|
-
consola.success('botDetectorConfig.ts created');
|
|
42
|
-
|
|
43
|
-
consola.start('Creating database tables...');
|
|
44
|
-
const pkgMain = path.resolve(process.cwd(), 'node_modules/@riavzon/bot-detector/dist/main.mjs');
|
|
45
|
-
const { defineConfiguration, createTables, getDb } = await import(pkgMain);
|
|
46
|
-
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
48
|
-
await defineConfiguration({ store: defaultStore });
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
50
|
-
await createTables(getDb());
|
|
51
|
-
|
|
52
|
-
consola.success('Setup complete. Import botDetectorConfig.ts at the top of your app entry point and mount the middleware.');
|
|
53
|
-
consola.log('');
|
|
54
|
-
consola.log('Keep data sources fresh (run daily or via cron):');
|
|
55
|
-
consola.log(' npx @riavzon/bot-detector refresh');
|
|
56
|
-
process.exit(0);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
await runMain(start);
|
package/src/default.ts
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
export const defaultStore = { main: { driver: 'sqlite' as const, name: './bot_detector.sqlite' } };
|
|
2
|
-
|
|
3
|
-
export const mainContent = `import './botDetectorConfig.js';
|
|
4
|
-
import express from 'express';
|
|
5
|
-
import cookieParser from 'cookie-parser';
|
|
6
|
-
import { detectBots } from '@riavzon/bot-detector';
|
|
7
|
-
|
|
8
|
-
const app = express();
|
|
9
|
-
app.use(cookieParser());
|
|
10
|
-
app.use(detectBots());
|
|
11
|
-
|
|
12
|
-
app.get('/', (req, res) => {
|
|
13
|
-
res.json({ banned: req.botDetection?.banned });
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
app.listen(3000);
|
|
17
|
-
`;
|
|
18
|
-
|
|
19
|
-
export const content = `import { defineConfiguration } from '@riavzon/bot-detector';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Bot Detector configuration — all values shown are the defaults.
|
|
23
|
-
* Tune penalties, enable/disable checkers, and swap adapters as needed.
|
|
24
|
-
*
|
|
25
|
-
* Next steps:
|
|
26
|
-
* Import this file before mounting the middleware in your app entry point
|
|
27
|
-
*
|
|
28
|
-
* Keep data sources fresh:
|
|
29
|
-
* npx @riavzon/bot-detector refresh
|
|
30
|
-
*/
|
|
31
|
-
await defineConfiguration({
|
|
32
|
-
|
|
33
|
-
// ─── Database (SQLite default — swap for mysql-pool / postgresql in production)
|
|
34
|
-
store: {
|
|
35
|
-
main: {
|
|
36
|
-
driver: 'sqlite',
|
|
37
|
-
name: './bot_detector.sqlite',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
// ─── Cache (default: in-process memory — uncomment to use a different one)
|
|
42
|
-
// storage: { driver: 'lru', max: 500, ttl: 1000 * 60 * 60 * 2 },
|
|
43
|
-
// storage: { driver: 'redis', url: process.env.REDIS_URL ?? 'redis://localhost:6379' },
|
|
44
|
-
// storage: { driver: 'upstash', url: process.env.UPSTASH_URL, token: process.env.UPSTASH_TOKEN },
|
|
45
|
-
|
|
46
|
-
// ─── Core scoring ──────────────────────────────────────────────────────────
|
|
47
|
-
banScore: 100,
|
|
48
|
-
maxScore: 100,
|
|
49
|
-
restoredReputationPoints: 10,
|
|
50
|
-
setNewComputedScore: false,
|
|
51
|
-
|
|
52
|
-
// ─── Whitelist (IPv4, IPv6, or CIDR) ───────────────────────────────────────
|
|
53
|
-
whiteList: [],
|
|
54
|
-
|
|
55
|
-
// ─── Re-check interval for returning visitors ──────────────────────────────
|
|
56
|
-
checksTimeRateControl: {
|
|
57
|
-
checkEveryRequest: true,
|
|
58
|
-
checkEvery: 1000 * 60 * 5,
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
// ─── Async batch write queue ───────────────────────────────────────────────
|
|
62
|
-
batchQueue: {
|
|
63
|
-
flushIntervalMs: 5000,
|
|
64
|
-
maxBufferSize: 100,
|
|
65
|
-
maxRetries: 3,
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
// ─── Logging ───────────────────────────────────────────────────────────────
|
|
69
|
-
logLevel: 'info',
|
|
70
|
-
|
|
71
|
-
// ─── Firewall ban (requires sudo ufw) ──────────────────────────────────────
|
|
72
|
-
punishmentType: {
|
|
73
|
-
enableFireWallBan: false,
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
// ─── Custom MMDB generation from visitor history ───────────────────────────
|
|
77
|
-
generator: {
|
|
78
|
-
scoreThreshold: 70,
|
|
79
|
-
generateTypes: false,
|
|
80
|
-
deleteAfterBuild: false,
|
|
81
|
-
mmdbctlPath: 'mmdbctl',
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
// ─── HTTP header anomaly penalties ─────────────────────────────────────────
|
|
85
|
-
headerOptions: {
|
|
86
|
-
weightPerMustHeader: 20,
|
|
87
|
-
missingBrowserEngine: 30,
|
|
88
|
-
postManOrInsomiaHeaders: 50,
|
|
89
|
-
AJAXHeaderExists: 30,
|
|
90
|
-
connectionHeaderIsClose: 20,
|
|
91
|
-
originHeaderIsNULL: 10,
|
|
92
|
-
originHeaderMismatch: 30,
|
|
93
|
-
omittedAcceptHeader: 30,
|
|
94
|
-
clientHintsMissingForBlink: 30,
|
|
95
|
-
teHeaderUnexpectedForBlink: 10,
|
|
96
|
-
clientHintsUnexpectedForGecko: 30,
|
|
97
|
-
teHeaderMissingForGecko: 20,
|
|
98
|
-
aggressiveCacheControlOnGet: 15,
|
|
99
|
-
crossSiteRequestMissingReferer: 10,
|
|
100
|
-
inconsistentSecFetchMode: 20,
|
|
101
|
-
hostMismatchWeight: 40,
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
// ─── Path traversal detection ──────────────────────────────────────────────
|
|
105
|
-
pathTraveler: {
|
|
106
|
-
maxIterations: 3,
|
|
107
|
-
maxPathLength: 1500,
|
|
108
|
-
pathLengthToLong: 100,
|
|
109
|
-
longDecoding: 100,
|
|
110
|
-
traversalDetected: 60,
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
// ─── Checkers (set enable: false to disable any individual checker) ─────────
|
|
114
|
-
checkers: {
|
|
115
|
-
|
|
116
|
-
localeMapsCheck: {
|
|
117
|
-
enable: true,
|
|
118
|
-
penalties: {
|
|
119
|
-
ipAndHeaderMismatch: 20,
|
|
120
|
-
missingHeader: 20,
|
|
121
|
-
missingGeoData: 20,
|
|
122
|
-
malformedHeader: 30,
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
knownBadUserAgents: {
|
|
127
|
-
enable: true,
|
|
128
|
-
penalties: {
|
|
129
|
-
criticalSeverity: 100,
|
|
130
|
-
highSeverity: 80,
|
|
131
|
-
mediumSeverity: 30,
|
|
132
|
-
lowSeverity: 10,
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
enableIpChecks: {
|
|
137
|
-
enable: true,
|
|
138
|
-
penalties: 10,
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
enableGoodBotsChecks: {
|
|
142
|
-
enable: true,
|
|
143
|
-
banUnlistedBots: true,
|
|
144
|
-
penalties: 100,
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
enableBehaviorRateCheck: {
|
|
148
|
-
enable: true,
|
|
149
|
-
behavioral_window: 60_000,
|
|
150
|
-
behavioral_threshold: 30,
|
|
151
|
-
penalties: 60,
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
enableProxyIspCookiesChecks: {
|
|
155
|
-
enable: true,
|
|
156
|
-
penalties: {
|
|
157
|
-
cookieMissing: 80,
|
|
158
|
-
proxyDetected: 40,
|
|
159
|
-
multiSourceBonus2to3: 10,
|
|
160
|
-
multiSourceBonus4plus: 20,
|
|
161
|
-
hostingDetected: 50,
|
|
162
|
-
ispUnknown: 10,
|
|
163
|
-
orgUnknown: 10,
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
enableUaAndHeaderChecks: {
|
|
168
|
-
enable: true,
|
|
169
|
-
penalties: {
|
|
170
|
-
headlessBrowser: 100,
|
|
171
|
-
shortUserAgent: 80,
|
|
172
|
-
tlsCheckFailed: 60,
|
|
173
|
-
badUaChecker: true,
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
enableBrowserAndDeviceChecks: {
|
|
178
|
-
enable: true,
|
|
179
|
-
penalties: {
|
|
180
|
-
cliOrLibrary: 100,
|
|
181
|
-
internetExplorer: 100,
|
|
182
|
-
linuxOs: 10,
|
|
183
|
-
impossibleBrowserCombinations: 30,
|
|
184
|
-
browserTypeUnknown: 10,
|
|
185
|
-
browserNameUnknown: 10,
|
|
186
|
-
desktopWithoutOS: 10,
|
|
187
|
-
deviceVendorUnknown: 10,
|
|
188
|
-
browserVersionUnknown: 10,
|
|
189
|
-
deviceModelUnknown: 5,
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
|
|
193
|
-
enableGeoChecks: {
|
|
194
|
-
enable: true,
|
|
195
|
-
bannedCountries: [],
|
|
196
|
-
penalties: {
|
|
197
|
-
countryUnknown: 10,
|
|
198
|
-
regionUnknown: 10,
|
|
199
|
-
latLonUnknown: 10,
|
|
200
|
-
districtUnknown: 10,
|
|
201
|
-
cityUnknown: 10,
|
|
202
|
-
timezoneUnknown: 10,
|
|
203
|
-
subregionUnknown: 10,
|
|
204
|
-
phoneUnknown: 10,
|
|
205
|
-
continentUnknown: 10,
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
enableKnownThreatsDetections: {
|
|
210
|
-
enable: true,
|
|
211
|
-
penalties: {
|
|
212
|
-
anonymiseNetwork: 20,
|
|
213
|
-
threatLevels: {
|
|
214
|
-
criticalLevel1: 40,
|
|
215
|
-
currentAttacksLevel2: 30,
|
|
216
|
-
threatLevel3: 20,
|
|
217
|
-
threatLevel4: 10,
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
enableAsnClassification: {
|
|
223
|
-
enable: true,
|
|
224
|
-
penalties: {
|
|
225
|
-
contentClassification: 20,
|
|
226
|
-
unknownClassification: 10,
|
|
227
|
-
lowVisibilityPenalty: 10,
|
|
228
|
-
lowVisibilityThreshold: 15,
|
|
229
|
-
comboHostingLowVisibility: 20,
|
|
230
|
-
},
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
enableTorAnalysis: {
|
|
234
|
-
enable: true,
|
|
235
|
-
penalties: {
|
|
236
|
-
runningNode: 15,
|
|
237
|
-
exitNode: 20,
|
|
238
|
-
webExitCapable: 15,
|
|
239
|
-
guardNode: 10,
|
|
240
|
-
badExit: 40,
|
|
241
|
-
obsoleteVersion: 10,
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
enableTimezoneConsistency: {
|
|
246
|
-
enable: true,
|
|
247
|
-
penalties: 20,
|
|
248
|
-
},
|
|
249
|
-
|
|
250
|
-
honeypot: {
|
|
251
|
-
enable: true,
|
|
252
|
-
paths: ['/.env', '/wp-admin', '/wp-login.php', '/.git/config', '/phpinfo.php'],
|
|
253
|
-
},
|
|
254
|
-
|
|
255
|
-
enableSessionCoherence: {
|
|
256
|
-
enable: true,
|
|
257
|
-
penalties: {
|
|
258
|
-
pathMismatch: 10,
|
|
259
|
-
missingReferer: 20,
|
|
260
|
-
domainMismatch: 30,
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
|
|
264
|
-
enableVelocityFingerprint: {
|
|
265
|
-
enable: true,
|
|
266
|
-
cvThreshold: 0.1,
|
|
267
|
-
penalties: 40,
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
enableKnownBadIpsCheck: {
|
|
271
|
-
enable: true,
|
|
272
|
-
highRiskPenalty: 30,
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
`;
|
package/tsconfig.json
DELETED