diff --git a/agent/app/dto/setting.go b/agent/app/dto/setting.go index 659e391549d2..9f9fa088f3b4 100644 --- a/agent/app/dto/setting.go +++ b/agent/app/dto/setting.go @@ -25,6 +25,8 @@ type SettingInfo struct { FileRecycleBin string `json:"fileRecycleBin"` LocalSSHConnShow string `json:"localSSHConnShow"` + + FirewallPortWhiteList string `json:"firewallPortWhiteList"` } type SettingUpdate struct { @@ -33,7 +35,7 @@ type SettingUpdate struct { } type AgentSettingUpdate struct { - Key string `json:"key" validate:"required,oneof=SystemIP DockerSockPath FileRecycleBin"` + Key string `json:"key" validate:"required,oneof=SystemIP DockerSockPath FileRecycleBin FirewallPortWhiteList"` Value string `json:"value"` } diff --git a/agent/app/service/firewall.go b/agent/app/service/firewall.go index b06c2d0e135a..7fee78e2eed0 100644 --- a/agent/app/service/firewall.go +++ b/agent/app/service/firewall.go @@ -579,30 +579,14 @@ func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) { } func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) error { - if !global.IsMaster { - if err := client.Port(fireClient.FireInfo{Port: global.CONF.Base.Port, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - } else { - var portSetting model.Setting - _ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error - if len(portSetting.Value) != 0 { - if err := client.Port(fireClient.FireInfo{Port: portSetting.Value, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - } - } - if err := client.Port(fireClient.FireInfo{Port: loadSSHPort(), Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - if err := client.Port(fireClient.FireInfo{Port: "80", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { - return err - } - if err := client.Port(fireClient.FireInfo{Port: "443", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + portWhiteList, err := loadFirewallPortWhiteList() + if err != nil { return err } - if err := client.Port(fireClient.FireInfo{Port: "443", Protocol: "udp", Strategy: "accept"}, "add"); err != nil { - return err + for _, item := range portWhiteList { + if err := client.Port(fireClient.FireInfo{Port: item.Port, Protocol: item.Protocol, Strategy: "accept"}, "add"); err != nil { + return err + } } return client.Reload() diff --git a/agent/app/service/firewall_setting.go b/agent/app/service/firewall_setting.go new file mode 100644 index 000000000000..4af09187a724 --- /dev/null +++ b/agent/app/service/firewall_setting.go @@ -0,0 +1,152 @@ +package service + +import ( + "fmt" + "strconv" + "strings" + + "github.com/1Panel-dev/1Panel/agent/constant" + "github.com/1Panel-dev/1Panel/agent/utils/firewall" + fireClient "github.com/1Panel-dev/1Panel/agent/utils/firewall/client" + "github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables" +) + +type firewallPortWhitelist struct { + Port string + Protocol string +} + +func loadFirewallPortWhiteList() ([]firewallPortWhitelist, error) { + value, err := settingRepo.GetValueByKey(constant.FirewallPortWhiteList) + if err != nil { + value = constant.FirewallPortWhiteListValue + if err := settingRepo.UpdateOrCreate(constant.FirewallPortWhiteList, value); err != nil { + return nil, err + } + } + return parseFullFirewallPortWhiteList(value) +} + +func parseFullFirewallPortWhiteList(value string) ([]firewallPortWhitelist, error) { + portWhiteList, err := parseFirewallPortWhiteList(value) + if err != nil { + return nil, err + } + panelPort := LoadPanelPort() + if panelPort == "" { + return nil, fmt.Errorf("find 1panel service port failed") + } + portWhiteList = append(portWhiteList, firewallPortWhitelist{Port: panelPort, Protocol: "tcp"}) + portWhiteList = append(portWhiteList, firewallPortWhitelist{Port: loadSSHPort(), Protocol: "tcp"}) + return normalizeFirewallPortWhiteList(portWhiteList), nil +} + +func parseFirewallPortWhiteList(value string) ([]firewallPortWhitelist, error) { + items := strings.FieldsFunc(value, func(r rune) bool { + return r == ',' || r == '\n' || r == ';' || r == ' ' + }) + ports := make([]firewallPortWhitelist, 0, len(items)) + exists := make(map[string]struct{}) + for _, item := range items { + item = strings.TrimSpace(item) + if item == "" { + continue + } + port, protocol, ok := strings.Cut(item, "/") + if !ok { + protocol = "tcp" + } + port = strings.TrimSpace(port) + protocol = strings.ToLower(strings.TrimSpace(protocol)) + if protocol != "tcp" && protocol != "udp" { + return nil, fmt.Errorf("invalid firewall port whitelist protocol: %s", item) + } + portNum, err := strconv.Atoi(port) + if err != nil || portNum < 1 || portNum > 65535 { + return nil, fmt.Errorf("invalid firewall port whitelist: %s", item) + } + key := fmt.Sprintf("%d/%s", portNum, protocol) + if _, ok := exists[key]; ok { + continue + } + exists[key] = struct{}{} + ports = append(ports, firewallPortWhitelist{Port: strconv.Itoa(portNum), Protocol: protocol}) + } + return ports, nil +} + +func normalizeFirewallPortWhiteList(portWhiteList []firewallPortWhitelist) []firewallPortWhitelist { + ports := make([]firewallPortWhitelist, 0, len(portWhiteList)) + exists := make(map[string]struct{}) + for _, item := range portWhiteList { + if item.Port == "" { + continue + } + key := fmt.Sprintf("%s/%s", item.Port, item.Protocol) + if _, ok := exists[key]; ok { + continue + } + exists[key] = struct{}{} + ports = append(ports, item) + } + return ports +} + +func syncFirewallPortWhiteListAfterUpdate(oldValue string) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + portWhiteList, err := loadFirewallPortWhiteList() + if err != nil { + return err + } + if client.Name() != "iptables" { + oldPortWhiteList, err := parseFullFirewallPortWhiteList(oldValue) + if err != nil { + return err + } + return syncFirewallClientPortWhiteList(client, oldPortWhiteList, portWhiteList) + } + isInit, _ := iptables.LoadInitStatus("iptables", "base") + if !isInit { + return nil + } + return applyFirewallPortWhiteListRules(portWhiteList, true) +} + +func syncFirewallClientPortWhiteList(client firewall.FirewallClient, oldPortWhiteList, portWhiteList []firewallPortWhitelist) error { + oldPorts := firewallPortWhiteListMap(oldPortWhiteList) + newPorts := firewallPortWhiteListMap(portWhiteList) + for _, item := range oldPortWhiteList { + key := firewallPortWhiteListKey(item) + if _, ok := newPorts[key]; ok { + continue + } + if err := client.Port(fireClient.FireInfo{Port: item.Port, Protocol: item.Protocol, Strategy: "accept"}, "remove"); err != nil { + return err + } + } + for _, item := range portWhiteList { + key := firewallPortWhiteListKey(item) + if _, ok := oldPorts[key]; ok { + continue + } + if err := client.Port(fireClient.FireInfo{Port: item.Port, Protocol: item.Protocol, Strategy: "accept"}, "add"); err != nil { + return err + } + } + return client.Reload() +} + +func firewallPortWhiteListMap(portWhiteList []firewallPortWhitelist) map[string]struct{} { + ports := make(map[string]struct{}) + for _, item := range portWhiteList { + ports[firewallPortWhiteListKey(item)] = struct{}{} + } + return ports +} + +func firewallPortWhiteListKey(item firewallPortWhitelist) string { + return item.Port + "/" + item.Protocol +} diff --git a/agent/app/service/iptables.go b/agent/app/service/iptables.go index 3d1adbf582bb..47488bbee20a 100644 --- a/agent/app/service/iptables.go +++ b/agent/app/service/iptables.go @@ -228,6 +228,12 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error { if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil { return err } + if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil { + return err + } + if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil { + return err + } _ = settingRepo.Update("IptablesStatus", constant.StatusEnable) return nil case "bind-base-without-init": @@ -365,25 +371,80 @@ func initPreRules() error { if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT", "-m", "comment", "--comment", "ESTABLISHED Whitelist"); err != nil { return err } - panelPort := LoadPanelPort() - if len(panelPort) == 0 { - return errors.New("find 1panel service port failed") + portWhiteList, err := loadFirewallPortWhiteList() + if err != nil { + return err + } + if err := applyFirewallPortWhiteListRules(portWhiteList, false); err != nil { + return err + } + if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "tcp", "-j", "DROP"); err != nil { + return err + } + if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "udp", "-j", "DROP"); err != nil { + return err + } + return nil +} + +func applyFirewallPortWhiteListRules(portWhiteList []firewallPortWhitelist, withSave bool) error { + if err := syncFirewallPortWhiteListRules(portWhiteList); err != nil { + return err } - ports := []string{"80", "443", panelPort, loadSSHPort()} - for _, item := range ports { - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-p", "tcp", "-m", "tcp", "--dport", item, "-j", "ACCEPT"); err != nil { + for _, item := range portWhiteList { + if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, "-p", item.Protocol, "-m", item.Protocol, "--dport", item.Port, "-j", "ACCEPT"); err != nil { return err } } - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "udp", "-m", "udp", "--dport", "443", "-j", "ACCEPT"); err != nil { + if !withSave { + return nil + } + if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil { return err } - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "tcp", "-j", "DROP"); err != nil { + return iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName) +} + +func syncFirewallPortWhiteListRules(portWhiteList []firewallPortWhitelist) error { + tcpWhitelist := make(map[string]struct{}) + udpWhitelist := make(map[string]struct{}) + for _, item := range portWhiteList { + if item.Protocol == "udp" { + udpWhitelist[item.Port] = struct{}{} + continue + } + tcpWhitelist[item.Port] = struct{}{} + } + + if err := cleanExtraFirewallPortRules(iptables.Chain1PanelBasicBefore, "tcp", tcpWhitelist); err != nil { return err } - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p", "udp", "-j", "DROP"); err != nil { + if err := cleanExtraFirewallPortRules(iptables.Chain1PanelBasicBefore, "udp", udpWhitelist); err != nil { return err } + return cleanExtraFirewallPortRules(iptables.Chain1PanelBasicAfter, "udp", map[string]struct{}{}) +} + +func cleanExtraFirewallPortRules(chain, protocol string, whitelist map[string]struct{}) error { + rules, err := iptables.ReadFilterRulesByChain(chain) + if err != nil { + return err + } + kept := make(map[string]struct{}) + for _, rule := range rules { + if rule.Strategy != "accept" || rule.Protocol != protocol || rule.DstPort == "" || rule.SrcIP != "" || rule.DstIP != "" || rule.SrcPort != "" { + continue + } + if _, ok := whitelist[rule.DstPort]; ok { + if _, seen := kept[rule.DstPort]; !seen { + kept[rule.DstPort] = struct{}{} + continue + } + } + if err := iptables.DeleteRule(iptables.FilterTab, chain, "-p", protocol, "-m", protocol, "--dport", rule.DstPort, "-j", "ACCEPT"); err != nil { + return err + } + } return nil } diff --git a/agent/app/service/setting.go b/agent/app/service/setting.go index 5c66ea4cc8d0..a28ae51ef34f 100644 --- a/agent/app/service/setting.go +++ b/agent/app/service/setting.go @@ -124,7 +124,22 @@ func (u *SettingService) GetWebsiteDir() string { } func (u *SettingService) Update(key, value string) error { - return settingRepo.UpdateOrCreate(key, value) + oldValue := constant.FirewallPortWhiteListValue + if key == constant.FirewallPortWhiteList { + if _, err := parseFirewallPortWhiteList(value); err != nil { + return err + } + if val, err := settingRepo.GetValueByKey(key); err == nil { + oldValue = val + } + } + if err := settingRepo.UpdateOrCreate(key, value); err != nil { + return err + } + if key == constant.FirewallPortWhiteList { + return syncFirewallPortWhiteListAfterUpdate(oldValue) + } + return nil } func (u *SettingService) UpdateTerminalAI(req dto.TerminalAIInfo) error { diff --git a/agent/constant/common.go b/agent/constant/common.go index 7a9c38f7d16c..347a23ff77f0 100644 --- a/agent/constant/common.go +++ b/agent/constant/common.go @@ -7,6 +7,9 @@ const ( SystemRestart = "systemRestart" + FirewallPortWhiteList = "FirewallPortWhiteList" + FirewallPortWhiteListValue = "80/tcp,443/tcp,443/udp" + TypeWebsite = "website" TypePhp = "php" TypeSSL = "ssl" diff --git a/agent/init/migration/migrate.go b/agent/init/migration/migrate.go index 76755271724f..9f83525c49ba 100644 --- a/agent/init/migration/migrate.go +++ b/agent/init/migration/migrate.go @@ -84,6 +84,7 @@ func InitAgentDB() { migrations.AddFileShareTable, migrations.AddFileHistoryTable, migrations.MigrateLegoV5, + migrations.InitFirewallPortWhiteList, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/agent/init/migration/migrations/init.go b/agent/init/migration/migrations/init.go index cf2b57e46890..8dd3be2b24cc 100644 --- a/agent/init/migration/migrations/init.go +++ b/agent/init/migration/migrations/init.go @@ -846,6 +846,23 @@ var InitIptablesStatus = &gormigrate.Migration{ if err := tx.Create(&model.Setting{Key: "IptablesOutputStatus", Value: constant.StatusDisable}).Error; err != nil { return err } + if err := tx.Create(&model.Setting{Key: constant.FirewallPortWhiteList, Value: constant.FirewallPortWhiteListValue}).Error; err != nil { + return err + } + return nil + }, +} + +var InitFirewallPortWhiteList = &gormigrate.Migration{ + ID: "20260601-init-firewall-port-whitelist", + Migrate: func(tx *gorm.DB) error { + var setting model.Setting + if err := tx.Where("key = ?", constant.FirewallPortWhiteList).First(&setting).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return tx.Create(&model.Setting{Key: constant.FirewallPortWhiteList, Value: constant.FirewallPortWhiteListValue}).Error + } + return err + } return nil }, } diff --git a/frontend/src/api/interface/setting.ts b/frontend/src/api/interface/setting.ts index 7c8f8252fbef..51373162c603 100644 --- a/frontend/src/api/interface/setting.ts +++ b/frontend/src/api/interface/setting.ts @@ -26,6 +26,7 @@ export namespace Setting { fileRecycleBin: string; localSSHConnShow: string; + firewallPortWhiteList: string; } export interface SettingInfo { systemVersion: string; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index b78195e09259..ab74b503a16a 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -3769,6 +3769,11 @@ const message = { bindHelper: 'Bind - Firewall rules will only take effect when the status is bound. Confirm?', unbindHelper: 'Unbind - When unbound, all added firewall rules will become invalid. Proceed with caution. Confirm?', + whiteList: 'Allowlist', + portWhiteList: 'Port allowlist', + portWhiteListAlter: + 'Ports in the allowlist are opened automatically when the firewall is initialized or started.', + portWhiteListHelper: 'Protocol can be specified, e.g. 80/tcp or 443/udp. Defaults to tcp when omitted.', defaultStrategy: 'Default policy for current chain {0} is {1}', defaultStrategy2: 'Default policy for current chain {0} is {1}, current status is unbound. Added firewall rules will take effect after binding!', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 87bb06681c69..f343152219c9 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -3819,6 +3819,12 @@ const message = { 'Vincular: las reglas de firewall solo surtirán efecto cuando el estado esté vinculado. ¿Confirmar?', unbindHelper: 'Desvincular: al desvincular, todas las reglas de firewall agregadas se volverán inválidas. Proceda con precaución. ¿Confirmar?', + whiteList: 'Lista blanca', + portWhiteList: 'Lista blanca de puertos', + portWhiteListAlter: + 'Los puertos de la lista blanca se abrirán automáticamente al inicializar o iniciar el firewall.', + portWhiteListHelper: + 'Puede especificar el protocolo, por ejemplo 80/tcp o 443/udp. Si se omite, se usa tcp por defecto.', defaultStrategy: 'La política predeterminada para la cadena actual {0} es {1}', defaultStrategy2: 'La política predeterminada para la cadena actual {0} es {1}, el estado actual es no vinculado. ¡Las reglas de firewall agregadas surtirán efecto después de la vinculación!', @@ -4096,7 +4102,8 @@ const message = { scoreWebsiteHTTP: '{0} no usa HTTPS', scoreWebsiteStopped: 'Estado anormal de {0}', scoreWebsiteMonitorUnavailable: 'El monitoreo web detectó un sitio no disponible', - scoreWebsiteMonitorAvailability: 'La disponibilidad del monitoreo web ({0}%) está por debajo del umbral', + scoreWebsiteMonitorAvailability: + 'La disponibilidad del monitoreo web ({0}%) está por debajo del umbral', scoreWafDisabled: 'WAF deshabilitado, los sitios web no están protegidos', scoreWafHighRiskHit: 'WAF detectó {0} reglas de riesgo en el periodo del informe', scoreCronjobFailed: '{0} registros de fallos de tareas programadas en los últimos 7 días', @@ -4202,8 +4209,10 @@ const message = { 'Se detectaron {0} configuraciones de riesgo. Refuerce la seguridad de acceso para reducir el riesgo de intrusión.', loginHealthNormalDesc: 'Las configuraciones de acceso y SSH están en estado normal', loginHealthNormalReason: 'La seguridad de acceso es normal', - securityEntranceConfiguredDesc: 'Entrada de seguridad configurada para reducir la exposición de la entrada predeterminada', - securityEntranceRiskDesc: 'Entrada de seguridad deshabilitada. Se recomienda ocultar la entrada predeterminada', + securityEntranceConfiguredDesc: + 'Entrada de seguridad configurada para reducir la exposición de la entrada predeterminada', + securityEntranceRiskDesc: + 'Entrada de seguridad deshabilitada. Se recomienda ocultar la entrada predeterminada', allowIPsRestrictedDesc: 'IPs autorizadas restringidas para el acceso al panel', allowIPsRiskDesc: 'IPs de acceso sin restricciones. Configure IPs autorizadas para entornos públicos', bindDomainRestrictedDesc: 'Dominio de acceso vinculado', @@ -4223,11 +4232,15 @@ const message = { mfaRiskDesc: 'Autenticación MFA deshabilitada. Se recomienda habilitar la autenticación multifactor', passwordExpiration: 'Fecha de vencimiento de contraseña', passwordExpirationNormalDesc: 'La fecha de vencimiento de contraseña está en un rango seguro', - passwordExpirationUnsetDesc: 'Fecha de vencimiento de contraseña no configurada. Se recomienda configurarla pronto', - passwordExpirationRiskDesc: 'La contraseña vence en {0} días. Se recomienda gestionarla con anticipación', - passwordExpirationExpiredDesc: 'La contraseña expiró hace {0} días. Por favor, gestionar lo antes posible', + passwordExpirationUnsetDesc: + 'Fecha de vencimiento de contraseña no configurada. Se recomienda configurarla pronto', + passwordExpirationRiskDesc: + 'La contraseña vence en {0} días. Se recomienda gestionarla con anticipación', + passwordExpirationExpiredDesc: + 'La contraseña expiró hace {0} días. Por favor, gestionar lo antes posible', sessionTimeoutNormalDesc: 'El tiempo de espera de sesión está en un rango seguro', - sessionTimeoutRiskDesc: 'Tiempo de espera de sesión largo. Se recomienda limitar la duración de sesiones inactivas', + sessionTimeoutRiskDesc: + 'Tiempo de espera de sesión largo. Se recomienda limitar la duración de sesiones inactivas', sshServiceNormalDesc: 'El servicio SSH está ejecutándose normalmente', sshServiceRiskDesc: 'El servicio SSH no está ejecutándose o está en estado anormal', sshPortNormalDesc: 'El puerto SSH se ha cambiado del puerto predeterminado', @@ -4235,9 +4248,11 @@ const message = { rootLoginNormalDesc: 'El usuario root no puede iniciar sesión directamente', rootLoginRiskDesc: 'El usuario root puede iniciar sesión directamente. Se recomienda deshabilitarlo', passwordAuthNormalDesc: 'El inicio de sesión SSH por contraseña está deshabilitado', - passwordAuthRiskDesc: 'El inicio de sesión por contraseña está permitido, aumentando el riesgo de fuerza bruta', + passwordAuthRiskDesc: + 'El inicio de sesión por contraseña está permitido, aumentando el riesgo de fuerza bruta', keyAuthNormalDesc: 'La autenticación SSH por clave está habilitada', - keyAuthRiskDesc: 'La autenticación por clave no está habilitada. Se recomienda usar inicio de sesión por clave', + keyAuthRiskDesc: + 'La autenticación por clave no está habilitada. Se recomienda usar inicio de sesión por clave', websiteOverview: 'Resumen de sitios web', primaryDomain: 'Dominio principal', expireTime: 'Fecha de vencimiento', @@ -4277,7 +4292,8 @@ const message = { alertHealthAttention: 'Requiere atención', alertHealthRisk: 'Riesgo alto', alertHealthSummary: 'Estado de salud de alertas', - alertHealthNormalReason: 'Tareas de alerta, canales de notificación y registros de ejecución están saludables', + alertHealthNormalReason: + 'Tareas de alerta, canales de notificación y registros de ejecución están saludables', alertNoChannelReason: 'No hay canal de notificación de alerta habilitado', alertFailedLogReason: '{0} registros de fallos de alerta encontrados', alertPendingReason: '{0} registros de alerta pendientes de sincronización', @@ -4354,7 +4370,8 @@ const message = { viewHostMonitor: 'Ver monitoreo del host', systemHealthAttentionDesc: '{0} elementos de riesgo detectados en las últimas 24 horas. Priorice los picos de recursos y el uso de disco.', - systemHealthNormalDesc: 'Las métricas de ejecución del host estuvieron normales en las últimas 24 horas', + systemHealthNormalDesc: + 'Las métricas de ejecución del host estuvieron normales en las últimas 24 horas', monitorEnabled: 'Monitoreo habilitado', cpuCoreUsage: '{0} / {1} núcleos', load1Minute: 'Carga 1 min', @@ -4521,7 +4538,8 @@ const message = { savePath: 'Directorio de guardado', savePathRequired: 'Configure el directorio de guardado del informe', autoExport: 'Habilitar exportación automática', - autoExportDesc: 'Generar automáticamente un informe de operaciones cada día a las 09:00 cuando esté habilitado', + autoExportDesc: + 'Generar automáticamente un informe de operaciones cada día a las 09:00 cuando esté habilitado', autoExportEnabled: 'Exportación automática habilitada', autoExportDisabled: 'Exportación automática deshabilitada', readOnlyPermissionTip: diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 3196d91811dc..51a8584f2004 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -3805,6 +3805,10 @@ const message = { bindHelper: 'バインド - ファイアウォールルールは状態がバインドされている場合のみ有効になります。確認しますか?', unbindHelper: 'アンバインド - アンバインドすると、追加されたすべてのファイアウォールルールが無効になります。注意して操作してください。確認しますか?', + whiteList: 'ホワイトリスト', + portWhiteList: 'ポートホワイトリスト', + portWhiteListAlter: 'ファイアウォールの初期化または起動時に、ホワイトリスト内のポートは自動的に許可されます。', + portWhiteListHelper: '80/tcp や 443/udp のようにプロトコルを指定できます。省略時は tcp が使用されます。', defaultStrategy: '現在のチェーン {0} のデフォルトポリシーは {1} です', defaultStrategy2: '現在のチェーン {0} のデフォルトポリシーは {1} です。現在の状態は未バインドです。追加されたファイアウォールルールはバインド後に有効になります!', @@ -4184,12 +4188,15 @@ const message = { '{0} 件のリスク設定を検出しました。ログインセキュリティを強化して侵入リスクを低減してください。', loginHealthNormalDesc: '現在のログインとSSHセキュリティ設定は正常です', loginHealthNormalReason: 'ログインセキュリティは正常です', - securityEntranceConfiguredDesc: 'セキュリティエントランスが設定済みで、デフォルト入口の露出リスクを低減しています', - securityEntranceRiskDesc: 'セキュリティエントランスが無効です。デフォルトのログイン入口を隠すことをお勧めします', + securityEntranceConfiguredDesc: + 'セキュリティエントランスが設定済みで、デフォルト入口の露出リスクを低減しています', + securityEntranceRiskDesc: + 'セキュリティエントランスが無効です。デフォルトのログイン入口を隠すことをお勧めします', allowIPsRestrictedDesc: 'パネルアクセス許可IPが制限されています', allowIPsRiskDesc: 'アクセスIPが制限されていません。公開環境では許可IPの設定をお勧めします', bindDomainRestrictedDesc: 'アクセスドメインがバインドされています', - bindDomainRiskDesc: 'アクセスドメインがバインドされていません。固定ドメインへのアクセス制限をお勧めします', + bindDomainRiskDesc: + 'アクセスドメインがバインドされていません。固定ドメインへのアクセス制限をお勧めします', accessRestrictionValue: '許可IP: {0} / バインドドメイン: {1}', accessRestrictionNormalDesc: '許可IPまたはバインドドメインが設定済みで、パネルアクセス元が制限されています', @@ -4198,8 +4205,7 @@ const message = { panelHTTPSNormalDesc: 'パネルHTTPSが有効です', panelHTTPSRiskDesc: 'パネルHTTPSが無効です。ログイン通信が平文で露出するリスクがあります', passwordComplexityNormalDesc: 'パスワード複雑性検証が有効です', - passwordComplexityRiskDesc: - 'パスワード複雑性検証が無効で、弱パスワードのリスクが高いです', + passwordComplexityRiskDesc: 'パスワード複雑性検証が無効で、弱パスワードのリスクが高いです', mfa: 'MFA 認証', mfaNormalDesc: 'MFA認証が有効で、ログインセキュリティが強化されています', mfaRiskDesc: 'MFA認証が無効です。多要素認証の有効化をお勧めします', @@ -4209,7 +4215,8 @@ const message = { passwordExpirationRiskDesc: 'パスワードが{0}日以内に期限切れになります。事前に対応してください', passwordExpirationExpiredDesc: 'パスワードが{0}日前に期限切れになりました。至急対応してください', sessionTimeoutNormalDesc: 'セッションタイムアウトは安全な範囲内です', - sessionTimeoutRiskDesc: 'セッションタイムアウトが長めです。アイドルセッションの有効期間を制限することをお勧めします', + sessionTimeoutRiskDesc: + 'セッションタイムアウトが長めです。アイドルセッションの有効期間を制限することをお勧めします', sshServiceNormalDesc: 'SSHサービスは正常に稼働しています', sshServiceRiskDesc: 'SSHサービスが未稼働または異常です', sshPortNormalDesc: 'SSHポートがデフォルトポートから変更済みです', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index bc765de0863f..c146048cd357 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -3718,6 +3718,10 @@ const message = { bindHelper: '바인딩 - 방화벽 규칙은 상태가 바인딩된 경우에만 효과가 있습니다. 확인하시겠습니까?', unbindHelper: '바인딩 해제 - 바인딩 해제 시 추가된 모든 방화벽 규칙이 무효화됩니다. 주의하여 진행하세요. 확인하시겠습니까?', + whiteList: '화이트리스트', + portWhiteList: '포트 화이트리스트', + portWhiteListAlter: '방화벽을 초기화하거나 시작할 때 화이트리스트의 포트가 자동으로 허용됩니다.', + portWhiteListHelper: '80/tcp 또는 443/udp처럼 프로토콜을 지정할 수 있습니다. 생략하면 기본값은 tcp입니다.', defaultStrategy: '현재 체인 {0}의 기본 정책은 {1}입니다', defaultStrategy2: '현재 체인 {0}의 기본 정책은 {1}입니다. 현재 상태는 바인딩되지 않았습니다. 추가된 방화벽 규칙은 바인딩 후에 효과가 발생합니다!', @@ -3952,8 +3956,7 @@ const message = { reportDate: '보고서 날짜', serverSecurityOverview: '서버 보안 운영 개요', securityScore: '보안 점수', - overviewSummary: - '현재 보안 등급: {0}. 총 감점 {1}점, {2}개 위험 항목 발견, {3}개 검사 대상 포함.', + overviewSummary: '현재 보안 등급: {0}. 총 감점 {1}점, {2}개 위험 항목 발견, {3}개 검사 대상 포함.', riskDistribution: '위험 분포', totalDeducted: '총 감점', noRiskDeducted: '미감점', @@ -4092,8 +4095,7 @@ const message = { recent24Hours: '최근 24시간', currentService: '현재 서비스', riskItemsExist: '{0}개 위험 항목 존재', - loginHealthRiskDesc: - '{0}개의 위험 설정이 감지되었습니다. 로그인 보안을 강화하여 침입 위험을 낮추세요.', + loginHealthRiskDesc: '{0}개의 위험 설정이 감지되었습니다. 로그인 보안을 강화하여 침입 위험을 낮추세요.', loginHealthNormalDesc: '현재 로그인 및 SSH 보안 설정이 정상 상태입니다', loginHealthNormalReason: '로그인 보안 설정 정상', securityEntranceConfiguredDesc: '보안 입구가 구성되어 기본 입구 노출 위험이 감소됩니다', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 7cf8ff96a870..e38fbc2414f3 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -3857,6 +3857,12 @@ const message = { bindHelper: 'Ikat - Peraturan firewall hanya akan berkuat kuasa apabila status terikat. Sahkan?', unbindHelper: 'Nyahikat - Apabila tidak terikat, semua peraturan firewall yang ditambah akan menjadi tidak sah. Teruskan dengan berhati-hati. Sahkan?', + whiteList: 'Senarai putih', + portWhiteList: 'Senarai putih port', + portWhiteListAlter: + 'Port dalam senarai putih akan dibuka secara automatik apabila firewall dimulakan atau dihidupkan.', + portWhiteListHelper: + 'Protokol boleh ditentukan, contohnya 80/tcp atau 443/udp. Jika diabaikan, tcp digunakan secara lalai.', defaultStrategy: 'Dasar lalai untuk rantaian semasa {0} adalah {1}', defaultStrategy2: 'Dasar lalai untuk rantaian semasa {0} adalah {1}, status semasa adalah tidak terikat. Peraturan firewall yang ditambah akan berkuat kuasa selepas pengikatan!', @@ -4239,8 +4245,10 @@ const message = { '{0} konfigurasi berisiko dikesan. Kukuhkan keselamatan log masuk untuk mengurangkan risiko pencerobohan.', loginHealthNormalDesc: 'Konfigurasi keselamatan log masuk dan SSH semasa adalah normal', loginHealthNormalReason: 'Keselamatan log masuk adalah normal', - securityEntranceConfiguredDesc: 'Pintu masuk keselamatan dikonfigurasi untuk mengurangkan pendedahan laluan lalai', - securityEntranceRiskDesc: 'Pintu masuk keselamatan tidak didayakan. Sembunyikan pintu masuk log masuk lalai', + securityEntranceConfiguredDesc: + 'Pintu masuk keselamatan dikonfigurasi untuk mengurangkan pendedahan laluan lalai', + securityEntranceRiskDesc: + 'Pintu masuk keselamatan tidak didayakan. Sembunyikan pintu masuk log masuk lalai', allowIPsRestrictedDesc: 'IP dibenarkan dihadkan untuk akses panel', allowIPsRiskDesc: 'IP akses tidak dihadkan. Konfigurasikan IP dibenarkan untuk persekitaran awam', bindDomainRestrictedDesc: 'Domain akses telah diikat', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 86225f2cc71a..9f862c3dda51 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -3993,6 +3993,12 @@ const message = { 'Vincular - As regras de firewall só entrarão em vigor quando o status estiver vinculado. Confirmar?', unbindHelper: 'Desvincular - Quando desvinculado, todas as regras de firewall adicionadas se tornarão inválidas. Prossiga com cautela. Confirmar?', + whiteList: 'Lista branca', + portWhiteList: 'Lista branca de portas', + portWhiteListAlter: + 'As portas na lista branca serão abertas automaticamente ao inicializar ou iniciar o firewall.', + portWhiteListHelper: + 'O protocolo pode ser especificado, por exemplo 80/tcp ou 443/udp. Se omitido, o padrão é tcp.', defaultStrategy: 'A política padrão para a cadeia atual {0} é {1}', defaultStrategy2: 'A política padrão para a cadeia atual {0} é {1}, o status atual é não vinculado. As regras de firewall adicionadas entrarão em vigor após a vinculação!', @@ -4378,7 +4384,8 @@ const message = { '{0} configurações de risco detectadas. Fortaleça a segurança de login para reduzir o risco de invasão.', loginHealthNormalDesc: 'As configurações atuais de login e segurança SSH estão normais', loginHealthNormalReason: 'Segurança de login está normal', - securityEntranceConfiguredDesc: 'Entrada de segurança configurada para reduzir a exposição da entrada padrão', + securityEntranceConfiguredDesc: + 'Entrada de segurança configurada para reduzir a exposição da entrada padrão', securityEntranceRiskDesc: 'Entrada de segurança desativada. Oculte a entrada de login padrão', allowIPsRestrictedDesc: 'IPs autorizados estão restritos para acesso ao painel', allowIPsRiskDesc: 'IPs de acesso sem restrição. Configure IPs autorizados para ambientes públicos', @@ -4445,7 +4452,8 @@ const message = { alertHealthAttention: 'Atenção necessária', alertHealthRisk: 'Alto risco', alertHealthSummary: 'Saúde do alerta', - alertHealthNormalReason: 'Tarefas de alerta, canais de notificação e registros de execução estão saudáveis', + alertHealthNormalReason: + 'Tarefas de alerta, canais de notificação e registros de execução estão saudáveis', alertNoChannelReason: 'Nenhum canal de notificação está ativado', alertFailedLogReason: '{0} registros de alerta com falha encontrados', alertPendingReason: '{0} registros de alerta pendentes de sincronização', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 9b690357fc3d..6f3d940b5a5b 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -3848,6 +3848,11 @@ const message = { bindHelper: 'Привязать - Правила брандмауэра вступят в силу только когда статус привязан. Подтвердить?', unbindHelper: 'Отвязать - При отвязке все добавленные правила брандмауэра станут недействительными. Действуйте осторожно. Подтвердить?', + whiteList: 'Белый список', + portWhiteList: 'Белый список портов', + portWhiteListAlter: + 'Порты из белого списка будут автоматически открыты при инициализации или запуске брандмауэра.', + portWhiteListHelper: 'Можно указать протокол, например 80/tcp или 443/udp. Если не указано, используется tcp.', defaultStrategy: 'Политика по умолчанию для текущей цепочки {0} - {1}', defaultStrategy2: 'Политика по умолчанию для текущей цепочки {0} - {1}, текущий статус - не привязан. Добавленные правила брандмауэра вступят в силу после привязки!', @@ -4230,7 +4235,8 @@ const message = { 'Обнаружено {0} рисковых настроек. Рекомендуется усилить безопасность входа для снижения риска вторжения.', loginHealthNormalDesc: 'Текущие настройки безопасности входа и SSH в норме', loginHealthNormalReason: 'Настройки безопасности входа в норме', - securityEntranceConfiguredDesc: 'Безопасный вход настроен, снижается риск раскрытия стандартной точки входа', + securityEntranceConfiguredDesc: + 'Безопасный вход настроен, снижается риск раскрытия стандартной точки входа', securityEntranceRiskDesc: 'Безопасный вход не включён. Рекомендуется скрыть стандартную точку входа', allowIPsRestrictedDesc: 'Доступ к панели ограничен по IP-адресам', allowIPsRiskDesc: 'Доступ по IP не ограничен. Для публичных сред рекомендуется настроить доверенные IP', @@ -4252,10 +4258,12 @@ const message = { passwordExpiration: 'Срок действия пароля', passwordExpirationNormalDesc: 'Срок действия пароля находится в безопасном диапазоне', passwordExpirationUnsetDesc: 'Срок действия пароля не задан, рекомендуется скорее настроить', - passwordExpirationRiskDesc: 'Срок действия пароля истекает через {0} дней, рекомендуется заблаговременно продлить', + passwordExpirationRiskDesc: + 'Срок действия пароля истекает через {0} дней, рекомендуется заблаговременно продлить', passwordExpirationExpiredDesc: 'Срок действия пароля истёк {0} дней назад, продлите как можно скорее', sessionTimeoutNormalDesc: 'Тайм-аут сессии находится в безопасном диапазоне', - sessionTimeoutRiskDesc: 'Тайм-аут сессии слишком велик. Рекомендуется ограничить срок неактивных сессий', + sessionTimeoutRiskDesc: + 'Тайм-аут сессии слишком велик. Рекомендуется ограничить срок неактивных сессий', sshServiceNormalDesc: 'Служба SSH работает нормально', sshServiceRiskDesc: 'Служба SSH не работает или находится в аномальном состоянии', sshPortNormalDesc: 'SSH-порт изменён с порта по умолчанию', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 373a3eaf6c59..8fbc22c042ce 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -3849,6 +3849,12 @@ const message = { bindHelper: 'Bağla - Güvenlik duvarı kuralları yalnızca durum bağlı olduğunda etkili olur. Onaylıyor musunuz?', unbindHelper: 'Bağlantıyı Kaldır - Bağlantı kaldırıldığında, eklenen tüm güvenlik duvarı kuralları geçersiz olacaktır. Dikkatli ilerleyin. Onaylıyor musunuz?', + whiteList: 'Beyaz liste', + portWhiteList: 'Port beyaz listesi', + portWhiteListAlter: + 'Beyaz listedeki portlar, güvenlik duvarı başlatılırken veya çalıştırılırken otomatik olarak açılır.', + portWhiteListHelper: + 'Protokol belirtilebilir, örn. 80/tcp veya 443/udp. Belirtilmezse varsayılan tcp kullanılır.', defaultStrategy: 'Mevcut zincir {0} için varsayılan politika {1}', defaultStrategy2: 'Mevcut zincir {0} için varsayılan politika {1}, mevcut durum bağlı değil. Eklenen güvenlik duvarı kuralları bağlandıktan sonra etkili olacak!', @@ -4113,7 +4119,7 @@ const message = { scoreSSHLoginFailedHigh: 'SSH girişi {0} kez başarısız oldu', scoreSSHLoginFailedMedium: 'SSH girişi {0} kez başarısız oldu', scoreMFADisabled: 'MFA devre dışı', - scoreAllowIPsOpen: 'İzin verilen IP\'ler ve bağlı alan adı yapılandırılmamış veya erişim kısıtlanmamış', + scoreAllowIPsOpen: "İzin verilen IP'ler ve bağlı alan adı yapılandırılmamış veya erişim kısıtlanmamış", scorePasswordExpired: 'Panel şifresi süresi dolmuş', scorePasswordExpiring: 'Panel şifresi {0} gün içinde sona eriyor', scorePanelHTTPSDisabled: 'Panel HTTPS devre dışı', @@ -4196,7 +4202,7 @@ const message = { notConfigured: 'Yapılandırılmamış', normal: 'Normal', needAttention: 'Dikkat Gerekli', - allowIPs: 'İzin Verilen IP\'ler', + allowIPs: "İzin Verilen IP'ler", restricted: 'Kısıtlanmış', unrestricted: 'Kısıtlanmamış', bindDomain: 'Bağlı Alan Adı', @@ -4231,22 +4237,22 @@ const message = { '{0} riskli yapılandırma algılandı. Saldırı riskini azaltmak için giriş güvenliğini güçlendirin.', loginHealthNormalDesc: 'Mevcut giriş ve SSH güvenlik yapılandırmaları normal durumda', loginHealthNormalReason: 'Giriş güvenliği normal', - securityEntranceConfiguredDesc: 'Güvenlik girişi yapılandırılmış, varsayılan giriş maruziyeti azaltılmış', + securityEntranceConfiguredDesc: + 'Güvenlik girişi yapılandırılmış, varsayılan giriş maruziyeti azaltılmış', securityEntranceRiskDesc: 'Güvenlik girişi devre dışı. Varsayılan giriş girişini gizleyin', - allowIPsRestrictedDesc: 'Panel erişimi için izin verilen IP\'ler kısıtlanmış', - allowIPsRiskDesc: 'Erişim IP\'leri kısıtlanmamış. Genel ortamlar için izin verilen IP\'leri yapılandırın', + allowIPsRestrictedDesc: "Panel erişimi için izin verilen IP'ler kısıtlanmış", + allowIPsRiskDesc: "Erişim IP'leri kısıtlanmamış. Genel ortamlar için izin verilen IP'leri yapılandırın", bindDomainRestrictedDesc: 'Erişim alan adı bağlanmış', bindDomainRiskDesc: 'Erişim alan adı bağlanmamış. Erişimi sabit bir alan adıyla kısıtlayın', - accessRestrictionValue: 'İzin verilen IP\'ler: {0} / Bağlı alan adı: {1}', + accessRestrictionValue: "İzin verilen IP'ler: {0} / Bağlı alan adı: {1}", accessRestrictionNormalDesc: - 'Panel erişim kaynaklarını kısıtlamak için izin verilen IP\'ler veya bağlı alan adı yapılandırılmış', + "Panel erişim kaynaklarını kısıtlamak için izin verilen IP'ler veya bağlı alan adı yapılandırılmış", accessRestrictionRiskDesc: - 'İzin verilen IP\'ler ve bağlı alan adı yapılandırılmamış veya erişim kısıtlanmamış. En az birini yapılandırın', + "İzin verilen IP'ler ve bağlı alan adı yapılandırılmamış veya erişim kısıtlanmamış. En az birini yapılandırın", panelHTTPSNormalDesc: 'Panel HTTPS etkin', panelHTTPSRiskDesc: 'Panel HTTPS devre dışı. Giriş trafiği açığa çıkabilir', passwordComplexityNormalDesc: 'Şifre karmaşıklık doğrulaması etkin', - passwordComplexityRiskDesc: - 'Şifre karmaşıklık doğrulaması devre dışı, zayıf şifre riski yüksek', + passwordComplexityRiskDesc: 'Şifre karmaşıklık doğrulaması devre dışı, zayıf şifre riski yüksek', sessionTimeoutNormalDesc: 'Oturum zaman aşımı güvenli aralıkta', sessionTimeoutRiskDesc: 'Oturum zaman aşımı uzun. Boş oturum geçerlilik süresini kısıtlayın', sshServiceNormalDesc: 'SSH servisi normal çalışıyor', @@ -4399,7 +4405,7 @@ const message = { '{0} risk öğesi algılandı. Web sitesi güvenliğini ve kullanılabilirliğini korumak için yakında ele alın.', websiteHealthNormalDesc: 'Mevcut web sitesi koruma metrikleri normal', handleSslRisk: 'Sertifika Risklerini Ele Al', - viewWaf: 'WAF\'ı Gör', + viewWaf: "WAF'ı Gör", priority: 'Öncelik', riskDescription: 'Risk Açıklaması', deductScore: 'Düşülen Puan', @@ -4514,14 +4520,14 @@ const message = { checkBackupTasks: 'Yedek Görevlerini Kontrol Et', generationRule: 'Oluşturma Kuralları', scheduleDaily: 'Günlük', - scheduleDailyDesc: 'Her gün 09:00\'da son 24 saatin raporunu oluştur', + scheduleDailyDesc: "Her gün 09:00'da son 24 saatin raporunu oluştur", scheduleWeekly: 'Haftalık', - scheduleWeeklyDesc: 'Her Pazartesi 09:00\'da son 7 günün raporunu oluştur', + scheduleWeeklyDesc: "Her Pazartesi 09:00'da son 7 günün raporunu oluştur", scheduleMonthly: 'Aylık', - scheduleMonthlyDesc: 'Her ayın 1\'inde 09:00\'da bir önceki ayın raporunu oluştur', - scheduleCurrentDaily: 'Her gün 09:00\'da son 24 saatin raporu oluşturulur · Sonraki {0}', - scheduleCurrentWeekly: 'Her Pazartesi 09:00\'da son 7 günün raporu oluşturulur · Sonraki {0}', - scheduleCurrentMonthly: 'Her ayın 1\'inde 09:00\'da bir önceki ayın raporu oluşturulur · Sonraki {0}', + scheduleMonthlyDesc: "Her ayın 1'inde 09:00'da bir önceki ayın raporunu oluştur", + scheduleCurrentDaily: "Her gün 09:00'da son 24 saatin raporu oluşturulur · Sonraki {0}", + scheduleCurrentWeekly: "Her Pazartesi 09:00'da son 7 günün raporu oluşturulur · Sonraki {0}", + scheduleCurrentMonthly: "Her ayın 1'inde 09:00'da bir önceki ayın raporu oluşturulur · Sonraki {0}", notificationMethod: 'Bildirim Yöntemleri', channel: 'Kanal', receiver: 'Alıcı', @@ -4542,7 +4548,7 @@ const message = { savePath: 'Kayıt Dizini', savePathRequired: 'Rapor kayıt dizinini ayarlayın', autoExport: 'Otomatik Dışa Aktarmayı Etkinleştir', - autoExportDesc: 'Etkinleştirildiğinde her gün 09:00\'da otomatik olarak operasyon raporu oluşturulur', + autoExportDesc: "Etkinleştirildiğinde her gün 09:00'da otomatik olarak operasyon raporu oluşturulur", autoExportEnabled: 'Otomatik dışa aktarma etkin', autoExportDisabled: 'Otomatik dışa aktarma devre dışı', readOnlyPermissionTip: diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 805454b7685e..3f1d5666d1d3 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -3506,6 +3506,10 @@ const message = { initHelper: '偵測到 {0} 未初始化,請點選頂部狀態列的初始化按鈕進行設定', bindHelper: '綁定 僅當狀態為綁定時,防火牆規則才能生效,是否確認?', unbindHelper: '解除綁定 解除綁定時,已新增的所有防火牆規則將失效,請謹慎操作,是否確認?', + whiteList: '白名單', + portWhiteList: '埠白名單', + portWhiteListAlter: '防火牆初始化或啟動時,將自動放行白名單埠', + portWhiteListHelper: '支援指定協定(如 80/tcp、443/udp),未指定時預設使用 tcp。', defaultStrategy: '目前鏈 {0} 的預設策略為 {1}', defaultStrategy2: '目前鏈 {0} 的預設策略為 {1},當前狀態為未綁定,已新增的防火牆規則需要綁定後生效', filterRule: 'Filter 規則', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 0f0fe845ae5d..f786015f8c04 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -3498,6 +3498,9 @@ const message = { initHelper: '检测到 {0} 未初始化,请点击顶部状态栏的初始化按钮进行配置!', bindHelper: '绑定 仅当状态为绑定时,防火墙规则才能生效,是否确认?', unbindHelper: '解绑 解除绑定时,已添加的所有防火墙规则将失效,请谨慎操作,是否确认?', + portWhiteList: '端口白名单', + portWhiteListAlter: '防火墙初始化或启动时,将自动放行白名单端口', + portWhiteListHelper: '支持指定协议(如 80/tcp、443/udp),未指定时默认使用 TCP。', defaultStrategy: '当前链 {0} 的默认策略为 {1}', defaultStrategy2: '当前链 {0} 的默认策略为 {1},当前状态为未绑定,已添加的防火墙规则需要绑定后生效!', filterRule: 'Filter 规则', diff --git a/frontend/src/views/host/firewall/port/index.vue b/frontend/src/views/host/firewall/port/index.vue index 77cd1070b0e4..3206ac1d0ac4 100644 --- a/frontend/src/views/host/firewall/port/index.vue +++ b/frontend/src/views/host/firewall/port/index.vue @@ -46,6 +46,9 @@ {{ $t('commons.button.create') }} + + {{ $t('firewall.portWhiteList') }} + {{ $t('commons.button.delete') }} @@ -158,6 +161,7 @@ + @@ -165,6 +169,7 @@ import FireRouter from '@/views/host/firewall/index.vue'; import OperateDialog from '@/views/host/firewall/port/operate/index.vue'; import ImportDialog from '@/views/host/firewall/port/import/index.vue'; +import WhiteList from '@/views/host/firewall/port/white-list/index.vue'; import FireStatus from '@/views/host/firewall/status/index.vue'; import ProcessDetail from '@/views/host/process/process/detail/index.vue'; import { onMounted, reactive, ref } from 'vue'; @@ -194,6 +199,7 @@ const fireStatusRef = ref(); const opRef = ref(); const dialogImportRef = ref(); const processDetailRef = ref(); +const whiteListRef = ref(); const listeningProcesses = ref([]); @@ -398,6 +404,10 @@ const onImport = () => { dialogImportRef.value.acceptParams(); }; +const onOpenWhiteList = () => { + whiteListRef.value.acceptParams(); +}; + const onExport = () => { ElMessageBox.confirm( i18n.global.t('firewall.exportHelper', [selects.value.length]), diff --git a/frontend/src/views/host/firewall/port/white-list/index.vue b/frontend/src/views/host/firewall/port/white-list/index.vue new file mode 100644 index 000000000000..f57db12f36b0 --- /dev/null +++ b/frontend/src/views/host/firewall/port/white-list/index.vue @@ -0,0 +1,180 @@ + + +