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.
Files changed (55) hide show
  1. package/README.md +191 -0
  2. package/aiwaf.sqlite +0 -0
  3. package/examples/sandbox/README.md +44 -2
  4. package/examples/sandbox/aiwaf-adonis-proxy/Dockerfile +16 -0
  5. package/examples/sandbox/aiwaf-adonis-proxy/package.json +13 -0
  6. package/examples/sandbox/aiwaf-adonis-proxy/server.js +71 -0
  7. package/examples/sandbox/aiwaf-fastify-proxy/Dockerfile +21 -0
  8. package/examples/sandbox/aiwaf-fastify-proxy/package.json +16 -0
  9. package/examples/sandbox/aiwaf-fastify-proxy/server.js +42 -0
  10. package/examples/sandbox/aiwaf-hapi-proxy/Dockerfile +16 -0
  11. package/examples/sandbox/aiwaf-hapi-proxy/package.json +15 -0
  12. package/examples/sandbox/aiwaf-hapi-proxy/server.js +55 -0
  13. package/examples/sandbox/aiwaf-koa-proxy/Dockerfile +16 -0
  14. package/examples/sandbox/aiwaf-koa-proxy/package.json +16 -0
  15. package/examples/sandbox/aiwaf-koa-proxy/server.js +41 -0
  16. package/examples/sandbox/aiwaf-nest-proxy/Dockerfile +17 -0
  17. package/examples/sandbox/aiwaf-nest-proxy/main.js +55 -0
  18. package/examples/sandbox/aiwaf-nest-proxy/package.json +20 -0
  19. package/examples/sandbox/aiwaf-next-proxy/Dockerfile +16 -0
  20. package/examples/sandbox/aiwaf-next-proxy/package.json +16 -0
  21. package/examples/sandbox/aiwaf-next-proxy/pages/index.js +3 -0
  22. package/examples/sandbox/aiwaf-next-proxy/server.js +65 -0
  23. package/examples/sandbox/attack-suite.js +301 -22
  24. package/examples/sandbox/compare-results-modes.js +141 -0
  25. package/examples/sandbox/compare-results.js +250 -12
  26. package/examples/sandbox/docker-compose.yml +115 -0
  27. package/examples/sandbox/run-and-compare.js +19 -78
  28. package/index.js +15 -2
  29. package/lib/adonisMiddleware.js +82 -0
  30. package/lib/anomalyDetector.js +18 -5
  31. package/lib/fastifyPlugin.js +49 -0
  32. package/lib/featureUtils.js +11 -1
  33. package/lib/hapiPlugin.js +92 -0
  34. package/lib/headerValidation.js +9 -0
  35. package/lib/koaMiddleware.js +68 -0
  36. package/lib/nestMiddleware.js +12 -0
  37. package/lib/nextMiddleware.js +78 -0
  38. package/lib/rateLimiter.js +3 -0
  39. package/lib/wafMiddleware.js +160 -12
  40. package/lib/wasmAdapter.js +187 -0
  41. package/package.json +19 -2
  42. package/test/adonis-middleware.test.js +129 -0
  43. package/test/fastify-plugin.test.js +106 -0
  44. package/test/hapi-plugin.test.js +115 -0
  45. package/test/jest.teardown.js +33 -0
  46. package/test/koa-middleware.test.js +104 -0
  47. package/test/nest-integration.test.js +92 -0
  48. package/test/nest-middleware.test.js +88 -0
  49. package/test/next-handler.test.js +174 -0
  50. package/test/perf-wasm.js +64 -0
  51. package/test/waf.test.js +30 -0
  52. package/test/wasm-adapter.test.js +59 -0
  53. package/test/wasm-retrain-behavior.test.js +87 -0
  54. package/test/wasm-waf-integration.test.js +65 -0
  55. 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 http://localhost:3001 http://localhost:3000
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,13 @@
1
+ {
2
+ "name": "aiwaf-adonis-proxy-sandbox",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "commonjs",
6
+ "scripts": {
7
+ "start": "node server.js"
8
+ },
9
+ "dependencies": {
10
+ "aiwaf-js": "file:../../..",
11
+ "http-proxy-middleware": "^3.0.0"
12
+ }
13
+ }
@@ -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"]