Internet exposure checks and response rate limiting
Jarl works out which views are reachable from the internet (match-clients
ending in a catch-all, not private-looking addresses: an internal view of a
global IPv6 prefix is still yours; a server without views: open allow-query
and a non-private listen address), with a per-view override (schema 9), and
checks public ones: rate limiting, open resolver, minimal-any, cache
snooping, open NOTIFY and transfers, version and host name, management
interfaces. Fixes are staged like any change, including rate limiting from
ISC's example in log-only mode with the secondaries exempt, then enforcing.
named logs what rate limiting limits (or would, in log-only mode, where its
counters don't move) as query-errors; Jarl routes those lines to its log
and counts them (rrl breakdown, ratelimited top lists, Prometheus
jarl_ratelimit_logged_total), shown on the new Exposure page.
A change that newly opens a public view up must be confirmed (accept_risk,
--accept-risk, a checkbox on the Changes page; 409 confirm_risk
otherwise). Findings can be acknowledged with a reason and stay visible as
info. GET /exposure, POST /exposure/fix|ack|unack, jarl exposure,
docs/exposure.md.
Also fixes query statistics skipping TSIG-signed queries ("IP#port/key
NAME" in named's log).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cf550bd512
commit
bdd7acfd3b
50 files changed
+2019
-52
No files matched your search
@@ -51,8 +51,21 @@ const (
|
||||
// operations.
|
||||
OpRecordDisable = "record.disable"
|
||||
OpRecordEnable = "record.enable"
|
||||
// Acknowledging an exposure finding (docs/exposure.md), and taking it
|
||||
// back, become view.update or settings.update operations.
|
||||
OpExposureAck = "exposure.ack"
|
||||
OpExposureUnack = "exposure.unack"
|
||||
)
|
||||
|
||||
// AckInput acknowledges (or un-acknowledges) an exposure finding of a view
|
||||
// (by ID or name), or of the server (neither given).
|
||||
type AckInput struct {
|
||||
ViewID int64 `json:"view_id,omitempty"`
|
||||
View string `json:"view,omitempty"`
|
||||
Code string `json:"code"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
// OpKinds lists all operation kinds.
|
||||
var OpKinds = []string{OpZoneCreate, OpZoneUpdate, OpZoneDelete, OpRecordCreate, OpRecordUpdate, OpRecordDelete, OpRRSetReplace,
|
||||
OpViewCreate, OpViewUpdate, OpViewDelete, OpViewReorder, OpACLCreate, OpACLUpdate, OpACLDelete,
|
||||
@@ -184,6 +197,9 @@ type ViewInput struct {
|
||||
AdoptZones bool `json:"adopt_zones,omitempty"`
|
||||
// Cascade (delete) also deletes the view's zones.
|
||||
Cascade bool `json:"cascade,omitempty"`
|
||||
// Exposure is "auto" (or ""), "public" or "private" (docs/exposure.md).
|
||||
Exposure *string `json:"exposure,omitempty"`
|
||||
Acknowledged *[]model.Acknowledgement `json:"acknowledged,omitempty"`
|
||||
}
|
||||
|
||||
// ReorderInput sets the order of views.
|
||||
@@ -227,6 +243,9 @@ type SettingsInput struct {
|
||||
Expire *uint32 `json:"expire,omitempty"`
|
||||
NegativeTTL *uint32 `json:"negative_ttl,omitempty"`
|
||||
SerialPolicy *string `json:"serial_policy,omitempty"`
|
||||
// Exposure and Acknowledged are the server's (docs/exposure.md).
|
||||
Exposure *string `json:"exposure,omitempty"`
|
||||
Acknowledged *[]model.Acknowledgement `json:"acknowledged,omitempty"`
|
||||
}
|
||||
|
||||
// DeleteInput carries options for delete operations.
|
||||
|
||||
Reference in new issue
Block a user