@liberstudio/cloudflare-list 2.3.6 → 2.3.9
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
CHANGED
|
@@ -76,6 +76,7 @@ import { CloudflareAttacksModule } from "@liberstudio/cloudflare-list";
|
|
|
76
76
|
excludedPaths: ["/api/health", "/api/webhook"],
|
|
77
77
|
silentPaths: ["/auth/me", "/auth/refresh"],
|
|
78
78
|
verbose: false,
|
|
79
|
+
whatsappNotify: { phone: "393331234567" },
|
|
79
80
|
}),
|
|
80
81
|
],
|
|
81
82
|
})
|
|
@@ -102,6 +103,9 @@ import { CloudflareAttacksModule } from "@liberstudio/cloudflare-list";
|
|
|
102
103
|
excludedPaths: ["/api/health", "/api/webhook", /^\/api\/public\/.*/],
|
|
103
104
|
silentPaths: ["/auth/me", "/auth/refresh"],
|
|
104
105
|
verbose: false,
|
|
106
|
+
whatsappNotify: {
|
|
107
|
+
phone: config.getOrThrow<string>("WA_NOTIFY_PHONE"),
|
|
108
|
+
},
|
|
105
109
|
}),
|
|
106
110
|
}),
|
|
107
111
|
],
|
|
@@ -124,6 +128,33 @@ export class AppModule {}
|
|
|
124
128
|
| `excludedPaths` | `(string \| RegExp)[]` | no | Path esclusi da ogni rilevamento e log |
|
|
125
129
|
| `silentPaths` | `(string \| RegExp)[]` | no | Path bloccati su Cloudflare ma senza log su file |
|
|
126
130
|
| `verbose` | `boolean` | no | Se `true`, il log include body, query, params e stack |
|
|
131
|
+
| `whatsappNotify` | `{ phone: string }` | no | Invia una notifica WhatsApp quando un IP viene bannato |
|
|
132
|
+
|
|
133
|
+
### `whatsappNotify` — notifiche ban su WhatsApp
|
|
134
|
+
|
|
135
|
+
Quando configurato, invia un messaggio WhatsApp ad un numero specifico ogni volta che un IP viene bloccato su Cloudflare. Richiede le variabili d'ambiente `WA_URL`, `WA_USER`, `WA_PASSWORD` e `CLOUDFLARE_WA_DEVICE_ID` già presenti nel progetto (lette automaticamente da `process.env`).
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
whatsappNotify: {
|
|
139
|
+
phone: "393331234567", // numero con prefisso internazionale, senza +
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Il messaggio inviato sarà:
|
|
144
|
+
```
|
|
145
|
+
🚨 IP bannato su Cloudflare
|
|
146
|
+
IP: 1.2.3.4
|
|
147
|
+
Subnet bloccata: 1.2.0.0/16
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Variabili d'ambiente richieste (lette automaticamente da `process.env`):
|
|
151
|
+
```env
|
|
152
|
+
WA_URL=https://messaggistica.liberdesign.eu
|
|
153
|
+
WA_USER=your-user
|
|
154
|
+
WA_PASSWORD=your-password
|
|
155
|
+
CLOUDFLARE_WA_DEVICE_ID=your-device-id
|
|
156
|
+
WA_NOTIFY_PHONE=393331234567
|
|
157
|
+
```
|
|
127
158
|
|
|
128
159
|
### `allowedIps` — whitelist server
|
|
129
160
|
|
|
@@ -8,6 +8,7 @@ export declare class AttacksService {
|
|
|
8
8
|
private readonly ASN_LOOKUP_URL;
|
|
9
9
|
constructor(httpService: HttpService, options: CloudflareAttacksOptions);
|
|
10
10
|
blockIp(rawIp: string): Promise<CloudflareResponse | null>;
|
|
11
|
+
private sendWhatsappNotification;
|
|
11
12
|
private lookupAsnRange;
|
|
12
13
|
updateIpList(cidr: string): Promise<CloudflareResponse>;
|
|
13
14
|
}
|
package/dist/attacks.service.js
CHANGED
|
@@ -41,13 +41,36 @@ let AttacksService = class AttacksService {
|
|
|
41
41
|
}
|
|
42
42
|
const asnRange = await this.lookupAsnRange(rawIp);
|
|
43
43
|
if (asnRange) {
|
|
44
|
-
this.logger.
|
|
45
|
-
|
|
44
|
+
this.logger.error(`ASN range trovato per ${rawIp}: ${asnRange} — blocco intera subnet`);
|
|
45
|
+
const result = await this.updateIpList(asnRange);
|
|
46
|
+
this.sendWhatsappNotification(rawIp, asnRange);
|
|
47
|
+
return result;
|
|
46
48
|
}
|
|
47
49
|
const cidr = (0, utils_1.normalizeIp)(rawIp);
|
|
48
50
|
if (!cidr)
|
|
49
51
|
throw new Error(`IP non valido: ${rawIp}`);
|
|
50
|
-
|
|
52
|
+
const result = await this.updateIpList(cidr);
|
|
53
|
+
this.sendWhatsappNotification(rawIp, cidr);
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
sendWhatsappNotification(rawIp, cidr) {
|
|
57
|
+
const wa = this.options.whatsappNotify;
|
|
58
|
+
if (!wa)
|
|
59
|
+
return;
|
|
60
|
+
const url = process.env["WA_URL"];
|
|
61
|
+
const user = process.env["WA_USER"];
|
|
62
|
+
const password = process.env["WA_PASSWORD"];
|
|
63
|
+
const deviceId = process.env["CLOUDFLARE_WA_DEVICE_ID"];
|
|
64
|
+
if (!url || !user || !password || !deviceId) {
|
|
65
|
+
this.logger.warn("Notifica WhatsApp saltata: WA_URL, WA_USER, WA_PASSWORD o CLOUDFLARE_WA_DEVICE_ID mancanti");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const auth = Buffer.from(`${user}:${password}`).toString("base64");
|
|
69
|
+
const message = `🚨 IP bannato su Cloudflare\nIP: ${rawIp}\nSubnet bloccata: ${cidr}`;
|
|
70
|
+
(0, rxjs_1.firstValueFrom)(this.httpService.post(`${url}/send/message`, { phone: wa.phone, message }, { headers: { Authorization: `Basic ${auth}`, "X-Device-Id": deviceId } })).catch((err) => {
|
|
71
|
+
const msg = err instanceof Error ? err.message : "Errore sconosciuto";
|
|
72
|
+
this.logger.warn(`Notifica WhatsApp fallita: ${msg}`);
|
|
73
|
+
});
|
|
51
74
|
}
|
|
52
75
|
async lookupAsnRange(ip) {
|
|
53
76
|
try {
|
|
@@ -61,7 +84,7 @@ let AttacksService = class AttacksService {
|
|
|
61
84
|
async updateIpList(cidr) {
|
|
62
85
|
const { accountId, listId, apiToken, comment } = this.options;
|
|
63
86
|
const url = `${this.API_URL}/${accountId}/rules/lists/${listId}/items`;
|
|
64
|
-
this.logger.
|
|
87
|
+
this.logger.error(`Aggiungo ${cidr} alla lista Cloudflare`);
|
|
65
88
|
const body = [{ ip: cidr, comment }];
|
|
66
89
|
try {
|
|
67
90
|
const response = await (0, rxjs_1.firstValueFrom)(this.httpService.post(url, body, {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export interface WhatsappNotifyOptions {
|
|
2
|
+
phone: string;
|
|
3
|
+
}
|
|
1
4
|
export interface CloudflareAttacksOptions {
|
|
2
5
|
apiToken: string;
|
|
3
6
|
accountId: string;
|
|
@@ -8,6 +11,7 @@ export interface CloudflareAttacksOptions {
|
|
|
8
11
|
excludedPaths?: (string | RegExp)[];
|
|
9
12
|
silentPaths?: (string | RegExp)[];
|
|
10
13
|
verbose?: boolean;
|
|
14
|
+
whatsappNotify?: WhatsappNotifyOptions;
|
|
11
15
|
}
|
|
12
16
|
export interface CloudflareAttacksAsyncOptions {
|
|
13
17
|
imports?: any[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liberstudio/cloudflare-list",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.9",
|
|
4
4
|
"description": "Modulo NestJS per gestione IP List Cloudflare",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"build": "npx tsc",
|
|
17
17
|
"prepublishOnly": "npm run build",
|
|
18
18
|
"version:bump": "npx tsx src/scripts/version-bump.ts",
|
|
19
|
-
"pub": "npm publish --access public"
|
|
19
|
+
"pub": "npm run build && npm publish --access public"
|
|
20
20
|
},
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"access": "public"
|