securenow 5.14.0 → 5.15.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/CONSUMING-APPS-GUIDE.md +20 -14
- package/NPM_README.md +368 -124
- package/README.md +23 -17
- package/SKILL-API.md +597 -0
- package/SKILL-CLI.md +395 -0
- package/cli.js +1 -1
- package/docs/FIREWALL-GUIDE.md +35 -12
- package/package.json +4 -2
package/NPM_README.md
CHANGED
|
@@ -3,15 +3,18 @@
|
|
|
3
3
|
OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt applications. Send distributed traces and logs to any OTLP-compatible observability backend.
|
|
4
4
|
|
|
5
5
|
**Features:**
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
6
|
+
- Zero-config automatic instrumentation
|
|
7
|
+
- Distributed tracing for all popular frameworks
|
|
8
|
+
- Automatic logging with console instrumentation
|
|
9
|
+
- Built-in sensitive data redaction
|
|
10
|
+
- Request body capture for debugging
|
|
11
|
+
- Multi-layer firewall -- auto-blocks IPs from your SecureNow blocklist
|
|
12
|
+
- `withSecureNow()` config wrapper for Next.js -- eliminates manual `serverExternalPackages`
|
|
13
|
+
- `securenow init` CLI scaffolds instrumentation files for any framework
|
|
14
|
+
- `securenow/firewall-only` entry point for firewall without tracing overhead
|
|
15
|
+
- Fully configurable via environment variables
|
|
16
|
+
- Single `-r securenow/register` flag -- works for both CJS and ESM apps
|
|
17
|
+
- Native Nuxt 3 module (`securenow/nuxt`)
|
|
15
18
|
|
|
16
19
|
---
|
|
17
20
|
|
|
@@ -19,7 +22,7 @@ OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt application
|
|
|
19
22
|
|
|
20
23
|
- [Installation](#installation)
|
|
21
24
|
- [Quick Start](#quick-start)
|
|
22
|
-
- [CLI
|
|
25
|
+
- [CLI -- Command Line Interface](#cli--command-line-interface)
|
|
23
26
|
- [Framework-Specific Setup](#framework-specific-setup)
|
|
24
27
|
- [Express.js](#expressjs)
|
|
25
28
|
- [Next.js](#nextjs)
|
|
@@ -28,7 +31,7 @@ OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt application
|
|
|
28
31
|
- [NestJS](#nestjs)
|
|
29
32
|
- [Koa](#koa)
|
|
30
33
|
- [Hapi](#hapi)
|
|
31
|
-
- [Firewall
|
|
34
|
+
- [Firewall -- Automatic IP Blocking](#firewall--automatic-ip-blocking)
|
|
32
35
|
- [Environment Variables Reference](#environment-variables-reference)
|
|
33
36
|
- [Logging Setup](#logging-setup)
|
|
34
37
|
- [Request Body Capture](#request-body-capture)
|
|
@@ -54,7 +57,23 @@ yarn add securenow
|
|
|
54
57
|
|
|
55
58
|
## Quick Start
|
|
56
59
|
|
|
57
|
-
### 1.
|
|
60
|
+
### 1. Automatic Setup (Recommended)
|
|
61
|
+
|
|
62
|
+
Run the init command after installing:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx securenow init --key snk_live_abc123...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This detects your framework and:
|
|
69
|
+
- **Next.js**: Creates `instrumentation.ts`, suggests `withSecureNow()` for `next.config.js`
|
|
70
|
+
- **Nuxt 3**: Suggests adding `securenow/nuxt` to modules
|
|
71
|
+
- **Express / Node.js**: Shows how to add `-r securenow/register` to your start script
|
|
72
|
+
- **All**: Writes `SECURENOW_API_KEY` to `.env.local` when `--key` is provided
|
|
73
|
+
|
|
74
|
+
### 2. Manual Setup
|
|
75
|
+
|
|
76
|
+
#### Set Environment Variables
|
|
58
77
|
|
|
59
78
|
```bash
|
|
60
79
|
# Required: Your application identifier
|
|
@@ -65,11 +84,14 @@ export SECURENOW_INSTANCE=http://your-otlp-collector:4318
|
|
|
65
84
|
|
|
66
85
|
# Optional: Enable logging
|
|
67
86
|
export SECURENOW_LOGGING_ENABLED=1
|
|
87
|
+
|
|
88
|
+
# Optional: Enable the firewall (set your API key)
|
|
89
|
+
export SECURENOW_API_KEY=snk_live_abc123...
|
|
68
90
|
```
|
|
69
91
|
|
|
70
|
-
|
|
92
|
+
#### Run Your Application
|
|
71
93
|
|
|
72
|
-
Add `-r securenow/register` to your start command
|
|
94
|
+
Add `-r securenow/register` to your start command -- that's the only change:
|
|
73
95
|
|
|
74
96
|
```bash
|
|
75
97
|
node -r securenow/register app.js
|
|
@@ -106,15 +128,16 @@ const app = express();
|
|
|
106
128
|
You'll see confirmation in the console:
|
|
107
129
|
|
|
108
130
|
```
|
|
109
|
-
[securenow] OTel SDK started
|
|
110
|
-
[securenow]
|
|
131
|
+
[securenow] OTel SDK started -> http://your-otlp-collector:4318/v1/traces
|
|
132
|
+
[securenow] Firewall: ENABLED
|
|
133
|
+
[securenow] Firewall: synced 142 blocked IPs (138 exact + 4 CIDR ranges)
|
|
111
134
|
```
|
|
112
135
|
|
|
113
136
|
---
|
|
114
137
|
|
|
115
|
-
## CLI
|
|
138
|
+
## CLI -- Command Line Interface
|
|
116
139
|
|
|
117
|
-
The `securenow` CLI gives you full access to the SecureNow platform from the terminal
|
|
140
|
+
The `securenow` CLI gives you full access to the SecureNow platform from the terminal -- no browser required for day-to-day workflows. Zero additional dependencies.
|
|
118
141
|
|
|
119
142
|
### Getting Started
|
|
120
143
|
|
|
@@ -129,6 +152,18 @@ npx securenow login --token <YOUR_JWT>
|
|
|
129
152
|
npx securenow whoami
|
|
130
153
|
```
|
|
131
154
|
|
|
155
|
+
### Project Setup
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Auto-detect framework and scaffold instrumentation files
|
|
159
|
+
npx securenow init
|
|
160
|
+
|
|
161
|
+
# Pass your API key to auto-write it to .env.local
|
|
162
|
+
npx securenow init --key snk_live_abc123...
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
For Next.js projects, `init` creates `instrumentation.ts` (or `.js` if no TypeScript) and tells you how to update `next.config.js` with `withSecureNow()`. For Nuxt, it suggests adding `securenow/nuxt` to your modules. For Express/Node, it shows the `-r securenow/register` flag.
|
|
166
|
+
|
|
132
167
|
### Managing Applications
|
|
133
168
|
|
|
134
169
|
```bash
|
|
@@ -213,7 +248,7 @@ npx securenow alerts history --limit 20
|
|
|
213
248
|
### IP Intelligence & Blocklist
|
|
214
249
|
|
|
215
250
|
```bash
|
|
216
|
-
# Look up any IP
|
|
251
|
+
# Look up any IP -- geo, abuse score, verdict, risk factors
|
|
217
252
|
npx securenow ip 203.0.113.42
|
|
218
253
|
|
|
219
254
|
# Show traces from a specific IP
|
|
@@ -233,7 +268,7 @@ npx securenow trusted remove <id>
|
|
|
233
268
|
|
|
234
269
|
### Forensic Queries
|
|
235
270
|
|
|
236
|
-
Ask questions in plain English
|
|
271
|
+
Ask questions in plain English -- the AI translates them to SQL and runs them against your data.
|
|
237
272
|
|
|
238
273
|
```bash
|
|
239
274
|
# Run a forensic query
|
|
@@ -296,14 +331,6 @@ Config files are stored in `~/.securenow/`:
|
|
|
296
331
|
| `config.json` | API URL, default app, output format |
|
|
297
332
|
| `credentials.json` | Auth token (file permissions: 0600) |
|
|
298
333
|
|
|
299
|
-
### Initialize Instrumentation
|
|
300
|
-
|
|
301
|
-
```bash
|
|
302
|
-
# Interactive setup — creates instrumentation files for Next.js
|
|
303
|
-
npx securenow init
|
|
304
|
-
npx securenow init --ts --src --force
|
|
305
|
-
```
|
|
306
|
-
|
|
307
334
|
### Global Flags
|
|
308
335
|
|
|
309
336
|
Every command supports these flags:
|
|
@@ -344,6 +371,7 @@ fi
|
|
|
344
371
|
|
|
345
372
|
| Category | Command | Description |
|
|
346
373
|
|----------|---------|-------------|
|
|
374
|
+
| **Setup** | `init` | Auto-scaffold instrumentation for your framework |
|
|
347
375
|
| **Auth** | `login` | Authenticate via browser or `--token` |
|
|
348
376
|
| | `logout` | Clear credentials |
|
|
349
377
|
| | `whoami` | Show session info |
|
|
@@ -389,7 +417,6 @@ fi
|
|
|
389
417
|
| | `config get` | Show config |
|
|
390
418
|
| | `config set <k> <v>` | Set config value |
|
|
391
419
|
| | `config path` | Config file paths |
|
|
392
|
-
| | `init` | Setup instrumentation |
|
|
393
420
|
| | `version` | Show version |
|
|
394
421
|
|
|
395
422
|
---
|
|
@@ -439,6 +466,7 @@ module.exports = {
|
|
|
439
466
|
env: {
|
|
440
467
|
SECURENOW_APPID: 'your-app-key',
|
|
441
468
|
SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
|
|
469
|
+
SECURENOW_API_KEY: 'snk_live_abc123...',
|
|
442
470
|
SECURENOW_LOGGING_ENABLED: '1',
|
|
443
471
|
SECURENOW_NO_UUID: '1',
|
|
444
472
|
SECURENOW_CAPTURE_BODY: '1',
|
|
@@ -447,6 +475,8 @@ module.exports = {
|
|
|
447
475
|
};
|
|
448
476
|
```
|
|
449
477
|
|
|
478
|
+
> **Important:** Always use `node_args: '-r securenow/register'` in PM2 configs. Without it, PM2 restarts won't load the SDK, and the firewall won't activate.
|
|
479
|
+
|
|
450
480
|
---
|
|
451
481
|
|
|
452
482
|
### Fastify
|
|
@@ -476,7 +506,7 @@ fastify.listen({ port: 3000 }, (err) => {
|
|
|
476
506
|
});
|
|
477
507
|
```
|
|
478
508
|
|
|
479
|
-
> **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify
|
|
509
|
+
> **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify -- the body capture hook conflicts with Fastify's internal stream handling.
|
|
480
510
|
|
|
481
511
|
---
|
|
482
512
|
|
|
@@ -519,7 +549,7 @@ app.listen(3000, () => console.log('Koa running on port 3000'));
|
|
|
519
549
|
npm install securenow @nestjs/core @nestjs/common reflect-metadata ts-node typescript
|
|
520
550
|
```
|
|
521
551
|
|
|
522
|
-
NestJS uses TypeScript
|
|
552
|
+
NestJS uses TypeScript -- securenow is loaded via `-r` flags instead of in-code `require()`:
|
|
523
553
|
|
|
524
554
|
```typescript
|
|
525
555
|
// app.ts
|
|
@@ -599,7 +629,7 @@ const init = async () => {
|
|
|
599
629
|
init().catch((err) => { console.error(err); process.exit(1); });
|
|
600
630
|
```
|
|
601
631
|
|
|
602
|
-
> **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi
|
|
632
|
+
> **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi -- the body capture hook consumes the request stream before Hapi's payload parser.
|
|
603
633
|
|
|
604
634
|
---
|
|
605
635
|
|
|
@@ -642,7 +672,7 @@ http.createServer(toNodeListener(app)).listen(3000, () => {
|
|
|
642
672
|
npm install securenow polka
|
|
643
673
|
```
|
|
644
674
|
|
|
645
|
-
Polka is minimalist
|
|
675
|
+
Polka is minimalist -- no built-in body parser:
|
|
646
676
|
|
|
647
677
|
```javascript
|
|
648
678
|
// app.js
|
|
@@ -719,7 +749,7 @@ http.createServer(handler).listen(3000, () => console.log('HTTP running on port
|
|
|
719
749
|
npm install securenow hono @hono/node-server
|
|
720
750
|
```
|
|
721
751
|
|
|
722
|
-
Hono uses ESM
|
|
752
|
+
Hono uses ESM -- preload via `-r` flag (the ESM hook is auto-registered on Node >=20.6):
|
|
723
753
|
|
|
724
754
|
```javascript
|
|
725
755
|
// app.mjs
|
|
@@ -753,7 +783,7 @@ node -r securenow/register app.mjs
|
|
|
753
783
|
npm install securenow @feathersjs/feathers @feathersjs/express @feathersjs/errors
|
|
754
784
|
```
|
|
755
785
|
|
|
756
|
-
Feathers uses Express transport
|
|
786
|
+
Feathers uses Express transport -- same setup as Express:
|
|
757
787
|
|
|
758
788
|
```javascript
|
|
759
789
|
// app.js
|
|
@@ -788,27 +818,101 @@ app.listen(3000, () => console.log('Feathers running on port 3000'));
|
|
|
788
818
|
|
|
789
819
|
### Next.js
|
|
790
820
|
|
|
791
|
-
See [Next.js Complete Guide
|
|
821
|
+
See [Next.js Complete Guide](./docs/NEXTJS-SETUP-COMPLETE.md) for the full reference.
|
|
822
|
+
|
|
823
|
+
#### Option A: `withSecureNow()` wrapper (v5.13.0+ -- Recommended)
|
|
824
|
+
|
|
825
|
+
One wrapper handles everything: `serverExternalPackages` (Next 15) or `experimental.serverComponentsExternalPackages` (Next 14), `instrumentationHook`, and webpack warning suppression.
|
|
826
|
+
|
|
827
|
+
**1. Update `next.config.js`:**
|
|
828
|
+
|
|
829
|
+
```javascript
|
|
830
|
+
const { withSecureNow } = require('securenow/nextjs-webpack-config');
|
|
831
|
+
|
|
832
|
+
module.exports = withSecureNow({
|
|
833
|
+
// your existing config -- reactStrictMode, images, rewrites, etc.
|
|
834
|
+
});
|
|
835
|
+
```
|
|
792
836
|
|
|
793
|
-
Create `instrumentation.ts`
|
|
837
|
+
**2. Create `instrumentation.ts` (or `.js`):**
|
|
794
838
|
|
|
795
839
|
```typescript
|
|
796
840
|
export async function register() {
|
|
797
841
|
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
798
|
-
|
|
842
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
843
|
+
registerSecureNow();
|
|
799
844
|
}
|
|
800
845
|
}
|
|
801
846
|
```
|
|
802
847
|
|
|
803
|
-
|
|
848
|
+
Or run `npx securenow init` to auto-generate this file.
|
|
849
|
+
|
|
850
|
+
**3. Set environment variables in `.env.local`:**
|
|
804
851
|
|
|
805
852
|
```env
|
|
806
853
|
SECURENOW_APPID=my-nextjs-app
|
|
807
854
|
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
855
|
+
SECURENOW_API_KEY=snk_live_abc123...
|
|
808
856
|
SECURENOW_LOGGING_ENABLED=1
|
|
809
857
|
SECURENOW_NO_UUID=1
|
|
810
858
|
```
|
|
811
859
|
|
|
860
|
+
That's it. `withSecureNow()` auto-detects your Next.js version and configures:
|
|
861
|
+
- **Next.js 15+**: Sets `serverExternalPackages` with all 13 required OTel packages
|
|
862
|
+
- **Next.js 14**: Sets `experimental.serverComponentsExternalPackages` and `experimental.instrumentationHook: true`
|
|
863
|
+
- **Both**: Suppresses webpack warnings from OpenTelemetry instrumentation packages
|
|
864
|
+
|
|
865
|
+
#### Option B: Manual configuration
|
|
866
|
+
|
|
867
|
+
If you prefer not to use the wrapper, manually add the packages:
|
|
868
|
+
|
|
869
|
+
```javascript
|
|
870
|
+
// next.config.js (Next.js 15+)
|
|
871
|
+
module.exports = {
|
|
872
|
+
serverExternalPackages: [
|
|
873
|
+
'securenow',
|
|
874
|
+
'@opentelemetry/sdk-node',
|
|
875
|
+
'@opentelemetry/auto-instrumentations-node',
|
|
876
|
+
'@opentelemetry/instrumentation-http',
|
|
877
|
+
'@opentelemetry/exporter-trace-otlp-http',
|
|
878
|
+
'@opentelemetry/exporter-logs-otlp-http',
|
|
879
|
+
'@opentelemetry/sdk-logs',
|
|
880
|
+
'@opentelemetry/instrumentation',
|
|
881
|
+
'@opentelemetry/resources',
|
|
882
|
+
'@opentelemetry/semantic-conventions',
|
|
883
|
+
'@opentelemetry/api',
|
|
884
|
+
'@opentelemetry/api-logs',
|
|
885
|
+
'@vercel/otel',
|
|
886
|
+
],
|
|
887
|
+
};
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
```javascript
|
|
891
|
+
// next.config.js (Next.js 14)
|
|
892
|
+
module.exports = {
|
|
893
|
+
experimental: {
|
|
894
|
+
instrumentationHook: true,
|
|
895
|
+
serverComponentsExternalPackages: [
|
|
896
|
+
'securenow',
|
|
897
|
+
'@opentelemetry/sdk-node',
|
|
898
|
+
'@opentelemetry/auto-instrumentations-node',
|
|
899
|
+
'@opentelemetry/instrumentation-http',
|
|
900
|
+
'@opentelemetry/exporter-trace-otlp-http',
|
|
901
|
+
'@opentelemetry/exporter-logs-otlp-http',
|
|
902
|
+
'@opentelemetry/sdk-logs',
|
|
903
|
+
'@opentelemetry/instrumentation',
|
|
904
|
+
'@opentelemetry/resources',
|
|
905
|
+
'@opentelemetry/semantic-conventions',
|
|
906
|
+
'@opentelemetry/api',
|
|
907
|
+
'@opentelemetry/api-logs',
|
|
908
|
+
'@vercel/otel',
|
|
909
|
+
],
|
|
910
|
+
},
|
|
911
|
+
};
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
**Why is this needed?** Next.js bundles server code with webpack, which breaks OpenTelemetry's dynamic `require()` calls and monkey-patching. Externalizing these packages keeps them as normal Node.js `require()` calls at runtime. The `withSecureNow()` wrapper handles this automatically.
|
|
915
|
+
|
|
812
916
|
---
|
|
813
917
|
|
|
814
918
|
### Nuxt 3
|
|
@@ -830,9 +934,10 @@ export default defineNuxtConfig({
|
|
|
830
934
|
```env
|
|
831
935
|
SECURENOW_APPID=my-nuxt-app
|
|
832
936
|
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
937
|
+
SECURENOW_API_KEY=snk_live_abc123...
|
|
833
938
|
```
|
|
834
939
|
|
|
835
|
-
That's it
|
|
940
|
+
That's it -- the Nuxt module handles OTel SDK initialization, Nitro externalization, firewall activation, and request tracing automatically. Optional config:
|
|
836
941
|
|
|
837
942
|
```typescript
|
|
838
943
|
export default defineNuxtConfig({
|
|
@@ -845,30 +950,32 @@ export default defineNuxtConfig({
|
|
|
845
950
|
});
|
|
846
951
|
```
|
|
847
952
|
|
|
953
|
+
The Nuxt server plugin (v5.13.0+) initializes the firewall independently from OpenTelemetry, so IP blocking works even if tracing encounters an error.
|
|
954
|
+
|
|
848
955
|
---
|
|
849
956
|
|
|
850
957
|
### Compatibility Matrix
|
|
851
958
|
|
|
852
|
-
| Framework | Traces | Logs | Body Capture | Notes |
|
|
853
|
-
|
|
854
|
-
| Express | Yes | Yes | Yes | Fully compatible |
|
|
855
|
-
| Fastify | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
|
|
856
|
-
| Koa | Yes | Yes | Yes | Needs `koa-bodyparser` |
|
|
857
|
-
| NestJS | Yes | Yes | Yes | Use `-r ts-node/register` |
|
|
858
|
-
| Hapi | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
|
|
859
|
-
| h3 | Yes | Yes | Yes | Uses `toNodeListener()` |
|
|
860
|
-
| Polka | Yes | Yes | Yes | Needs manual body parser |
|
|
861
|
-
| Micro/HTTP | Yes | Yes | Yes | Full control |
|
|
862
|
-
| Hono | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
|
|
863
|
-
| Feathers | Yes | Yes | Yes | Uses Express transport |
|
|
864
|
-
| Next.js | Yes | Yes | Yes | Use `instrumentation.ts` |
|
|
865
|
-
| Nuxt 3 | Yes | Yes | Yes | Use `securenow/nuxt` module |
|
|
959
|
+
| Framework | Traces | Logs | Body Capture | Firewall | Notes |
|
|
960
|
+
|-----------|--------|------|--------------|----------|-------|
|
|
961
|
+
| Express | Yes | Yes | Yes | Yes | Fully compatible |
|
|
962
|
+
| Fastify | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0` required |
|
|
963
|
+
| Koa | Yes | Yes | Yes | Yes | Needs `koa-bodyparser` |
|
|
964
|
+
| NestJS | Yes | Yes | Yes | Yes | Use `-r ts-node/register` |
|
|
965
|
+
| Hapi | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0` required |
|
|
966
|
+
| h3 | Yes | Yes | Yes | Yes | Uses `toNodeListener()` |
|
|
967
|
+
| Polka | Yes | Yes | Yes | Yes | Needs manual body parser |
|
|
968
|
+
| Micro/HTTP | Yes | Yes | Yes | Yes | Full control |
|
|
969
|
+
| Hono | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
|
|
970
|
+
| Feathers | Yes | Yes | Yes | Yes | Uses Express transport |
|
|
971
|
+
| Next.js | Yes | Yes | Yes | Yes | Use `instrumentation.ts` + `withSecureNow()` |
|
|
972
|
+
| Nuxt 3 | Yes | Yes | Yes | Yes | Use `securenow/nuxt` module |
|
|
866
973
|
|
|
867
974
|
---
|
|
868
975
|
|
|
869
|
-
## Firewall
|
|
976
|
+
## Firewall -- Automatic IP Blocking
|
|
870
977
|
|
|
871
|
-
SecureNow can automatically block IPs from your blocklist at the application layer. No code changes
|
|
978
|
+
SecureNow can automatically block IPs from your blocklist at the application layer. No code changes -- just set an API key and the firewall activates.
|
|
872
979
|
|
|
873
980
|
### Enable the Firewall
|
|
874
981
|
|
|
@@ -885,17 +992,70 @@ That's it. On startup, you'll see:
|
|
|
885
992
|
[securenow] Firewall: synced 142 blocked IPs (138 exact + 4 CIDR ranges)
|
|
886
993
|
```
|
|
887
994
|
|
|
995
|
+
### How It Works
|
|
996
|
+
|
|
997
|
+
The firewall uses a version-based sync protocol for efficiency:
|
|
998
|
+
|
|
999
|
+
1. **Version check** every 10 seconds (lightweight HEAD-like request with ETag)
|
|
1000
|
+
2. **Full blocklist sync** only when the version changes (or every 5 minutes as a safety net)
|
|
1001
|
+
3. **In-memory matching** with a pre-compiled set (exact IPs) and sorted CIDR list for sub-millisecond lookups
|
|
1002
|
+
4. **Exponential backoff** with jitter when the API is temporarily unreachable
|
|
1003
|
+
5. **Allowlist support** -- trusted IPs are never blocked, even if they appear on the blocklist
|
|
1004
|
+
6. **Localhost fallback** -- when the configured API URL is unreachable (ECONNREFUSED), the SDK automatically tries `http://localhost:4000` for co-located deployments
|
|
1005
|
+
|
|
1006
|
+
After you block an IP in the dashboard or CLI, it typically takes 10-15 seconds to propagate to all running instances.
|
|
1007
|
+
|
|
1008
|
+
### Firewall-Only Mode (No Tracing)
|
|
1009
|
+
|
|
1010
|
+
If you only need IP blocking without OpenTelemetry tracing overhead, use the standalone entry point:
|
|
1011
|
+
|
|
1012
|
+
```bash
|
|
1013
|
+
node -r securenow/firewall-only app.js
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
Or in `package.json`:
|
|
1017
|
+
|
|
1018
|
+
```json
|
|
1019
|
+
"scripts": {
|
|
1020
|
+
"start": "node -r securenow/firewall-only app.js"
|
|
1021
|
+
}
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
This is useful when:
|
|
1025
|
+
- You only need IP blocking, not observability
|
|
1026
|
+
- You want to minimize startup time and memory footprint
|
|
1027
|
+
- You're adding the firewall to a project that uses a different tracing solution
|
|
1028
|
+
- For Next.js, this avoids the need for `serverExternalPackages` entirely
|
|
1029
|
+
|
|
1030
|
+
Environment variables for firewall-only mode:
|
|
1031
|
+
|
|
1032
|
+
```bash
|
|
1033
|
+
SECURENOW_API_KEY=snk_live_abc123... # Required
|
|
1034
|
+
SECURENOW_API_URL=https://api.securenow.ai # Optional (auto-detected)
|
|
1035
|
+
SECURENOW_FIREWALL_ENABLED=1 # Default: 1
|
|
1036
|
+
SECURENOW_FIREWALL_TCP=1 # Optional: Layer 2
|
|
1037
|
+
SECURENOW_FIREWALL_IPTABLES=1 # Optional: Layer 3
|
|
1038
|
+
SECURENOW_FIREWALL_CLOUD=cloudflare # Optional: Layer 4
|
|
1039
|
+
```
|
|
1040
|
+
|
|
888
1041
|
### Blocking Layers
|
|
889
1042
|
|
|
890
|
-
The firewall supports four layers
|
|
1043
|
+
The firewall supports four layers -- Layer 1 is always on, the rest are opt-in:
|
|
891
1044
|
|
|
892
1045
|
| Layer | Env Var | Description |
|
|
893
1046
|
|-------|---------|-------------|
|
|
894
|
-
| **Layer 1: HTTP** | *(always on)* | Returns 403 Forbidden. Works with proxy headers. |
|
|
895
|
-
| **Layer 2: TCP** | `SECURENOW_FIREWALL_TCP=1` | `socket.destroy()`
|
|
1047
|
+
| **Layer 1: HTTP** | *(always on)* | Returns 403 Forbidden with a security alert page. Works with proxy headers. |
|
|
1048
|
+
| **Layer 2: TCP** | `SECURENOW_FIREWALL_TCP=1` | `socket.destroy()` -- zero bytes sent back |
|
|
896
1049
|
| **Layer 3: iptables** | `SECURENOW_FIREWALL_IPTABLES=1` | Kernel-level DROP (Linux, requires root) |
|
|
897
1050
|
| **Layer 4: Cloud WAF** | `SECURENOW_FIREWALL_CLOUD=cloudflare` | Pushes to Cloudflare, AWS WAF, or GCP Cloud Armor |
|
|
898
1051
|
|
|
1052
|
+
### Blocked Page
|
|
1053
|
+
|
|
1054
|
+
When an IP is blocked at Layer 1, the user sees a full-page security alert with:
|
|
1055
|
+
- Their detected IP address
|
|
1056
|
+
- A warning that malicious activity was detected
|
|
1057
|
+
- Contact information (`contact@securenow.ai`) for false positives
|
|
1058
|
+
|
|
899
1059
|
### Get an API Key
|
|
900
1060
|
|
|
901
1061
|
```bash
|
|
@@ -967,13 +1127,17 @@ See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
|
|
|
967
1127
|
| Variable | Description | Default |
|
|
968
1128
|
|----------|-------------|---------|
|
|
969
1129
|
| `SECURENOW_API_KEY` | API key with `firewall:read` scope. Enables the firewall when set. | - |
|
|
970
|
-
| `SECURENOW_API_URL` | SecureNow API base URL. | `https://api.securenow.ai` |
|
|
1130
|
+
| `SECURENOW_API_URL` | SecureNow API base URL. Auto-detected for co-located deployments (falls back to `http://localhost:4000` on ECONNREFUSED). | `https://api.securenow.ai` |
|
|
971
1131
|
| `SECURENOW_FIREWALL_ENABLED` | Master kill-switch. Set to `0` to disable. | `1` |
|
|
972
|
-
| `
|
|
1132
|
+
| `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between version checks (lightweight ETag-based). | `10` |
|
|
1133
|
+
| `SECURENOW_FIREWALL_SYNC_INTERVAL` | Full blocklist refresh interval in seconds (safety net). | `300` |
|
|
973
1134
|
| `SECURENOW_FIREWALL_FAIL_MODE` | `open` (allow when unavailable) or `closed` (block all). | `open` |
|
|
1135
|
+
| `SECURENOW_FIREWALL_STATUS_CODE` | HTTP status code for blocked requests. | `403` |
|
|
1136
|
+
| `SECURENOW_FIREWALL_LOG` | Log blocked requests and sync events to console. Set to `0` to silence. | `1` |
|
|
974
1137
|
| `SECURENOW_FIREWALL_TCP` | Enable Layer 2 TCP blocking. | `0` |
|
|
975
1138
|
| `SECURENOW_FIREWALL_IPTABLES` | Enable Layer 3 iptables blocking. | `0` |
|
|
976
1139
|
| `SECURENOW_FIREWALL_CLOUD` | Cloud WAF provider: `cloudflare`, `aws`, or `gcp`. | - |
|
|
1140
|
+
| `SECURENOW_FIREWALL_CLOUD_DRY_RUN` | Log cloud pushes without applying changes. | `0` |
|
|
977
1141
|
| `SECURENOW_TRUSTED_PROXIES` | Comma-separated trusted proxy IPs. | - |
|
|
978
1142
|
|
|
979
1143
|
See [Firewall Guide](./docs/FIREWALL-GUIDE.md) for complete details on all layers.
|
|
@@ -993,6 +1157,22 @@ See [Firewall Guide](./docs/FIREWALL-GUIDE.md) for complete details on all layer
|
|
|
993
1157
|
|
|
994
1158
|
---
|
|
995
1159
|
|
|
1160
|
+
## Entry Points Reference
|
|
1161
|
+
|
|
1162
|
+
SecureNow provides multiple entry points depending on your needs:
|
|
1163
|
+
|
|
1164
|
+
| Entry Point | Usage | Includes Tracing | Includes Firewall | Notes |
|
|
1165
|
+
|-------------|-------|-------------------|-------------------|-------|
|
|
1166
|
+
| `securenow/register` | `node -r securenow/register app.js` | Yes | Yes | Default -- full tracing + firewall |
|
|
1167
|
+
| `securenow/firewall-only` | `node -r securenow/firewall-only app.js` | No | Yes | Firewall only, no OTel overhead |
|
|
1168
|
+
| `securenow/nextjs` | `require('securenow/nextjs').registerSecureNow()` | Yes | Yes | Next.js instrumentation hook |
|
|
1169
|
+
| `securenow/nuxt` | `modules: ['securenow/nuxt']` | Yes | Yes | Nuxt 3 module |
|
|
1170
|
+
| `securenow/nextjs-webpack-config` | `withSecureNow(config)` | - | - | Next.js config wrapper |
|
|
1171
|
+
| `securenow/firewall` | `require('securenow/firewall').init({...})` | No | Yes | Programmatic firewall API |
|
|
1172
|
+
| `securenow/tracing` | `require('securenow/tracing')` | Yes | No | Programmatic tracing API |
|
|
1173
|
+
|
|
1174
|
+
---
|
|
1175
|
+
|
|
996
1176
|
## Logging Setup
|
|
997
1177
|
|
|
998
1178
|
### Automatic Console Logging
|
|
@@ -1012,11 +1192,11 @@ console.debug('Debug info');
|
|
|
1012
1192
|
```
|
|
1013
1193
|
|
|
1014
1194
|
**Severity mapping:**
|
|
1015
|
-
- `console.log()`
|
|
1016
|
-
- `console.info()`
|
|
1017
|
-
- `console.warn()`
|
|
1018
|
-
- `console.error()`
|
|
1019
|
-
- `console.debug()`
|
|
1195
|
+
- `console.log()` -> INFO
|
|
1196
|
+
- `console.info()` -> INFO
|
|
1197
|
+
- `console.warn()` -> WARN
|
|
1198
|
+
- `console.error()` -> ERROR
|
|
1199
|
+
- `console.debug()` -> DEBUG
|
|
1020
1200
|
|
|
1021
1201
|
**Environment variable:**
|
|
1022
1202
|
```bash
|
|
@@ -1086,11 +1266,11 @@ export SECURENOW_MAX_BODY_SIZE=10240 # 10KB (optional)
|
|
|
1086
1266
|
|
|
1087
1267
|
### Multipart Body Capture (v5.8.0+)
|
|
1088
1268
|
|
|
1089
|
-
Enable with `SECURENOW_CAPTURE_MULTIPART=1` to capture multipart/form-data requests. Uses a streaming parser that never buffers file content
|
|
1269
|
+
Enable with `SECURENOW_CAPTURE_MULTIPART=1` to capture multipart/form-data requests. Uses a streaming parser that never buffers file content -- memory stays at ~few KB regardless of upload size.
|
|
1090
1270
|
|
|
1091
1271
|
**What gets captured:**
|
|
1092
|
-
- **Text fields**
|
|
1093
|
-
- **File fields**
|
|
1272
|
+
- **Text fields** -- field name and value (up to 1000 chars), with sensitive fields auto-redacted
|
|
1273
|
+
- **File fields** -- metadata only: field name, filename, content-type, and size in bytes
|
|
1094
1274
|
|
|
1095
1275
|
**Example trace attribute:**
|
|
1096
1276
|
```json
|
|
@@ -1159,6 +1339,12 @@ export SECURENOW_CAPTURE_BODY=1
|
|
|
1159
1339
|
export SECURENOW_MAX_BODY_SIZE=20480
|
|
1160
1340
|
export SECURENOW_SENSITIVE_FIELDS="internal_id,session_key"
|
|
1161
1341
|
|
|
1342
|
+
# Firewall
|
|
1343
|
+
export SECURENOW_API_KEY=snk_live_abc123...
|
|
1344
|
+
export SECURENOW_FIREWALL_TCP=1
|
|
1345
|
+
export SECURENOW_FIREWALL_VERSION_INTERVAL=10
|
|
1346
|
+
export SECURENOW_FIREWALL_SYNC_INTERVAL=300
|
|
1347
|
+
|
|
1162
1348
|
# Environment
|
|
1163
1349
|
export NODE_ENV=production
|
|
1164
1350
|
|
|
@@ -1261,13 +1447,21 @@ const enabled: boolean = isLoggingEnabled();
|
|
|
1261
1447
|
// instrumentation.ts
|
|
1262
1448
|
export async function register() {
|
|
1263
1449
|
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
await import('securenow/register');
|
|
1450
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
1451
|
+
registerSecureNow();
|
|
1267
1452
|
}
|
|
1268
1453
|
}
|
|
1269
1454
|
```
|
|
1270
1455
|
|
|
1456
|
+
```javascript
|
|
1457
|
+
// next.config.js
|
|
1458
|
+
const { withSecureNow } = require('securenow/nextjs-webpack-config');
|
|
1459
|
+
|
|
1460
|
+
module.exports = withSecureNow({
|
|
1461
|
+
reactStrictMode: true,
|
|
1462
|
+
});
|
|
1463
|
+
```
|
|
1464
|
+
|
|
1271
1465
|
### NestJS with TypeScript
|
|
1272
1466
|
|
|
1273
1467
|
Use `-r securenow/register -r ts-node/register` flags instead of in-code require:
|
|
@@ -1316,7 +1510,7 @@ node app.js
|
|
|
1316
1510
|
|
|
1317
1511
|
Look for lines like:
|
|
1318
1512
|
```
|
|
1319
|
-
[securenow] OTel SDK started
|
|
1513
|
+
[securenow] OTel SDK started -> http://localhost:4318/v1/traces
|
|
1320
1514
|
```
|
|
1321
1515
|
|
|
1322
1516
|
**Check 4: Verify initialization order**
|
|
@@ -1324,15 +1518,52 @@ Look for lines like:
|
|
|
1324
1518
|
SecureNow must be required BEFORE any other modules:
|
|
1325
1519
|
|
|
1326
1520
|
```javascript
|
|
1327
|
-
//
|
|
1521
|
+
// Correct
|
|
1328
1522
|
require('securenow/register');
|
|
1329
1523
|
const express = require('express');
|
|
1330
1524
|
|
|
1331
|
-
//
|
|
1525
|
+
// Wrong -- too late!
|
|
1332
1526
|
const express = require('express');
|
|
1333
1527
|
require('securenow/register');
|
|
1334
1528
|
```
|
|
1335
1529
|
|
|
1530
|
+
### Firewall Not Blocking IPs
|
|
1531
|
+
|
|
1532
|
+
**Check 1: Is `SECURENOW_API_KEY` set?**
|
|
1533
|
+
|
|
1534
|
+
```bash
|
|
1535
|
+
echo $SECURENOW_API_KEY
|
|
1536
|
+
```
|
|
1537
|
+
|
|
1538
|
+
**Check 2: Is the IP in the blocklist?**
|
|
1539
|
+
|
|
1540
|
+
```bash
|
|
1541
|
+
npx securenow blocklist
|
|
1542
|
+
npx securenow firewall test-ip 1.2.3.4
|
|
1543
|
+
```
|
|
1544
|
+
|
|
1545
|
+
**Check 3: Check startup logs for sync status**
|
|
1546
|
+
|
|
1547
|
+
You should see:
|
|
1548
|
+
```
|
|
1549
|
+
[securenow] Firewall: ENABLED
|
|
1550
|
+
[securenow] Firewall: synced 142 blocked IPs
|
|
1551
|
+
```
|
|
1552
|
+
|
|
1553
|
+
If you see `initial sync failed`, check the API URL and key.
|
|
1554
|
+
|
|
1555
|
+
**Check 4: Wait for propagation**
|
|
1556
|
+
|
|
1557
|
+
After blocking an IP, it takes 10-15 seconds to propagate (one version-check interval).
|
|
1558
|
+
|
|
1559
|
+
**Check 5: Are you behind a proxy?**
|
|
1560
|
+
|
|
1561
|
+
Set `SECURENOW_TRUSTED_PROXIES` to your proxy's IP so the firewall sees the real client IP.
|
|
1562
|
+
|
|
1563
|
+
**Check 6: Using PM2?**
|
|
1564
|
+
|
|
1565
|
+
Make sure `node_args: '-r securenow/register'` is in your `ecosystem.config.cjs`. Without it, PM2 restarts skip the SDK entirely.
|
|
1566
|
+
|
|
1336
1567
|
### Logs Not Appearing
|
|
1337
1568
|
|
|
1338
1569
|
**Check 1: Is logging enabled?**
|
|
@@ -1352,7 +1583,7 @@ require('securenow/register');
|
|
|
1352
1583
|
|
|
1353
1584
|
You should see:
|
|
1354
1585
|
```
|
|
1355
|
-
[securenow]
|
|
1586
|
+
[securenow] Logging: ENABLED -> http://localhost:4318/v1/logs
|
|
1356
1587
|
```
|
|
1357
1588
|
|
|
1358
1589
|
**Check 4: Verify OTLP logs endpoint**
|
|
@@ -1407,22 +1638,24 @@ export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
|
|
|
1407
1638
|
|
|
1408
1639
|
### Next.js Instrumentation Not Working
|
|
1409
1640
|
|
|
1410
|
-
**Check 1:
|
|
1641
|
+
**Check 1: Using `withSecureNow()`?**
|
|
1642
|
+
|
|
1643
|
+
```javascript
|
|
1644
|
+
const { withSecureNow } = require('securenow/nextjs-webpack-config');
|
|
1645
|
+
module.exports = withSecureNow({ /* your config */ });
|
|
1646
|
+
```
|
|
1647
|
+
|
|
1648
|
+
This auto-handles `serverExternalPackages` / `experimental.serverComponentsExternalPackages` and `instrumentationHook` based on your Next.js version.
|
|
1649
|
+
|
|
1650
|
+
**Check 2: Verify instrumentation file location**
|
|
1411
1651
|
|
|
1412
1652
|
`instrumentation.ts` or `instrumentation.js` must be in the project root (same level as `app/` or `pages/`).
|
|
1413
1653
|
|
|
1414
|
-
**Check
|
|
1654
|
+
**Check 3: Check for OTel MODULE_NOT_FOUND errors**
|
|
1415
1655
|
|
|
1416
|
-
|
|
1417
|
-
// next.config.js
|
|
1418
|
-
module.exports = {
|
|
1419
|
-
experimental: {
|
|
1420
|
-
instrumentationHook: true,
|
|
1421
|
-
},
|
|
1422
|
-
};
|
|
1423
|
-
```
|
|
1656
|
+
If you see `MODULE_NOT_FOUND` for `@opentelemetry/*` packages, your `next.config.js` is missing the externalization. Use `withSecureNow()` to fix this automatically.
|
|
1424
1657
|
|
|
1425
|
-
**Check
|
|
1658
|
+
**Check 4: Restart dev server**
|
|
1426
1659
|
|
|
1427
1660
|
```bash
|
|
1428
1661
|
# Kill the server and restart
|
|
@@ -1441,12 +1674,12 @@ export SECURENOW_NO_UUID=1
|
|
|
1441
1674
|
|
|
1442
1675
|
This uses the same service name for all workers.
|
|
1443
1676
|
|
|
1444
|
-
**Problem: Workers not instrumented**
|
|
1677
|
+
**Problem: Workers not instrumented / firewall not active**
|
|
1445
1678
|
|
|
1446
1679
|
**Solution: Use node_args in PM2 config**
|
|
1447
1680
|
|
|
1448
1681
|
```javascript
|
|
1449
|
-
// ecosystem.config.
|
|
1682
|
+
// ecosystem.config.cjs
|
|
1450
1683
|
module.exports = {
|
|
1451
1684
|
apps: [{
|
|
1452
1685
|
name: 'my-app',
|
|
@@ -1456,11 +1689,14 @@ module.exports = {
|
|
|
1456
1689
|
env: {
|
|
1457
1690
|
SECURENOW_APPID: 'my-app',
|
|
1458
1691
|
SECURENOW_INSTANCE: 'http://localhost:4318',
|
|
1692
|
+
SECURENOW_API_KEY: 'snk_live_abc123...',
|
|
1459
1693
|
}
|
|
1460
1694
|
}]
|
|
1461
1695
|
};
|
|
1462
1696
|
```
|
|
1463
1697
|
|
|
1698
|
+
Without `node_args`, PM2 starts your script directly without the securenow preload, so neither tracing nor the firewall will be active.
|
|
1699
|
+
|
|
1464
1700
|
---
|
|
1465
1701
|
|
|
1466
1702
|
## Best Practices
|
|
@@ -1470,10 +1706,10 @@ module.exports = {
|
|
|
1470
1706
|
Don't hardcode configuration. Use environment variables:
|
|
1471
1707
|
|
|
1472
1708
|
```javascript
|
|
1473
|
-
//
|
|
1709
|
+
// Bad
|
|
1474
1710
|
process.env.SECURENOW_APPID = 'hardcoded-value';
|
|
1475
1711
|
|
|
1476
|
-
//
|
|
1712
|
+
// Good -- use .env file or export
|
|
1477
1713
|
// .env
|
|
1478
1714
|
SECURENOW_APPID=my-app
|
|
1479
1715
|
SECURENOW_INSTANCE=http://localhost:4318
|
|
@@ -1484,10 +1720,10 @@ SECURENOW_INSTANCE=http://localhost:4318
|
|
|
1484
1720
|
Pass objects to console methods for better filtering:
|
|
1485
1721
|
|
|
1486
1722
|
```javascript
|
|
1487
|
-
//
|
|
1723
|
+
// Less useful
|
|
1488
1724
|
console.log('User 123 logged in');
|
|
1489
1725
|
|
|
1490
|
-
//
|
|
1726
|
+
// Better -- structured attributes
|
|
1491
1727
|
console.log('User logged in', {
|
|
1492
1728
|
userId: 123,
|
|
1493
1729
|
email: 'user@example.com',
|
|
@@ -1517,13 +1753,13 @@ console.debug('Cache hit', { key: 'user:123' });
|
|
|
1517
1753
|
Even though SecureNow automatically redacts common sensitive fields, avoid logging:
|
|
1518
1754
|
|
|
1519
1755
|
```javascript
|
|
1520
|
-
//
|
|
1756
|
+
// Bad
|
|
1521
1757
|
console.log('Login attempt', {
|
|
1522
1758
|
email: 'user@example.com',
|
|
1523
1759
|
password: 'secret123', // Will be redacted, but don't log it!
|
|
1524
1760
|
});
|
|
1525
1761
|
|
|
1526
|
-
//
|
|
1762
|
+
// Good
|
|
1527
1763
|
console.log('Login attempt', {
|
|
1528
1764
|
email: 'user@example.com',
|
|
1529
1765
|
timestamp: Date.now(),
|
|
@@ -1594,31 +1830,35 @@ No code changes needed!
|
|
|
1594
1830
|
## Architecture
|
|
1595
1831
|
|
|
1596
1832
|
```
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1833
|
+
Your Application
|
|
1834
|
+
(Express/Next.js/etc)
|
|
1835
|
+
|
|
|
1836
|
+
v
|
|
1837
|
+
+---------------------------+
|
|
1838
|
+
| SecureNow Library |
|
|
1839
|
+
| +---------------------+ |
|
|
1840
|
+
| | Firewall Layer | | <-- Blocks IPs before they reach your app
|
|
1841
|
+
| +---------------------+ |
|
|
1842
|
+
| | Auto-instrumentation | |
|
|
1843
|
+
| | Console wrapper | |
|
|
1844
|
+
| | Body capture | |
|
|
1845
|
+
| +---------------------+ |
|
|
1846
|
+
+---------------------------+
|
|
1847
|
+
|
|
|
1848
|
+
+---------+---------+
|
|
1849
|
+
| |
|
|
1850
|
+
v v
|
|
1851
|
+
+-----------+ +-----------+
|
|
1852
|
+
| OTel SDK | | SecureNow |
|
|
1853
|
+
| OTLP | | API |
|
|
1854
|
+
| Exporters | | (blocklist|
|
|
1855
|
+
+-----------+ | sync) |
|
|
1856
|
+
| +-----------+
|
|
1857
|
+
v
|
|
1858
|
+
+-----------+
|
|
1859
|
+
| Your OTLP |
|
|
1860
|
+
| Backend |
|
|
1861
|
+
+-----------+
|
|
1622
1862
|
```
|
|
1623
1863
|
|
|
1624
1864
|
---
|
|
@@ -1629,6 +1869,8 @@ No code changes needed!
|
|
|
1629
1869
|
- **Batch export:** Traces and logs are batched before sending
|
|
1630
1870
|
- **Async processing:** No blocking of application threads
|
|
1631
1871
|
- **Configurable:** Disable instrumentations you don't need
|
|
1872
|
+
- **Firewall:** Sub-millisecond IP lookups using pre-compiled hash sets and sorted CIDR lists
|
|
1873
|
+
- **Smart sync:** Version-based polling with ETag/304 eliminates unnecessary data transfer
|
|
1632
1874
|
|
|
1633
1875
|
---
|
|
1634
1876
|
|
|
@@ -1636,10 +1878,12 @@ No code changes needed!
|
|
|
1636
1878
|
|
|
1637
1879
|
- **Automatic redaction** of sensitive fields (passwords, tokens, keys)
|
|
1638
1880
|
- **Configurable** sensitive field patterns
|
|
1639
|
-
- **No data stored** locally
|
|
1640
|
-
- **Multi-layer firewall**
|
|
1881
|
+
- **No data stored** locally -- everything sent to your OTLP backend
|
|
1882
|
+
- **Multi-layer firewall** -- blocks IPs at HTTP, TCP, OS, and cloud-edge levels
|
|
1641
1883
|
- **API keys** with granular scopes, IP allowlisting, and SHA-256 hashing
|
|
1642
|
-
- **
|
|
1884
|
+
- **Allowlist support** -- trusted IPs are never blocked
|
|
1885
|
+
- **Fail-open by default** -- network issues never accidentally block legitimate traffic
|
|
1886
|
+
- **Open source** -- audit the code yourself
|
|
1643
1887
|
|
|
1644
1888
|
---
|
|
1645
1889
|
|
|
@@ -1677,4 +1921,4 @@ Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for gu
|
|
|
1677
1921
|
|
|
1678
1922
|
---
|
|
1679
1923
|
|
|
1680
|
-
**Made with
|
|
1924
|
+
**Made with care for the Node.js community**
|