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:
co-authored by
Claude Sonnet 4.6
parent
49899e984c
commit
1d06b28064
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import { Alert, Button, Card, Col, Drawer, Form, Input, InputNumber, Modal, Progress, Row, Select, Space, Statistic, Switch, Tabs, Tag, Tooltip, Typography, message } from 'antd'
|
||||
import { Alert, Button, Card, Col, Divider, Drawer, Form, Input, InputNumber, Modal, Progress, Row, Select, Space, Statistic, Switch, Tabs, Tag, Tooltip, Typography, message } from 'antd'
|
||||
import type { ColumnsType } from 'antd/es/table'
|
||||
import { BarChartOutlined, CheckCircleOutlined, ClearOutlined, CloseCircleOutlined, GlobalOutlined, NodeIndexOutlined, PlusOutlined, ReloadOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
@@ -43,6 +43,10 @@ interface Settings {
|
||||
qname_minimisation: boolean
|
||||
cache_min_ttl: number
|
||||
cache_max_ttl: number
|
||||
prefetch: boolean
|
||||
serve_expired: boolean
|
||||
msg_cache_size_mb: number
|
||||
rrset_cache_size_mb: number
|
||||
}
|
||||
|
||||
const RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'TXT', 'MX', 'SRV', 'NS', 'PTR', 'CAA']
|
||||
@@ -464,6 +468,7 @@ function SettingsTab() {
|
||||
for (const i of sys ?? []) {
|
||||
if (i.ifname === 'lo') continue
|
||||
for (const a of i.addr_info ?? []) {
|
||||
if (a.local.startsWith('fe80:')) continue
|
||||
ipOptions.push({
|
||||
value: a.local,
|
||||
label: `${a.local} — ${i.ifname} (${a.family === 'inet' ? 'IPv4' : 'IPv6'})`,
|
||||
@@ -477,7 +482,20 @@ function SettingsTab() {
|
||||
.split(',')
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean),
|
||||
} : undefined
|
||||
} : {
|
||||
listen_addresses: [],
|
||||
listen_port: 53,
|
||||
upstream_forwards: '1.1.1.1, 9.9.9.9',
|
||||
access_acl: '10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16',
|
||||
dnssec: false,
|
||||
qname_minimisation: true,
|
||||
cache_min_ttl: 60,
|
||||
cache_max_ttl: 86400,
|
||||
prefetch: false,
|
||||
serve_expired: false,
|
||||
msg_cache_size_mb: 64,
|
||||
rrset_cache_size_mb: 128,
|
||||
}
|
||||
|
||||
const save = useMutation({
|
||||
mutationFn: async (v: SettingsForm) => {
|
||||
@@ -566,9 +584,19 @@ function SettingsTab() {
|
||||
<Form.Item label={t('dns.settings.qnameMin')} name="qname_minimisation" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Space>
|
||||
<Form.Item label={t('dns.settings.prefetch')} name="prefetch" valuePropName="checked"
|
||||
extra={t('dns.settings.prefetchExtra')}>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('dns.settings.serveExpired')} name="serve_expired" valuePropName="checked"
|
||||
extra={t('dns.settings.serveExpiredExtra')}>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
|
||||
<Divider plain>{t('dns.settings.cacheSection')}</Divider>
|
||||
<Space wrap>
|
||||
<Form.Item label={t('dns.settings.cacheMin')} name="cache_min_ttl" dependencies={['cache_max_ttl']}>
|
||||
<InputNumber min={0} style={{ width: 120 }} />
|
||||
<InputNumber min={0} style={{ width: 130 }} addonAfter="s" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('dns.settings.cacheMax')}
|
||||
@@ -586,7 +614,15 @@ function SettingsTab() {
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<InputNumber min={60} style={{ width: 120 }} />
|
||||
<InputNumber min={60} style={{ width: 130 }} addonAfter="s" />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('dns.settings.msgCacheSizeMB')} name="msg_cache_size_mb"
|
||||
extra={t('dns.settings.msgCacheSizeMBExtra')}>
|
||||
<InputNumber min={8} max={4096} style={{ width: 130 }} addonAfter="MB" />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('dns.settings.rrsetCacheSizeMB')} name="rrset_cache_size_mb"
|
||||
extra={t('dns.settings.rrsetCacheSizeMBExtra')}>
|
||||
<InputNumber min={16} max={8192} style={{ width: 130 }} addonAfter="MB" />
|
||||
</Form.Item>
|
||||
</Space>
|
||||
<Form.Item>
|
||||
|
||||
Reference in New Issue
Block a user