feat: HA-Cluster v1.2.x — Split-Brain, TOTP, Enterprise-FW, Drift-Fix, VIP-Recovery

- keepalived: pg_role='standby' hat Vorrang vor role für BACKUP-Bestimmung
- keepalived-master.sh: gecrasht Dienste beim MASTER-Übergang starten (nicht nur reload)
- confighash: ip_addresses per Interface-Name hashen statt per FK (Cross-Node-Drift-Fix)
- TOTP/2FA: RFC 6238 — Setup-Flow, QR-Code, Admin-Disable; two-step Login
- Firewall-UI: Enterprise-Design — auto-Beschreibung, icon-only Actions, zero-hit Indikator
- fe80-Filter: Link-local IPv6 aus NTP/DNS Listen-Dropdowns entfernen
- VIP-Dashboard, Dual-Path VRRP, GW-Tracking (Migrations 0033/0034)
- Forward Proxy + DNS erweiterte Einstellungen (Migrations 0031/0032)
- unbound-control: edgeguard in unbound-Gruppe via postinst

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-31 18:18:31 +02:00
parent 49899e984c
commit 1d06b28064
55 changed files with 3132 additions and 672 deletions

View File

@@ -204,12 +204,16 @@ func (r *Repo) DeleteRecord(ctx context.Context, id int64) error {
func (r *Repo) GetSettings(ctx context.Context) (*models.DNSSettings, error) {
row := r.Pool.QueryRow(ctx, `
SELECT id, listen_addresses, listen_port, upstream_forwards, access_acl,
dnssec, qname_minimisation, cache_min_ttl, cache_max_ttl, updated_at
dnssec, qname_minimisation, cache_min_ttl, cache_max_ttl,
prefetch, serve_expired, msg_cache_size_mb, rrset_cache_size_mb,
updated_at
FROM dns_settings WHERE id=1`)
var s models.DNSSettings
if err := row.Scan(&s.ID, &s.ListenAddresses, &s.ListenPort, &s.UpstreamForwards,
&s.AccessACL, &s.DNSSEC, &s.QNameMinimisation,
&s.CacheMinTTL, &s.CacheMaxTTL, &s.UpdatedAt); err != nil {
&s.CacheMinTTL, &s.CacheMaxTTL,
&s.Prefetch, &s.ServeExpired, &s.MsgCacheSizeMB, &s.RRSetCacheSizeMB,
&s.UpdatedAt); err != nil {
return nil, err
}
return &s, nil
@@ -220,16 +224,22 @@ func (r *Repo) UpdateSettings(ctx context.Context, s models.DNSSettings) (*model
UPDATE dns_settings SET
listen_addresses=$1, listen_port=$2, upstream_forwards=$3, access_acl=$4,
dnssec=$5, qname_minimisation=$6, cache_min_ttl=$7, cache_max_ttl=$8,
prefetch=$9, serve_expired=$10, msg_cache_size_mb=$11, rrset_cache_size_mb=$12,
updated_at=NOW()
WHERE id=1
RETURNING id, listen_addresses, listen_port, upstream_forwards, access_acl,
dnssec, qname_minimisation, cache_min_ttl, cache_max_ttl, updated_at`,
dnssec, qname_minimisation, cache_min_ttl, cache_max_ttl,
prefetch, serve_expired, msg_cache_size_mb, rrset_cache_size_mb,
updated_at`,
s.ListenAddresses, s.ListenPort, s.UpstreamForwards, s.AccessACL,
s.DNSSEC, s.QNameMinimisation, s.CacheMinTTL, s.CacheMaxTTL)
s.DNSSEC, s.QNameMinimisation, s.CacheMinTTL, s.CacheMaxTTL,
s.Prefetch, s.ServeExpired, s.MsgCacheSizeMB, s.RRSetCacheSizeMB)
var out models.DNSSettings
if err := row.Scan(&out.ID, &out.ListenAddresses, &out.ListenPort, &out.UpstreamForwards,
&out.AccessACL, &out.DNSSEC, &out.QNameMinimisation,
&out.CacheMinTTL, &out.CacheMaxTTL, &out.UpdatedAt); err != nil {
&out.CacheMinTTL, &out.CacheMaxTTL,
&out.Prefetch, &out.ServeExpired, &out.MsgCacheSizeMB, &out.RRSetCacheSizeMB,
&out.UpdatedAt); err != nil {
return nil, err
}
return &out, nil