What's New in v2.6
v2.5 made rate limits and lockouts hold across replicas. v2.6 does the same for the settings you change from the dashboard, and gives the open-redirect rule a way to tell your hosts from someone else's. Full details are in CHANGELOG.md.
Dashboard settings outlive the process
Four things can be changed from the dashboard rather than in code:
- the WAF's mode and per-category sensitivity
- its custom rules
- the per-route rate limits
- the alert threshold
Until v2.6 each change applied to the single instance that served the request. It was lost on the next restart, and behind a load balancer the dashboard showed one value while the other replicas went on enforcing another — switching the WAF to block mode during an incident quietly protected one instance out of three.
Those settings are now stored as a snapshot and applied by every replica. There is nothing to configure: any storage backend that can keep them does, and the SQLite, Postgres, and in-memory stores all can. Each replica picks up a change within Storage.SyncInterval, and a replica that scales up starts from the same settings as the rest.
1sentinel.Mount(r, nil, sentinel.Config{2 Storage: sentinel.StorageConfig{3 Driver: sentinel.Postgres,4 DSN: os.Getenv("DATABASE_URL"),56 // How soon a change made on another replica applies here.7 // Default 5s; a negative value turns polling off.8 SyncInterval: 5 * time.Second,9 },10})
Stored settings win over your config
Once something is changed from the dashboard, that value keeps applying — including after a deploy that sets a different value in code. This is deliberate: a change made during an incident shouldn't be undone by the next release.
To hand control back to your Config, discard the stored settings. Every replica picks that up on its next poll.
# What is stored, and what your config asked forcurl http://localhost:8080/sentinel/api/settings/live \-H "Authorization: Bearer $TOKEN"# Discard the stored settings everywherecurl -X DELETE http://localhost:8080/sentinel/api/settings/live \-H "Authorization: Bearer $TOKEN"
Every change is audited with the user and the old and new values. If your storage backend cannot keep settings, the change still applies to the instance you are talking to and the response carries a warning saying so, instead of looking permanent.
Your own callbacks are not open redirects
callback=https://app.example.com/oauth is the shape of an open redirect and the shape of an ordinary OAuth callback. Sentinel has no way to know which hostnames are yours, so it reported both — two of the nine false positives in the detection corpus are exactly this. Tell it which hosts you own:
1WAF: sentinel.WAFConfig{2 Enabled: true,3 Mode: sentinel.ModeBlock,4 AllowedRedirectHosts: []string{5 "example.com", // exact host, port ignored6 "*.apps.example.com", // any subdomain, not the bare domain7 },8},
A redirect to one of those passes. A redirect anywhere else is still reported, and so is a request carrying even one outside target alongside yours — or a target Sentinel cannot parse, because a redirect it cannot read is not one it should vouch for. Encoded targets are decoded first, double-encoded ones included. ValidateConfig rejects entries written as URLs and warns when the list is set while the rule is off.
Fixes
- Whitelisted IPs were forgotten on restart and never shared between replicas. They were written to storage, but only ever held in the memory of the process that added them, so after a restart every whitelisted IP silently went back to being inspected. The cache is now rebuilt from storage.
- A block made on one replica took up to 30 seconds to apply on the others. It is 5 seconds now, and configurable. The replica making the block still applies it immediately.
- One Redis call per rate-limited request instead of two. Publishing
X-RateLimit-Remainingmeant asking for the decision and then for the usage; a store can now answer both at once. - The dashboard's first load is about 240 KB instead of 720 KB. Pages are loaded on demand, and only the two pages with charts download the charting library.
Upgrading
Nothing is required. Two things are worth knowing:
- The first time someone changes a setting from the dashboard, it becomes sticky — including across deploys.
DELETE /sentinel/api/settings/livereturns control to yourConfig. - Each replica now polls storage every 5 seconds for blocks, whitelist entries, and settings. Set
Storage.SyncIntervalto tune it, or to a negative value to turn polling off.