fix: allow updated SSH ports through firewall before restart (#13894)

This commit is contained in:
ssongliu authored and GitHub committed 2026-09-22 14:51:54 +08:00
1 parent f58e147636
commit c4a6791271
4 files changed
+46 -68

No files matched your search

+1 -40
View File
@@ -2,7 +2,6 @@ package service
import (
"context"
"encoding/json"
"errors"
"fmt"
"slices"
@@ -99,45 +98,7 @@ func (s *FirewallService) UpdatePanelPort(ctx context.Context, oldPort, port uin
if oldPort == port {
return nil
}
firewallWhitelistMu.Lock()
defer firewallWhitelistMu.Unlock()
entries, err := loadFirewallPortWhiteList()
if err != nil {
return err
}
panelPorts := make([]firewall.PortWhitelist, 0)
for index := range entries {
if entries[index].Type != firewall.PortWhitelistTypePanel {
continue
}
entries[index].Port = strconv.Itoa(int(port))
panelPorts = append(panelPorts, entries[index])
}
if len(panelPorts) == 0 {
panelPorts = append(panelPorts, firewall.PortWhitelist{
Type: firewall.PortWhitelistTypePanel, Port: strconv.Itoa(int(port)), Protocol: "tcp",
Sources: []string{"0.0.0.0/0", "::/0"},
})
entries = append(entries, panelPorts...)
}
entries, err = firewall.ValidatePortWhitelist(entries)
if err != nil {
return err
}
value, err := json.Marshal(entries)
if err != nil {
return err
}
client, err := s.baseClient()
if err != nil && !errors.Is(err, lifecycle.ErrNotInstalled) {
return err
}
if err == nil {
if _, err := s.syncPortWhitelist(ctx, filter.Provider(client.Name()), panelPorts); err != nil {
return err
}
}
return settingRepo.UpdateOrCreate(constant.FirewallPortWhiteList, string(value))
return s.updateSystemAccessPortWhitelist(ctx, firewall.PortWhitelistTypePanel, []string{strconv.Itoa(int(port))})
}
func (s *FirewallService) LoadBaseInfo(chainGroup string) (dto.FirewallSubsystemStatus, error) {
+43 -26
View File
@@ -371,39 +371,56 @@ func (s *FirewallService) syncPortWhitelist(ctx context.Context, provider filter
return created, errors.Join(failures...)
}
func updateSystemAccessPortWhitelist(ctx context.Context, serviceType string, ports []string) error {
func (s *FirewallService) updateSystemAccessPortWhitelist(ctx context.Context, serviceType string, ports []string) error {
if len(ports) == 0 {
return fmt.Errorf("firewall whitelist %s requires a port", serviceType)
}
firewallWhitelistMu.Lock()
defer firewallWhitelistMu.Unlock()
firewallRuleMutationMu.Lock()
defer firewallRuleMutationMu.Unlock()
return global.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
entries, err := loadPortWhitelistSetting(tx)
if err != nil {
return err
entries, err := loadFirewallPortWhiteList()
if err != nil {
return err
}
servicePorts := make([]firewall.PortWhitelist, 0)
for index := range entries {
if entries[index].Type != serviceType {
continue
}
for index := range entries {
if entries[index].Type != serviceType {
continue
entries[index].Port = ports[0]
servicePorts = append(servicePorts, entries[index])
}
if len(servicePorts) == 0 {
servicePorts = append(servicePorts, firewall.PortWhitelist{
Type: serviceType, Port: ports[0], Protocol: "tcp",
Sources: []string{"0.0.0.0/0", "::/0"},
})
entries = append(entries, servicePorts...)
}
entries, err = firewall.ValidatePortWhitelist(entries)
if err != nil {
return err
}
value, err := json.Marshal(entries)
if err != nil {
return err
}
client, err := s.baseClient()
if err != nil && !errors.Is(err, lifecycle.ErrNotInstalled) {
return err
}
if err == nil {
allowances := make([]firewall.PortWhitelist, 0, len(servicePorts)*len(ports))
for _, rule := range servicePorts {
for _, port := range ports {
rule.Port = port
allowances = append(allowances, rule)
}
if len(ports) == 0 {
return fmt.Errorf("firewall whitelist %s requires a port", serviceType)
}
entries[index].Port = ports[0]
}
entries, err = firewall.ValidatePortWhitelist(entries)
if err != nil {
if _, err := s.syncPortWhitelist(ctx, filter.Provider(client.Name()), allowances); err != nil {
return err
}
value, err := json.Marshal(entries)
if err != nil {
return err
}
err = tx.Where("key = ?", constant.FirewallPortWhiteList).Assign(map[string]interface{}{"value": string(value)}).FirstOrCreate(&model.Setting{Key: constant.FirewallPortWhiteList}).Error
if err != nil {
return err
}
return nil
})
}
return settingRepo.UpdateOrCreate(constant.FirewallPortWhiteList, string(value))
}
func loadPortWhitelistSetting(db *gorm.DB) ([]firewall.PortWhitelist, error) {
+1 -1
View File
@@ -228,7 +228,7 @@ func (u *SSHService) Update(req dto.SSHUpdate) error {
return err
}
if req.Key == "Port" {
if err := updateSystemAccessPortWhitelist(context.Background(), firewall.PortWhitelistTypeSSH, splitSSHPorts(req.NewValue)); err != nil {
if err := newFirewallService().updateSystemAccessPortWhitelist(context.Background(), firewall.PortWhitelistTypeSSH, splitSSHPorts(req.NewValue)); err != nil {
if restoreErr := rewriteSSHManagedDirectives(sshPath, "Port", buildSSHDirectiveLines("Port", oldPortValue)); restoreErr != nil {
return fmt.Errorf("save SSH whitelist: %w; restore SSH configuration: %v", err, restoreErr)
}
+1 -1
View File
@@ -19,7 +19,7 @@ import (
const (
pingInterval = 30 * time.Second
pongWait = 75 * time.Second
writeWait = 5 * time.Second
writeWait = 30 * time.Second
)
var errAttachmentClosed = errors.New("terminal attachment is closed")