aiwaf-js 0.0.7 → 0.0.8
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 +191 -0
- package/aiwaf.sqlite +0 -0
- package/examples/sandbox/README.md +44 -2
- package/examples/sandbox/aiwaf-adonis-proxy/Dockerfile +16 -0
- package/examples/sandbox/aiwaf-adonis-proxy/package.json +13 -0
- package/examples/sandbox/aiwaf-adonis-proxy/server.js +71 -0
- package/examples/sandbox/aiwaf-fastify-proxy/Dockerfile +21 -0
- package/examples/sandbox/aiwaf-fastify-proxy/package.json +16 -0
- package/examples/sandbox/aiwaf-fastify-proxy/server.js +42 -0
- package/examples/sandbox/aiwaf-hapi-proxy/Dockerfile +16 -0
- package/examples/sandbox/aiwaf-hapi-proxy/package.json +15 -0
- package/examples/sandbox/aiwaf-hapi-proxy/server.js +55 -0
- package/examples/sandbox/aiwaf-koa-proxy/Dockerfile +16 -0
- package/examples/sandbox/aiwaf-koa-proxy/package.json +16 -0
- package/examples/sandbox/aiwaf-koa-proxy/server.js +41 -0
- package/examples/sandbox/aiwaf-nest-proxy/Dockerfile +17 -0
- package/examples/sandbox/aiwaf-nest-proxy/main.js +55 -0
- package/examples/sandbox/aiwaf-nest-proxy/package.json +20 -0
- package/examples/sandbox/aiwaf-next-proxy/Dockerfile +16 -0
- package/examples/sandbox/aiwaf-next-proxy/package.json +16 -0
- package/examples/sandbox/aiwaf-next-proxy/pages/index.js +3 -0
- package/examples/sandbox/aiwaf-next-proxy/server.js +65 -0
- package/examples/sandbox/attack-suite.js +301 -22
- package/examples/sandbox/compare-results-modes.js +141 -0
- package/examples/sandbox/compare-results.js +250 -12
- package/examples/sandbox/docker-compose.yml +115 -0
- package/examples/sandbox/run-and-compare.js +19 -78
- package/index.js +15 -2
- package/lib/adonisMiddleware.js +82 -0
- package/lib/anomalyDetector.js +18 -5
- package/lib/fastifyPlugin.js +49 -0
- package/lib/featureUtils.js +11 -1
- package/lib/hapiPlugin.js +92 -0
- package/lib/headerValidation.js +9 -0
- package/lib/koaMiddleware.js +68 -0
- package/lib/nestMiddleware.js +12 -0
- package/lib/nextMiddleware.js +78 -0
- package/lib/rateLimiter.js +3 -0
- package/lib/wafMiddleware.js +160 -12
- package/lib/wasmAdapter.js +187 -0
- package/package.json +19 -2
- package/test/adonis-middleware.test.js +129 -0
- package/test/fastify-plugin.test.js +106 -0
- package/test/hapi-plugin.test.js +115 -0
- package/test/jest.teardown.js +33 -0
- package/test/koa-middleware.test.js +104 -0
- package/test/nest-integration.test.js +92 -0
- package/test/nest-middleware.test.js +88 -0
- package/test/next-handler.test.js +174 -0
- package/test/perf-wasm.js +64 -0
- package/test/waf.test.js +30 -0
- package/test/wasm-adapter.test.js +59 -0
- package/test/wasm-retrain-behavior.test.js +87 -0
- package/test/wasm-waf-integration.test.js +65 -0
- package/train.js +15 -2
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# aiwaf-js
|
|
2
2
|
|
|
3
3
|
AIWAF-JS is a Node.js/Express Web Application Firewall that combines deterministic protections with anomaly detection and continuous learning. It ships as middleware, a CLI for ops workflows, and an offline trainer for IsolationForest models.
|
|
4
|
+
Supported frameworks: Express (native), Fastify, Hapi, Koa, NestJS (Express/Fastify wrappers), Next.js (API route wrapper), and AdonisJS.
|
|
4
5
|
|
|
5
6
|
## What It Does
|
|
6
7
|
|
|
@@ -62,6 +63,15 @@ AIWAF-JS is a Node.js/Express Web Application Firewall that combines determinist
|
|
|
62
63
|
npm install aiwaf-js
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
### Optional WASM Acceleration
|
|
67
|
+
|
|
68
|
+
AIWAF can use the `aiwaf-wasm` optional dependency for faster IsolationForest scoring and deterministic feature validation.
|
|
69
|
+
If the WASM module fails to load, it automatically falls back to the JS implementation.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm install aiwaf-wasm
|
|
73
|
+
```
|
|
74
|
+
|
|
65
75
|
## Quick Start
|
|
66
76
|
|
|
67
77
|
```js
|
|
@@ -88,6 +98,184 @@ app.get('/', (req, res) => res.send('Protected'));
|
|
|
88
98
|
app.listen(3000);
|
|
89
99
|
```
|
|
90
100
|
|
|
101
|
+
## Fastify Usage
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
const fastify = require('fastify')({ logger: true });
|
|
105
|
+
const aiwaf = require('aiwaf-js');
|
|
106
|
+
|
|
107
|
+
fastify.register(aiwaf.fastify, {
|
|
108
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
109
|
+
dynamicTopN: 10,
|
|
110
|
+
WINDOW_SEC: 10,
|
|
111
|
+
MAX_REQ: 20,
|
|
112
|
+
FLOOD_REQ: 40,
|
|
113
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
fastify.get('/', async () => 'Protected');
|
|
117
|
+
fastify.listen({ port: 3000 });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Hapi Usage
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
const Hapi = require('@hapi/hapi');
|
|
124
|
+
const aiwaf = require('aiwaf-js');
|
|
125
|
+
|
|
126
|
+
const server = Hapi.server({ port: 3000 });
|
|
127
|
+
await server.register({
|
|
128
|
+
plugin: aiwaf.hapi,
|
|
129
|
+
options: {
|
|
130
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
131
|
+
dynamicTopN: 10,
|
|
132
|
+
WINDOW_SEC: 10,
|
|
133
|
+
MAX_REQ: 20,
|
|
134
|
+
FLOOD_REQ: 40,
|
|
135
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
server.route({ method: 'GET', path: '/', handler: () => 'Protected' });
|
|
140
|
+
await server.start();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Koa Usage
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
const Koa = require('koa');
|
|
147
|
+
const bodyParser = require('koa-bodyparser');
|
|
148
|
+
const aiwaf = require('aiwaf-js');
|
|
149
|
+
|
|
150
|
+
const app = new Koa();
|
|
151
|
+
app.use(bodyParser());
|
|
152
|
+
|
|
153
|
+
app.use(aiwaf.koa({
|
|
154
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
155
|
+
dynamicTopN: 10,
|
|
156
|
+
WINDOW_SEC: 10,
|
|
157
|
+
MAX_REQ: 20,
|
|
158
|
+
FLOOD_REQ: 40,
|
|
159
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
160
|
+
}));
|
|
161
|
+
|
|
162
|
+
app.use(ctx => {
|
|
163
|
+
ctx.body = 'Protected';
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
app.listen(3000);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## NestJS (Express) Usage
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
173
|
+
import aiwaf from 'aiwaf-js';
|
|
174
|
+
|
|
175
|
+
@Module({})
|
|
176
|
+
export class AppModule implements NestModule {
|
|
177
|
+
configure(consumer: MiddlewareConsumer) {
|
|
178
|
+
consumer
|
|
179
|
+
.apply(aiwaf.nest({
|
|
180
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
181
|
+
dynamicTopN: 10,
|
|
182
|
+
WINDOW_SEC: 10,
|
|
183
|
+
MAX_REQ: 20,
|
|
184
|
+
FLOOD_REQ: 40,
|
|
185
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
186
|
+
}))
|
|
187
|
+
.forRoutes('*');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
If you need to guarantee ordering before other middleware/proxies, you can also attach the Express middleware directly in `main.ts`:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import { NestFactory } from '@nestjs/core';
|
|
196
|
+
import aiwaf from 'aiwaf-js';
|
|
197
|
+
import { AppModule } from './app.module';
|
|
198
|
+
|
|
199
|
+
async function bootstrap() {
|
|
200
|
+
const app = await NestFactory.create(AppModule);
|
|
201
|
+
app.use(aiwaf({
|
|
202
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
203
|
+
dynamicTopN: 10,
|
|
204
|
+
WINDOW_SEC: 10,
|
|
205
|
+
MAX_REQ: 20,
|
|
206
|
+
FLOOD_REQ: 40,
|
|
207
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
208
|
+
}));
|
|
209
|
+
await app.listen(3000);
|
|
210
|
+
}
|
|
211
|
+
bootstrap();
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## NestJS (Fastify) Usage
|
|
215
|
+
|
|
216
|
+
Use the Fastify plugin when running Nest with `FastifyAdapter`:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { NestFactory } from '@nestjs/core';
|
|
220
|
+
import { FastifyAdapter } from '@nestjs/platform-fastify';
|
|
221
|
+
import aiwaf from 'aiwaf-js';
|
|
222
|
+
import { AppModule } from './app.module';
|
|
223
|
+
|
|
224
|
+
async function bootstrap() {
|
|
225
|
+
const app = await NestFactory.create(AppModule, new FastifyAdapter());
|
|
226
|
+
await app.register(aiwaf.fastify, {
|
|
227
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
228
|
+
dynamicTopN: 10,
|
|
229
|
+
WINDOW_SEC: 10,
|
|
230
|
+
MAX_REQ: 20,
|
|
231
|
+
FLOOD_REQ: 40,
|
|
232
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
233
|
+
});
|
|
234
|
+
await app.listen(3000, '0.0.0.0');
|
|
235
|
+
}
|
|
236
|
+
bootstrap();
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Next.js (API Routes) Usage
|
|
240
|
+
|
|
241
|
+
Use the `aiwaf.next` helper to wrap a Next.js API route handler.
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
import aiwaf from 'aiwaf-js';
|
|
245
|
+
|
|
246
|
+
function handler(req, res) {
|
|
247
|
+
res.status(200).json({ ok: true });
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export default aiwaf.next(handler, {
|
|
251
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
252
|
+
dynamicTopN: 10,
|
|
253
|
+
WINDOW_SEC: 10,
|
|
254
|
+
MAX_REQ: 20,
|
|
255
|
+
FLOOD_REQ: 40,
|
|
256
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## AdonisJS Usage
|
|
261
|
+
|
|
262
|
+
Register the middleware in your Adonis middleware stack:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import aiwaf from 'aiwaf-js';
|
|
266
|
+
|
|
267
|
+
export const middleware = [
|
|
268
|
+
() => aiwaf.adonis({
|
|
269
|
+
staticKeywords: ['.php', '.env', '.git'],
|
|
270
|
+
dynamicTopN: 10,
|
|
271
|
+
WINDOW_SEC: 10,
|
|
272
|
+
MAX_REQ: 20,
|
|
273
|
+
FLOOD_REQ: 40,
|
|
274
|
+
HONEYPOT_FIELD: 'hp_field'
|
|
275
|
+
})
|
|
276
|
+
];
|
|
277
|
+
```
|
|
278
|
+
|
|
91
279
|
## Configuration
|
|
92
280
|
|
|
93
281
|
### Core Controls
|
|
@@ -105,6 +293,8 @@ app.listen(3000);
|
|
|
105
293
|
| `cache` | fallback memory cache | Custom cache backend used by limiter/features |
|
|
106
294
|
| `nTrees` | `100` | IsolationForest trees when model is initialized in-process |
|
|
107
295
|
| `sampleSize` | `256` | IsolationForest sample size |
|
|
296
|
+
| `AIWAF_WASM_VALIDATION` | `true` | Enable WASM validation when available (headers, URL, content, recent) |
|
|
297
|
+
| `AIWAF_WASM_VALIDATE_RECENT` | `false` | Run WASM recent-behavior validation on recent request logs |
|
|
108
298
|
|
|
109
299
|
### Header Validation
|
|
110
300
|
|
|
@@ -318,6 +508,7 @@ node examples/sandbox/run-and-compare.js http://localhost:3001 http://localhost:
|
|
|
318
508
|
```
|
|
319
509
|
|
|
320
510
|
The comparison output includes per‑attack block rates and total blocked requests.
|
|
511
|
+
Fastify proxy is also available on `http://localhost:3002`.
|
|
321
512
|
|
|
322
513
|
## License
|
|
323
514
|
|
package/aiwaf.sqlite
CHANGED
|
Binary file
|
|
@@ -13,6 +13,12 @@ docker compose up --build
|
|
|
13
13
|
Then open:
|
|
14
14
|
|
|
15
15
|
- AIWAF-protected: `http://localhost:3000`
|
|
16
|
+
- AIWAF-protected (Fastify): `http://localhost:3002`
|
|
17
|
+
- AIWAF-protected (Hapi): `http://localhost:3003`
|
|
18
|
+
- AIWAF-protected (Koa): `http://localhost:3004`
|
|
19
|
+
- AIWAF-protected (NestJS): `http://localhost:3005`
|
|
20
|
+
- AIWAF-protected (Next.js): `http://localhost:3006`
|
|
21
|
+
- AIWAF-protected (AdonisJS): `http://localhost:3007`
|
|
16
22
|
- Direct Juice Shop: `http://localhost:3001`
|
|
17
23
|
|
|
18
24
|
## Test
|
|
@@ -40,14 +46,50 @@ Run against AIWAF-protected Juice Shop:
|
|
|
40
46
|
node attack-suite.js http://localhost:3000 protected
|
|
41
47
|
```
|
|
42
48
|
|
|
49
|
+
Run against AIWAF-protected Juice Shop (Fastify):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
node attack-suite.js http://localhost:3002 protected_fastify
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Run against AIWAF-protected Juice Shop (Hapi):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
node attack-suite.js http://localhost:3003 protected_hapi
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Run against AIWAF-protected Juice Shop (Koa):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
node attack-suite.js http://localhost:3004 protected_koa
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Run against AIWAF-protected Juice Shop (NestJS):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
node attack-suite.js http://localhost:3005 protected_nest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Run against AIWAF-protected Juice Shop (Next.js):
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
node attack-suite.js http://localhost:3006 protected_next
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Run against AIWAF-protected Juice Shop (AdonisJS):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
node attack-suite.js http://localhost:3007 protected_adonis
|
|
83
|
+
```
|
|
84
|
+
|
|
43
85
|
Compare results:
|
|
44
86
|
|
|
45
87
|
```bash
|
|
46
|
-
node compare-results.js results_direct_*.json results_protected_*.json
|
|
88
|
+
node compare-results.js results_direct_*.json results_protected_*.json results_protected_fastify_*.json results_protected_hapi_*.json results_protected_koa_*.json results_protected_nest_*.json results_protected_next_*.json results_protected_adonis_*.json
|
|
47
89
|
```
|
|
48
90
|
|
|
49
91
|
Or run the full suite + comparison in one command:
|
|
50
92
|
|
|
51
93
|
```bash
|
|
52
|
-
node run-and-compare.js
|
|
94
|
+
node run-and-compare.js
|
|
53
95
|
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM node:20-bullseye
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
COPY . /workspace
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && apt-get install -y python3 make g++ \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
RUN npm_config_build_from_source=true npm install
|
|
10
|
+
|
|
11
|
+
WORKDIR /workspace/examples/sandbox/aiwaf-adonis-proxy
|
|
12
|
+
|
|
13
|
+
RUN npm_config_build_from_source=true npm install
|
|
14
|
+
|
|
15
|
+
EXPOSE 3007
|
|
16
|
+
CMD ["npm", "start"]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
2
|
+
const aiwaf = require('aiwaf-js');
|
|
3
|
+
|
|
4
|
+
const PORT = process.env.PORT || 3007;
|
|
5
|
+
const TARGET_BASE_URL = process.env.TARGET_BASE_URL || 'http://localhost:3001';
|
|
6
|
+
|
|
7
|
+
const proxy = createProxyMiddleware({
|
|
8
|
+
target: TARGET_BASE_URL,
|
|
9
|
+
changeOrigin: true,
|
|
10
|
+
ws: true,
|
|
11
|
+
logLevel: 'warn'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function createCtx(req, res) {
|
|
15
|
+
const response = {
|
|
16
|
+
response: res,
|
|
17
|
+
statusCode: res.statusCode || 200,
|
|
18
|
+
status(code) {
|
|
19
|
+
response.statusCode = code;
|
|
20
|
+
res.statusCode = code;
|
|
21
|
+
return response;
|
|
22
|
+
},
|
|
23
|
+
send(payload) {
|
|
24
|
+
res.end(payload);
|
|
25
|
+
return response;
|
|
26
|
+
},
|
|
27
|
+
json(payload) {
|
|
28
|
+
res.setHeader('content-type', 'application/json');
|
|
29
|
+
res.end(JSON.stringify(payload));
|
|
30
|
+
return response;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const request = {
|
|
35
|
+
request: req,
|
|
36
|
+
url: () => req.url,
|
|
37
|
+
headers: () => req.headers || {},
|
|
38
|
+
ip: () => (req.headers?.['x-forwarded-for'] || req.socket?.remoteAddress),
|
|
39
|
+
method: () => req.method
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return { request, response };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const middleware = aiwaf.adonis({
|
|
46
|
+
staticKeywords: ['.php', '.env', '.git', '../'],
|
|
47
|
+
dynamicTopN: 5,
|
|
48
|
+
WINDOW_SEC: 10,
|
|
49
|
+
MAX_REQ: 25,
|
|
50
|
+
FLOOD_REQ: 50,
|
|
51
|
+
HONEYPOT_FIELD: 'hp_field',
|
|
52
|
+
AIWAF_METHOD_POLICY_ENABLED: true,
|
|
53
|
+
AIWAF_ALLOWED_METHODS: ['GET', 'POST', 'HEAD', 'OPTIONS'],
|
|
54
|
+
AIWAF_HEADER_VALIDATION: true,
|
|
55
|
+
AIWAF_REQUIRED_HEADERS: [],
|
|
56
|
+
AIWAF_MIDDLEWARE_LOGGING: true,
|
|
57
|
+
AIWAF_MIDDLEWARE_LOG_PATH: process.env.AIWAF_MIDDLEWARE_LOG_PATH || 'logs/aiwaf-requests.jsonl'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
require('http')
|
|
61
|
+
.createServer(async (req, res) => {
|
|
62
|
+
console.log(`[sandbox-adonis] ${req.method} ${req.url}`);
|
|
63
|
+
const ctx = createCtx(req, res);
|
|
64
|
+
await middleware(ctx, () => new Promise(resolve => {
|
|
65
|
+
proxy(req, res, resolve);
|
|
66
|
+
}));
|
|
67
|
+
})
|
|
68
|
+
.listen(PORT, '0.0.0.0', () => {
|
|
69
|
+
console.log(`AIWAF Adonis sandbox proxy running on port ${PORT}`);
|
|
70
|
+
console.log(`Forwarding traffic to ${TARGET_BASE_URL}`);
|
|
71
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
FROM node:20-bullseye
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
|
|
5
|
+
COPY . /workspace
|
|
6
|
+
|
|
7
|
+
WORKDIR /workspace
|
|
8
|
+
|
|
9
|
+
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
|
|
10
|
+
|
|
11
|
+
ENV npm_config_build_from_source=sqlite3
|
|
12
|
+
|
|
13
|
+
RUN npm install
|
|
14
|
+
|
|
15
|
+
WORKDIR /workspace/examples/sandbox/aiwaf-fastify-proxy
|
|
16
|
+
|
|
17
|
+
RUN npm install
|
|
18
|
+
|
|
19
|
+
EXPOSE 3002
|
|
20
|
+
|
|
21
|
+
CMD ["npm", "start"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aiwaf-fastify-proxy-sandbox",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node server.js"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"aiwaf-js": "file:../../..",
|
|
12
|
+
"fastify": "^4.29.1",
|
|
13
|
+
"@fastify/middie": "^8.0.0",
|
|
14
|
+
"http-proxy-middleware": "^3.0.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const fastify = require('fastify')({ logger: true });
|
|
2
|
+
const aiwaf = require('aiwaf-js');
|
|
3
|
+
const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
4
|
+
|
|
5
|
+
const PORT = process.env.PORT || 3002;
|
|
6
|
+
const TARGET_BASE_URL = process.env.TARGET_BASE_URL || 'http://localhost:3001';
|
|
7
|
+
|
|
8
|
+
fastify.register(aiwaf.fastify, {
|
|
9
|
+
staticKeywords: ['.php', '.env', '.git', '../'],
|
|
10
|
+
dynamicTopN: 5,
|
|
11
|
+
WINDOW_SEC: 10,
|
|
12
|
+
MAX_REQ: 25,
|
|
13
|
+
FLOOD_REQ: 50,
|
|
14
|
+
HONEYPOT_FIELD: 'hp_field',
|
|
15
|
+
AIWAF_METHOD_POLICY_ENABLED: true,
|
|
16
|
+
AIWAF_ALLOWED_METHODS: ['GET', 'POST', 'HEAD', 'OPTIONS'],
|
|
17
|
+
AIWAF_HEADER_VALIDATION: true,
|
|
18
|
+
AIWAF_REQUIRED_HEADERS: [],
|
|
19
|
+
AIWAF_MIDDLEWARE_LOGGING: true,
|
|
20
|
+
AIWAF_MIDDLEWARE_LOG_PATH: process.env.AIWAF_MIDDLEWARE_LOG_PATH || 'logs/aiwaf-requests.jsonl'
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
fastify.addHook('onRequest', async (request, reply) => {
|
|
24
|
+
fastify.log.info(`[sandbox-fastify] ${request.method} ${request.url}`);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
fastify.register(require('@fastify/middie')).then(() => {
|
|
28
|
+
fastify.use(
|
|
29
|
+
'/',
|
|
30
|
+
createProxyMiddleware({
|
|
31
|
+
target: TARGET_BASE_URL,
|
|
32
|
+
changeOrigin: true,
|
|
33
|
+
ws: true,
|
|
34
|
+
logLevel: 'warn'
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
fastify.listen({ port: PORT, host: '0.0.0.0' }).then(() => {
|
|
40
|
+
fastify.log.info(`AIWAF Fastify sandbox proxy running on port ${PORT}`);
|
|
41
|
+
fastify.log.info(`Forwarding traffic to ${TARGET_BASE_URL}`);
|
|
42
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM node:20-bullseye
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
COPY . /workspace
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && apt-get install -y python3 make g++ \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
RUN npm_config_build_from_source=true npm install
|
|
10
|
+
|
|
11
|
+
WORKDIR /workspace/examples/sandbox/aiwaf-hapi-proxy
|
|
12
|
+
|
|
13
|
+
RUN npm_config_build_from_source=true npm install
|
|
14
|
+
|
|
15
|
+
EXPOSE 3003
|
|
16
|
+
CMD ["npm", "start"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aiwaf-hapi-proxy-sandbox",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node server.js"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"aiwaf-js": "file:../../..",
|
|
12
|
+
"@hapi/hapi": "^21.3.12",
|
|
13
|
+
"@hapi/h2o2": "^10.0.4"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const Hapi = require('@hapi/hapi');
|
|
2
|
+
const H2o2 = require('@hapi/h2o2');
|
|
3
|
+
const aiwaf = require('aiwaf-js');
|
|
4
|
+
|
|
5
|
+
const PORT = process.env.PORT || 3003;
|
|
6
|
+
const TARGET_BASE_URL = process.env.TARGET_BASE_URL || 'http://localhost:3001';
|
|
7
|
+
|
|
8
|
+
async function start() {
|
|
9
|
+
const server = Hapi.server({ port: PORT, host: '0.0.0.0' });
|
|
10
|
+
|
|
11
|
+
await server.register(H2o2);
|
|
12
|
+
await server.register({
|
|
13
|
+
plugin: aiwaf.hapi,
|
|
14
|
+
options: {
|
|
15
|
+
staticKeywords: ['.php', '.env', '.git', '../'],
|
|
16
|
+
dynamicTopN: 5,
|
|
17
|
+
WINDOW_SEC: 10,
|
|
18
|
+
MAX_REQ: 25,
|
|
19
|
+
FLOOD_REQ: 50,
|
|
20
|
+
HONEYPOT_FIELD: 'hp_field',
|
|
21
|
+
AIWAF_METHOD_POLICY_ENABLED: true,
|
|
22
|
+
AIWAF_ALLOWED_METHODS: ['GET', 'POST', 'HEAD', 'OPTIONS'],
|
|
23
|
+
AIWAF_HEADER_VALIDATION: true,
|
|
24
|
+
AIWAF_REQUIRED_HEADERS: [],
|
|
25
|
+
AIWAF_MIDDLEWARE_LOGGING: true,
|
|
26
|
+
AIWAF_MIDDLEWARE_LOG_PATH: process.env.AIWAF_MIDDLEWARE_LOG_PATH || 'logs/aiwaf-requests.jsonl'
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
server.ext('onRequest', (request, h) => {
|
|
31
|
+
console.log(`[sandbox-hapi] ${request.method.toUpperCase()} ${request.url.pathname}`);
|
|
32
|
+
return h.continue;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
server.route({
|
|
36
|
+
method: '*',
|
|
37
|
+
path: '/{path*}',
|
|
38
|
+
handler: {
|
|
39
|
+
proxy: {
|
|
40
|
+
uri: TARGET_BASE_URL,
|
|
41
|
+
passThrough: true,
|
|
42
|
+
xforward: true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
await server.start();
|
|
48
|
+
console.log(`AIWAF Hapi sandbox proxy running on port ${PORT}`);
|
|
49
|
+
console.log(`Forwarding traffic to ${TARGET_BASE_URL}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
start().catch(err => {
|
|
53
|
+
console.error(err);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM node:20-bullseye
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
COPY . /workspace
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && apt-get install -y python3 make g++ \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
RUN npm_config_build_from_source=true npm install
|
|
10
|
+
|
|
11
|
+
WORKDIR /workspace/examples/sandbox/aiwaf-koa-proxy
|
|
12
|
+
|
|
13
|
+
RUN npm_config_build_from_source=true npm install
|
|
14
|
+
|
|
15
|
+
EXPOSE 3004
|
|
16
|
+
CMD ["npm", "start"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aiwaf-koa-proxy-sandbox",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node server.js"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"aiwaf-js": "file:../../..",
|
|
12
|
+
"koa": "^2.15.4",
|
|
13
|
+
"koa-bodyparser": "^4.4.1",
|
|
14
|
+
"koa-proxies": "^0.12.4"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const Koa = require('koa');
|
|
2
|
+
const bodyParser = require('koa-bodyparser');
|
|
3
|
+
const proxy = require('koa-proxies');
|
|
4
|
+
const aiwaf = require('aiwaf-js');
|
|
5
|
+
|
|
6
|
+
const PORT = process.env.PORT || 3004;
|
|
7
|
+
const TARGET_BASE_URL = process.env.TARGET_BASE_URL || 'http://localhost:3001';
|
|
8
|
+
|
|
9
|
+
const app = new Koa();
|
|
10
|
+
|
|
11
|
+
app.use(bodyParser());
|
|
12
|
+
app.use((ctx, next) => {
|
|
13
|
+
console.log(`[sandbox-koa] ${ctx.method} ${ctx.url}`);
|
|
14
|
+
return next();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
app.use(aiwaf.koa({
|
|
18
|
+
staticKeywords: ['.php', '.env', '.git', '../'],
|
|
19
|
+
dynamicTopN: 5,
|
|
20
|
+
WINDOW_SEC: 10,
|
|
21
|
+
MAX_REQ: 25,
|
|
22
|
+
FLOOD_REQ: 50,
|
|
23
|
+
HONEYPOT_FIELD: 'hp_field',
|
|
24
|
+
AIWAF_METHOD_POLICY_ENABLED: true,
|
|
25
|
+
AIWAF_ALLOWED_METHODS: ['GET', 'POST', 'HEAD', 'OPTIONS'],
|
|
26
|
+
AIWAF_HEADER_VALIDATION: true,
|
|
27
|
+
AIWAF_REQUIRED_HEADERS: [],
|
|
28
|
+
AIWAF_MIDDLEWARE_LOGGING: true,
|
|
29
|
+
AIWAF_MIDDLEWARE_LOG_PATH: process.env.AIWAF_MIDDLEWARE_LOG_PATH || 'logs/aiwaf-requests.jsonl'
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
app.use(proxy('/', {
|
|
33
|
+
target: TARGET_BASE_URL,
|
|
34
|
+
changeOrigin: true,
|
|
35
|
+
logs: true
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
app.listen(PORT, () => {
|
|
39
|
+
console.log(`AIWAF Koa sandbox proxy running on port ${PORT}`);
|
|
40
|
+
console.log(`Forwarding traffic to ${TARGET_BASE_URL}`);
|
|
41
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
FROM node:20-bullseye
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
COPY . /workspace
|
|
5
|
+
|
|
6
|
+
RUN apt-get update && apt-get install -y python3 make g++ \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
RUN npm_config_build_from_source=true npm install
|
|
10
|
+
|
|
11
|
+
WORKDIR /workspace/examples/sandbox/aiwaf-nest-proxy
|
|
12
|
+
|
|
13
|
+
RUN npm_config_build_from_source=true npm install
|
|
14
|
+
RUN npm_config_build_from_source=true npm install http-proxy-middleware
|
|
15
|
+
|
|
16
|
+
EXPOSE 3005
|
|
17
|
+
CMD ["npm", "start"]
|