securenow 5.18.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +40 -239
- package/cli.js +455 -415
- package/console-instrumentation.js +136 -147
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +455 -1339
- package/docs/ARCHITECTURE.md +3 -3
- package/docs/AUTO-BODY-CAPTURE.md +1 -1
- package/docs/AUTO-SETUP.md +4 -4
- package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
- package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
- package/docs/CHANGELOG-NEXTJS.md +1 -1
- package/docs/CUSTOMER-GUIDE.md +16 -16
- package/docs/EASIEST-SETUP.md +5 -5
- package/docs/ENVIRONMENT-VARIABLES.md +652 -880
- package/docs/EXPRESS-BODY-CAPTURE.md +12 -13
- package/docs/EXPRESS-SETUP-GUIDE.md +720 -719
- package/docs/INDEX.md +4 -22
- package/docs/LOGGING-GUIDE.md +708 -701
- package/docs/LOGGING-QUICKSTART.md +239 -234
- package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
- package/docs/NEXTJS-GUIDE.md +14 -14
- package/docs/NEXTJS-QUICKSTART.md +1 -1
- package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
- package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
- package/docs/REDACTION-EXAMPLES.md +1 -1
- package/docs/REQUEST-BODY-CAPTURE.md +10 -19
- package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
- package/examples/README.md +6 -6
- package/examples/instrumentation-with-auto-capture.ts +1 -1
- package/examples/nextjs-env-example.txt +2 -2
- package/examples/nextjs-instrumentation.js +1 -1
- package/examples/nextjs-instrumentation.ts +1 -1
- package/examples/nextjs-with-logging-example.md +6 -6
- package/examples/nextjs-with-options.ts +1 -1
- package/examples/test-nextjs-setup.js +1 -1
- package/nextjs-auto-capture.js +207 -199
- package/nextjs-middleware.js +181 -186
- package/nextjs-webpack-config.js +53 -88
- package/nextjs-wrapper.js +158 -158
- package/nextjs.d.ts +1 -1
- package/nextjs.js +135 -190
- package/package.json +45 -67
- package/postinstall.js +6 -6
- package/register.d.ts +1 -1
- package/register.js +4 -39
- package/tracing.d.ts +1 -2
- package/tracing.js +22 -287
- package/web-vite.mjs +156 -239
- package/CONSUMING-APPS-GUIDE.md +0 -455
- package/NPM_README.md +0 -1933
- package/SKILL-API.md +0 -600
- package/SKILL-CLI.md +0 -409
- package/cidr.js +0 -83
- package/cli/apps.js +0 -585
- package/cli/auth.js +0 -280
- package/cli/client.js +0 -115
- package/cli/config.js +0 -173
- package/cli/firewall.js +0 -100
- package/cli/fp.js +0 -638
- package/cli/init.js +0 -201
- package/cli/monitor.js +0 -440
- package/cli/run.js +0 -133
- package/cli/security.js +0 -1064
- package/cli/ui.js +0 -386
- package/docs/API-KEYS-GUIDE.md +0 -233
- package/docs/AUTO-SETUP-SUMMARY.md +0 -331
- package/docs/BODY-CAPTURE-FIX.md +0 -261
- package/docs/COMPLETION-REPORT.md +0 -408
- package/docs/FINAL-SOLUTION.md +0 -335
- package/docs/FIREWALL-GUIDE.md +0 -426
- package/docs/IMPLEMENTATION-SUMMARY.md +0 -410
- package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +0 -323
- package/docs/NEXTJS-SETUP-COMPLETE.md +0 -795
- package/docs/NUXT-GUIDE.md +0 -166
- package/docs/SOLUTION-SUMMARY.md +0 -312
- package/firewall-cloud.js +0 -212
- package/firewall-iptables.js +0 -139
- package/firewall-only.js +0 -38
- package/firewall-tcp.js +0 -74
- package/firewall.js +0 -720
- package/free-trial-banner.js +0 -174
- package/nuxt-server-plugin.mjs +0 -423
- package/nuxt.d.ts +0 -60
- package/nuxt.mjs +0 -75
- package/resolve-ip.js +0 -77
package/docs/FIREWALL-GUIDE.md
DELETED
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
# SecureNow Firewall — Automatic IP Blocking for Node.js
|
|
2
|
-
|
|
3
|
-
Block malicious IPs at your application layer with zero code changes. The firewall syncs your SecureNow blocklist and enforces it across up to four network layers — from HTTP 403 responses all the way down to kernel-level packet drops and cloud-edge WAF rules.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## How It Works
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
Internet Traffic
|
|
11
|
-
│
|
|
12
|
-
▼
|
|
13
|
-
┌──────────────────────────┐
|
|
14
|
-
│ Layer 4: Cloud/Edge WAF │ Blocked at CDN (Cloudflare, AWS WAF, GCP Cloud Armor)
|
|
15
|
-
└──────────┬───────────────┘
|
|
16
|
-
▼
|
|
17
|
-
┌──────────────────────────┐
|
|
18
|
-
│ Layer 3: OS Firewall │ Dropped at kernel (iptables/nftables)
|
|
19
|
-
└──────────┬───────────────┘
|
|
20
|
-
▼
|
|
21
|
-
┌──────────────────────────┐
|
|
22
|
-
│ Layer 2: TCP Socket │ socket.destroy() — zero bytes sent back
|
|
23
|
-
└──────────┬───────────────┘
|
|
24
|
-
▼
|
|
25
|
-
┌──────────────────────────┐
|
|
26
|
-
│ Layer 1: HTTP Handler │ 403 Forbidden JSON response
|
|
27
|
-
└──────────┬───────────────┘
|
|
28
|
-
▼
|
|
29
|
-
Your App
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
All layers share the same in-memory blocklist, synced from the SecureNow API using a version-based protocol. Layer 1 (HTTP) is always active. Layers 2-4 are opt-in via environment variables.
|
|
33
|
-
|
|
34
|
-
**Sync protocol:**
|
|
35
|
-
- A lightweight version check runs every 10 seconds (uses ETag/304 -- no data transferred when unchanged)
|
|
36
|
-
- Full blocklist sync only when the version changes, or every 5 minutes as a safety net
|
|
37
|
-
- Changes propagate to all running instances in 10-15 seconds
|
|
38
|
-
- Exponential backoff with jitter when the API is temporarily unreachable
|
|
39
|
-
- Automatic localhost fallback when API is co-located (ECONNREFUSED triggers retry on `http://localhost:4000`)
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Quick Start
|
|
44
|
-
|
|
45
|
-
### 1. Get an API Key
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
# Log in to SecureNow
|
|
49
|
-
npx securenow login
|
|
50
|
-
|
|
51
|
-
# View your firewall status and API key
|
|
52
|
-
npx securenow firewall status
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Or create an API key from the dashboard: **Settings → API Keys → Create Key** with the `firewall:read` scope.
|
|
56
|
-
|
|
57
|
-
### 2. Add the Key to Your Environment
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
# .env
|
|
61
|
-
SECURENOW_API_KEY=snk_live_abc123...
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### 3. Start Your App
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
node -r securenow/register app.js
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
That's it. The firewall auto-activates when `SECURENOW_API_KEY` is present. You'll see:
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
[securenow] Firewall: ENABLED
|
|
74
|
-
[securenow] Firewall: Layer 1 (HTTP 403) active
|
|
75
|
-
[securenow] Firewall: Layer 2 (TCP drop) disabled (set SECURENOW_FIREWALL_TCP=1)
|
|
76
|
-
[securenow] Firewall: Layer 3 (iptables) disabled (set SECURENOW_FIREWALL_IPTABLES=1)
|
|
77
|
-
[securenow] Firewall: Layer 4 (Cloud WAF) disabled (set SECURENOW_FIREWALL_CLOUD=cloudflare|aws|gcp)
|
|
78
|
-
[securenow] Firewall: synced 142 blocked IPs (138 exact + 4 CIDR ranges)
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Firewall-Only Mode (No Tracing)
|
|
82
|
-
|
|
83
|
-
If you only need IP blocking without OpenTelemetry tracing:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
node -r securenow/firewall-only app.js
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
This loads only the firewall with zero OTel dependencies. No `serverExternalPackages`, no `instrumentation.js`, no tracing overhead. Set `SECURENOW_API_KEY` in your environment and you're done.
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Layers In Detail
|
|
94
|
-
|
|
95
|
-
### Layer 1: HTTP Handler (default — always on)
|
|
96
|
-
|
|
97
|
-
Intercepts every incoming HTTP/HTTPS request. Resolves the real client IP (respects `X-Forwarded-For` from trusted proxies), checks against the blocklist, and returns a 403 JSON response if blocked.
|
|
98
|
-
|
|
99
|
-
```json
|
|
100
|
-
{ "error": "Forbidden" }
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Works with every framework: Express, Fastify, Next.js, NestJS, Koa, Hapi, raw `http.createServer`, etc.
|
|
104
|
-
|
|
105
|
-
**Customize the status code:**
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
SECURENOW_FIREWALL_STATUS_CODE=429
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Layer 2: TCP Socket (`SECURENOW_FIREWALL_TCP=1`)
|
|
112
|
-
|
|
113
|
-
Destroys the TCP connection before HTTP parsing starts. Zero bytes sent back to the attacker — they see a connection reset, not a response.
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
SECURENOW_FIREWALL_TCP=1
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Caveat:** TCP-level only sees the direct connection IP (no proxy headers). Connections from known proxy IPs are let through to Layer 1 for proper header-based resolution. Most effective for direct-to-server deployments.
|
|
120
|
-
|
|
121
|
-
### Layer 3: OS Firewall (`SECURENOW_FIREWALL_IPTABLES=1`)
|
|
122
|
-
|
|
123
|
-
Manages a dedicated `SECURENOW_BLOCK` iptables/nftables chain. True kernel-level `DROP` — packets never reach Node.js.
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
SECURENOW_FIREWALL_IPTABLES=1
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**Requirements:**
|
|
130
|
-
- Linux only (skips gracefully on macOS/Windows)
|
|
131
|
-
- Requires `root` or `CAP_NET_ADMIN` capability
|
|
132
|
-
- Auto-detects nftables vs iptables
|
|
133
|
-
- Dedicated chain — never touches your existing rules
|
|
134
|
-
- Max 10,000 rules (configurable)
|
|
135
|
-
- Full cleanup on process shutdown (SIGINT/SIGTERM)
|
|
136
|
-
|
|
137
|
-
### Layer 4: Cloud/Edge WAF (`SECURENOW_FIREWALL_CLOUD=<provider>`)
|
|
138
|
-
|
|
139
|
-
Pushes the blocklist to your cloud WAF. Traffic is blocked at the CDN edge before it reaches your server.
|
|
140
|
-
|
|
141
|
-
#### Cloudflare
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
SECURENOW_FIREWALL_CLOUD=cloudflare
|
|
145
|
-
CLOUDFLARE_API_TOKEN=your-token
|
|
146
|
-
CLOUDFLARE_ACCOUNT_ID=your-account-id
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Creates/updates an IP List named `securenow-blocklist` with a WAF custom rule.
|
|
150
|
-
|
|
151
|
-
#### AWS WAF
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
SECURENOW_FIREWALL_CLOUD=aws
|
|
155
|
-
AWS_WAF_IP_SET_ID=your-ip-set-id
|
|
156
|
-
AWS_WAF_IP_SET_NAME=securenow-blocklist # optional, default
|
|
157
|
-
AWS_WAF_SCOPE=REGIONAL # or CLOUDFRONT
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Requires `@aws-sdk/client-wafv2` installed as a peer dependency:
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
npm install @aws-sdk/client-wafv2
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### GCP Cloud Armor
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
SECURENOW_FIREWALL_CLOUD=gcp
|
|
170
|
-
GCP_PROJECT_ID=your-project
|
|
171
|
-
GCP_SECURITY_POLICY=your-policy-name
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Requires `@google-cloud/compute` installed as a peer dependency:
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
npm install @google-cloud/compute
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### Dry-Run Mode
|
|
181
|
-
|
|
182
|
-
Test cloud pushes without applying changes:
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
SECURENOW_FIREWALL_CLOUD_DRY_RUN=1
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## Environment Variables Reference
|
|
191
|
-
|
|
192
|
-
| Variable | Default | Description |
|
|
193
|
-
|----------|---------|-------------|
|
|
194
|
-
| `SECURENOW_API_KEY` | *(required)* | API key with `firewall:read` scope |
|
|
195
|
-
| `SECURENOW_API_URL` | `https://api.securenow.ai` | API base URL. Auto-fallback to `http://localhost:4000` on ECONNREFUSED. |
|
|
196
|
-
| `SECURENOW_FIREWALL_ENABLED` | `1` | Master kill-switch (`0` to disable) |
|
|
197
|
-
| `SECURENOW_FIREWALL_VERSION_INTERVAL` | `10` | Seconds between version checks (lightweight ETag-based) |
|
|
198
|
-
| `SECURENOW_FIREWALL_SYNC_INTERVAL` | `300` | Full blocklist refresh interval in seconds (safety net) |
|
|
199
|
-
| `SECURENOW_FIREWALL_FAIL_MODE` | `open` | `open` = allow when list unavailable; `closed` = block all |
|
|
200
|
-
| `SECURENOW_FIREWALL_STATUS_CODE` | `403` | HTTP status code for blocked requests (Layer 1) |
|
|
201
|
-
| `SECURENOW_FIREWALL_LOG` | `1` | Log blocked requests to console (`0` to silence) |
|
|
202
|
-
| `SECURENOW_FIREWALL_TCP` | `0` | Enable Layer 2 TCP blocking |
|
|
203
|
-
| `SECURENOW_FIREWALL_IPTABLES` | `0` | Enable Layer 3 iptables/nftables blocking |
|
|
204
|
-
| `SECURENOW_FIREWALL_CLOUD` | *(none)* | Cloud WAF provider: `cloudflare`, `aws`, or `gcp` |
|
|
205
|
-
| `SECURENOW_FIREWALL_CLOUD_DRY_RUN` | `0` | Log cloud pushes without applying |
|
|
206
|
-
| `SECURENOW_TRUSTED_PROXIES` | *(none)* | Comma-separated trusted proxy IPs |
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
## Framework Examples
|
|
211
|
-
|
|
212
|
-
### Express.js
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
# .env
|
|
216
|
-
SECURENOW_APPID=my-express-app
|
|
217
|
-
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
218
|
-
SECURENOW_API_KEY=snk_live_abc123...
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
node -r securenow/register app.js
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
No code changes needed. The firewall patches `http.createServer` before Express starts.
|
|
226
|
-
|
|
227
|
-
### Next.js
|
|
228
|
-
|
|
229
|
-
```bash
|
|
230
|
-
# .env.local
|
|
231
|
-
SECURENOW_APPID=my-nextjs-app
|
|
232
|
-
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
233
|
-
SECURENOW_API_KEY=snk_live_abc123...
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
```javascript
|
|
237
|
-
// next.config.js
|
|
238
|
-
const { withSecureNow } = require('securenow/nextjs-webpack-config');
|
|
239
|
-
module.exports = withSecureNow({ /* your config */ });
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
// instrumentation.ts
|
|
244
|
-
export async function register() {
|
|
245
|
-
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
246
|
-
const { registerSecureNow } = require('securenow/nextjs');
|
|
247
|
-
registerSecureNow();
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
The firewall initializes independently from OpenTelemetry -- it works even if tracing setup encounters an error.
|
|
253
|
-
|
|
254
|
-
### PM2 Cluster
|
|
255
|
-
|
|
256
|
-
```javascript
|
|
257
|
-
// ecosystem.config.cjs
|
|
258
|
-
module.exports = {
|
|
259
|
-
apps: [{
|
|
260
|
-
name: 'my-app',
|
|
261
|
-
script: './app.js',
|
|
262
|
-
instances: 4,
|
|
263
|
-
node_args: '-r securenow/register',
|
|
264
|
-
env: {
|
|
265
|
-
SECURENOW_APPID: 'my-app',
|
|
266
|
-
SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
|
|
267
|
-
SECURENOW_API_KEY: 'snk_live_abc123...',
|
|
268
|
-
SECURENOW_NO_UUID: '1',
|
|
269
|
-
SECURENOW_FIREWALL_TCP: '1',
|
|
270
|
-
}
|
|
271
|
-
}]
|
|
272
|
-
};
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### Docker
|
|
276
|
-
|
|
277
|
-
```dockerfile
|
|
278
|
-
ENV SECURENOW_APPID=my-app
|
|
279
|
-
ENV SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
280
|
-
ENV SECURENOW_API_KEY=snk_live_abc123...
|
|
281
|
-
ENV SECURENOW_FIREWALL_TCP=1
|
|
282
|
-
|
|
283
|
-
CMD ["node", "-r", "securenow/register", "app.js"]
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
## CLI Commands
|
|
289
|
-
|
|
290
|
-
### Check Firewall Status
|
|
291
|
-
|
|
292
|
-
```bash
|
|
293
|
-
npx securenow firewall status
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
Shows: enabled/disabled, active layers, last sync time, blocked IP count, and API key info.
|
|
297
|
-
|
|
298
|
-
### Test an IP
|
|
299
|
-
|
|
300
|
-
```bash
|
|
301
|
-
npx securenow firewall test-ip 203.0.113.42
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
Check whether a specific IP would be blocked by the current blocklist.
|
|
305
|
-
|
|
306
|
-
### Manage the Blocklist
|
|
307
|
-
|
|
308
|
-
```bash
|
|
309
|
-
# List blocked IPs
|
|
310
|
-
npx securenow blocklist
|
|
311
|
-
|
|
312
|
-
# Block an IP
|
|
313
|
-
npx securenow blocklist add 203.0.113.42 --reason "Brute force"
|
|
314
|
-
|
|
315
|
-
# Unblock
|
|
316
|
-
npx securenow blocklist remove <id>
|
|
317
|
-
|
|
318
|
-
# Statistics
|
|
319
|
-
npx securenow blocklist stats
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
Changes take effect on the next version check (default every 10 seconds). Trusted IP changes also trigger immediate cache invalidation on the API side.
|
|
323
|
-
|
|
324
|
-
---
|
|
325
|
-
|
|
326
|
-
## Security Considerations
|
|
327
|
-
|
|
328
|
-
### Fail-Open vs Fail-Closed
|
|
329
|
-
|
|
330
|
-
By default, the firewall operates in **fail-open** mode: if the API is unreachable, all traffic is allowed. This prevents the firewall from accidentally blocking legitimate traffic due to a network issue.
|
|
331
|
-
|
|
332
|
-
For high-security environments, set `SECURENOW_FIREWALL_FAIL_MODE=closed` to block all traffic when the blocklist is unavailable.
|
|
333
|
-
|
|
334
|
-
### IP Resolution
|
|
335
|
-
|
|
336
|
-
The firewall uses the same trusted-proxy-aware IP resolution as SecureNow tracing:
|
|
337
|
-
|
|
338
|
-
- Only reads `X-Forwarded-For` / `X-Real-IP` when the direct connection comes from a private/trusted IP
|
|
339
|
-
- Walks the header chain from right to left to find the first non-proxy IP
|
|
340
|
-
- Configure additional trusted proxies via `SECURENOW_TRUSTED_PROXIES`
|
|
341
|
-
|
|
342
|
-
### API Key Security
|
|
343
|
-
|
|
344
|
-
- The firewall API key only needs the `firewall:read` scope
|
|
345
|
-
- Store it in environment variables or `.env` — never commit it to source control
|
|
346
|
-
- The key is hashed (SHA-256) on the server — SecureNow never stores the plaintext
|
|
347
|
-
|
|
348
|
-
### Sync Architecture
|
|
349
|
-
|
|
350
|
-
The SDK uses a unified sync endpoint (`/firewall/sync`) that combines version checking and data fetching into a single request:
|
|
351
|
-
|
|
352
|
-
1. **One request per poll** — The SDK sends its current blocklist and allowlist versions. The API responds with version info and only includes full IP lists for lists that have changed.
|
|
353
|
-
2. **HTTP Keep-Alive** — TCP connections are reused across polls. TLS handshake happens once; subsequent requests reuse the socket (~5-10ms vs ~100-200ms per request).
|
|
354
|
-
3. **Automatic fallback** — If the unified endpoint is not available (older API), the SDK falls back to legacy separate endpoints.
|
|
355
|
-
|
|
356
|
-
### Circuit Breaker & Back-Pressure
|
|
357
|
-
|
|
358
|
-
- **Circuit breaker** — After 5 consecutive errors, the SDK pauses all polling for 2 minutes. After cooldown, a single probe is sent. If it succeeds, normal polling resumes.
|
|
359
|
-
- **In-flight guard** — Only one poll can be in-flight at a time. If the API is slow, the next scheduled poll is skipped.
|
|
360
|
-
- **429 Retry-After** — When the API returns HTTP 429, all polling pauses for the `Retry-After` duration.
|
|
361
|
-
- **Exponential backoff** — Poll interval doubles on each consecutive error (10s → 20s → 40s → 80s, capped at 120s).
|
|
362
|
-
|
|
363
|
-
### Cleanup on Shutdown
|
|
364
|
-
|
|
365
|
-
All layers clean up on process exit (SIGINT/SIGTERM):
|
|
366
|
-
- Layer 1: restores original `http.createServer`
|
|
367
|
-
- Layer 2: restores original `net.Server.prototype.listen`
|
|
368
|
-
- Layer 3: removes the `SECURENOW_BLOCK` iptables/nftables chain
|
|
369
|
-
- Layer 4: no cleanup needed (cloud rules persist intentionally)
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
## Troubleshooting
|
|
374
|
-
|
|
375
|
-
### Firewall Not Activating
|
|
376
|
-
|
|
377
|
-
**Check 1:** Is `SECURENOW_API_KEY` set?
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
echo $SECURENOW_API_KEY
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
**Check 2:** Is the firewall disabled?
|
|
384
|
-
|
|
385
|
-
```bash
|
|
386
|
-
# Must NOT be set to 0
|
|
387
|
-
echo $SECURENOW_FIREWALL_ENABLED
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**Check 3:** Check the startup log for sync errors:
|
|
391
|
-
|
|
392
|
-
```
|
|
393
|
-
[securenow] Firewall: initial sync failed: API returned 401
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
This usually means the API key is invalid or missing the `firewall:read` scope.
|
|
397
|
-
|
|
398
|
-
### IPs Not Being Blocked
|
|
399
|
-
|
|
400
|
-
**Check 1:** Is the IP actually in your blocklist?
|
|
401
|
-
|
|
402
|
-
```bash
|
|
403
|
-
npx securenow blocklist
|
|
404
|
-
npx securenow firewall test-ip 1.2.3.4
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
**Check 2:** Are you behind a proxy? The firewall needs to see the real client IP. Set `SECURENOW_TRUSTED_PROXIES` to your proxy's IP.
|
|
408
|
-
|
|
409
|
-
**Check 3:** Wait 10-15 seconds for version-based propagation. The version check interval defaults to 10 seconds.
|
|
410
|
-
|
|
411
|
-
**Check 4:** Using PM2? Make sure `node_args: '-r securenow/register'` is in your `ecosystem.config.cjs`. Without it, PM2 restarts skip the SDK entirely.
|
|
412
|
-
|
|
413
|
-
### iptables Layer Not Working
|
|
414
|
-
|
|
415
|
-
- Must be on Linux
|
|
416
|
-
- Must run as root or with `CAP_NET_ADMIN`
|
|
417
|
-
- Check: `iptables -L SECURENOW_BLOCK` (should show the chain)
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
## Related Documentation
|
|
422
|
-
|
|
423
|
-
- [API Keys Guide](./API-KEYS-GUIDE.md) — Creating and managing API keys
|
|
424
|
-
- [Environment Variables Reference](./ENVIRONMENT-VARIABLES.md) — All configuration options
|
|
425
|
-
- [All Frameworks Quick Start](./ALL-FRAMEWORKS-QUICKSTART.md) — Framework setup guides
|
|
426
|
-
- [Automatic IP Capture](./AUTOMATIC-IP-CAPTURE.md) — How client IPs are resolved
|