bot-shield 1.0.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/README.md +53 -0
- package/index.js +94 -0
- package/package.json +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# BotShield Middleware
|
|
2
|
+
|
|
3
|
+
An Economic Deterrence Bot Mitigation Middleware for Express/Node.js based on V8 Javascript cryptographic token challenges.
|
|
4
|
+
|
|
5
|
+
This package protects your valuable API endpoints by filtering out automated scrapers and bots trying to steal data, while allowing legitimate human browsers to seamlessly access the content.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install bot-shield-mca
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const express = require('express');
|
|
17
|
+
const BotShield = require('bot-shield-mca');
|
|
18
|
+
|
|
19
|
+
const app = express();
|
|
20
|
+
const botShield = new BotShield({
|
|
21
|
+
riskThreshold: 70, // Blocking threshold (default 70)
|
|
22
|
+
maxRequestsPerWindow: 50, // Rate limiting volume
|
|
23
|
+
minTimeBetweenRequestsMs: 200 // Velocity tracking
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// 1. Expose the challenge token endpoint
|
|
27
|
+
app.get('/api/bot-challenge', botShield.challengeEndpoint);
|
|
28
|
+
|
|
29
|
+
// 2. Protect your valuable data API with the middleware
|
|
30
|
+
app.get('/api/data', botShield.protectApi, (req, res) => {
|
|
31
|
+
res.json({ message: "Protected data payload!" });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
app.listen(3000);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Frontend Integration (The X-BOT-SIGNAL)
|
|
38
|
+
|
|
39
|
+
Legitimate browsers must solve the execution challenge to retrieve the token and present it in the headers (`X-shield-token`) to access the protected JSON payload.
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
// Step 1: Challenge
|
|
43
|
+
const challenge = await fetch('http://localhost:3000/api/bot-challenge');
|
|
44
|
+
const { token } = await challenge.json();
|
|
45
|
+
|
|
46
|
+
// Step 2: Retrieve protected data
|
|
47
|
+
const response = await fetch('http://localhost:3000/api/data', {
|
|
48
|
+
headers: {
|
|
49
|
+
'x-shield-token': token
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
```
|
package/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
|
|
3
|
+
class BotShield {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.riskThreshold = options.riskThreshold || 70;
|
|
6
|
+
this.timeWindowMs = options.timeWindowMs || 60000;
|
|
7
|
+
this.maxRequestsPerWindow = options.maxRequestsPerWindow || 50;
|
|
8
|
+
this.minTimeBetweenRequestsMs = options.minTimeBetweenRequestsMs || 200;
|
|
9
|
+
|
|
10
|
+
this.clients = new Map();
|
|
11
|
+
this.validTokens = new Set();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
challengeEndpoint = (req, res) => {
|
|
15
|
+
const token = crypto.randomBytes(16).toString('hex');
|
|
16
|
+
this.validTokens.add(token);
|
|
17
|
+
setTimeout(() => this.validTokens.delete(token), 5 * 60 * 1000);
|
|
18
|
+
res.json({ token });
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
_getClientData(ip) {
|
|
22
|
+
if (!this.clients.has(ip)) {
|
|
23
|
+
this.clients.set(ip, {
|
|
24
|
+
requestCount: 0,
|
|
25
|
+
lastRequestTime: Date.now(),
|
|
26
|
+
firstRequestTime: Date.now()
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return this.clients.get(ip);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_calculateRiskScore(clientData, hasValidToken, timeSinceLastRequest) {
|
|
33
|
+
let score = 0;
|
|
34
|
+
const signals = {};
|
|
35
|
+
|
|
36
|
+
if (!hasValidToken) {
|
|
37
|
+
score += 75;
|
|
38
|
+
signals.jsExecuted = false;
|
|
39
|
+
} else {
|
|
40
|
+
signals.jsExecuted = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (timeSinceLastRequest < this.minTimeBetweenRequestsMs) {
|
|
44
|
+
score += 30;
|
|
45
|
+
signals.suspiciousTiming = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (clientData.requestCount > this.maxRequestsPerWindow) {
|
|
49
|
+
score += 40;
|
|
50
|
+
signals.highVolume = true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { score, signals };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protectApi = (req, res, next) => {
|
|
57
|
+
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
|
58
|
+
const clientToken = req.headers['x-shield-token'];
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
|
|
61
|
+
const clientData = this._getClientData(ip);
|
|
62
|
+
const timeSinceLastRequest = now - clientData.lastRequestTime;
|
|
63
|
+
const hasValidToken = this.validTokens.has(clientToken);
|
|
64
|
+
|
|
65
|
+
if (now - clientData.firstRequestTime > this.timeWindowMs) {
|
|
66
|
+
clientData.requestCount = 0;
|
|
67
|
+
clientData.firstRequestTime = now;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
clientData.requestCount += 1;
|
|
71
|
+
clientData.lastRequestTime = now;
|
|
72
|
+
|
|
73
|
+
const { score, signals } = this._calculateRiskScore(clientData, hasValidToken, timeSinceLastRequest);
|
|
74
|
+
|
|
75
|
+
if (score >= this.riskThreshold) {
|
|
76
|
+
console.log("\n" + "X".repeat(60));
|
|
77
|
+
console.log("🚨 [THREAT INTERCEPTED] 🚨");
|
|
78
|
+
console.log(`[!] Target: ${req.originalUrl} | IP: ${ip} | Risk Score: ${score}/100`);
|
|
79
|
+
console.log(`[!] Primary Reason: X-BOT-SIGNAL Missing`);
|
|
80
|
+
console.log("X".repeat(60));
|
|
81
|
+
|
|
82
|
+
return res.status(403).json({
|
|
83
|
+
error: "Access Denied",
|
|
84
|
+
code: "SHIELD_ERR",
|
|
85
|
+
message: "Verification Required. Unverified client behavior detected."
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.clients.set(ip, clientData);
|
|
90
|
+
next();
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = BotShield;
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bot-shield",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "An Economic Deterrence Bot Mitigation Middleware for Express",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"bot-protection",
|
|
11
|
+
"middleware",
|
|
12
|
+
"express",
|
|
13
|
+
"security",
|
|
14
|
+
"bot-shield",
|
|
15
|
+
"rate-limiting",
|
|
16
|
+
"economic-deterrence"
|
|
17
|
+
],
|
|
18
|
+
"author": "Your Name",
|
|
19
|
+
"license": "ISC"
|
|
20
|
+
}
|