diff --git a/agent/app/dto/firewall.go b/agent/app/dto/firewall.go index d819733d2..a5150b521 100644 --- a/agent/app/dto/firewall.go +++ b/agent/app/dto/firewall.go @@ -26,6 +26,7 @@ type FirewallOperation struct { type PortRuleOperate struct { ID uint `json:"id"` Operation string `json:"operation" validate:"required,oneof=add remove"` + Chain string `json:"chain"` Address string `json:"address"` Port string `json:"port" validate:"required"` Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"` @@ -89,7 +90,7 @@ type IptablesOp struct { type IptablesRuleOp struct { Operation string `json:"operation" validate:"required,oneof=add remove"` ID uint `json:"id"` - Chain string `json:"chain" validate:"required,oneof=1PANEL_INPUT 1PANEL_OUTPUT"` + Chain string `json:"chain" validate:"required,oneof=1PANEL_BASIC 1PANEL_BASIC_BEFORE 1PANEL_INPUT 1PANEL_OUTPUT"` Protocol string `json:"protocol"` SrcIP string `json:"srcIP"` SrcPort uint `json:"srcPort"` diff --git a/agent/app/service/firewall.go b/agent/app/service/firewall.go index 643e9d2bb..a47cb8f1f 100644 --- a/agent/app/service/firewall.go +++ b/agent/app/service/firewall.go @@ -232,9 +232,8 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) if err != nil { return err } - chain := "" - if client.Name() == "iptables" { - chain = iptables.Chain1PanelBasic + if len(req.Chain) == 0 && client.Name() == "iptables" { + req.Chain = iptables.Chain1PanelBasic } protos := strings.Split(req.Protocol, "/") itemAddress := strings.Split(strings.TrimSuffix(req.Address, ","), ",") @@ -253,7 +252,7 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) return err } req.Port = strings.ReplaceAll(req.Port, ":", "-") - if err := u.addPortRecord(chain, req); err != nil { + if err := u.addPortRecord(req); err != nil { return err } } @@ -274,7 +273,7 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) if len(req.Protocol) == 0 { req.Protocol = "tcp/udp" } - if err := u.addPortRecord(chain, req); err != nil { + if err := u.addPortRecord(req); err != nil { return err } } @@ -290,7 +289,7 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) if err := u.operatePort(client, req); err != nil { return err } - if err := u.addPortRecord(chain, req); err != nil { + if err := u.addPortRecord(req); err != nil { return err } } @@ -307,7 +306,7 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) if err := u.operatePort(client, req); err != nil { return err } - if err := u.addPortRecord(chain, req); err != nil { + if err := u.addPortRecord(req); err != nil { return err } } @@ -707,7 +706,7 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er } } } - if err := client.Port(fireClient.FireInfo{Port: "22", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil { + 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 { @@ -720,7 +719,7 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er return client.Reload() } -func (u *FirewallService) addPortRecord(chain string, req dto.PortRuleOperate) error { +func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error { if req.Operation == "remove" { if req.ID != 0 { return hostRepo.DeleteFirewallRecordByID(req.ID) @@ -729,7 +728,7 @@ func (u *FirewallService) addPortRecord(chain string, req dto.PortRuleOperate) e if err := hostRepo.SaveFirewallRecord(&model.Firewall{ Type: "port", - Chain: chain, + Chain: req.Chain, DstPort: req.Port, Protocol: req.Protocol, SrcIP: req.Address, @@ -821,7 +820,7 @@ func checkPortUsed(ports, proto string, apps []portOfApp) string { } func loadInitStatus(clientName, tab string) (bool, bool) { - if clientName != "iptables" && tab != "forward" { + if clientName != "firewalld" || (clientName != "iptables" && tab != "forward") { return true, true } switch tab { diff --git a/agent/app/service/iptables.go b/agent/app/service/iptables.go index f1ee7fdff..bdd04ce8f 100644 --- a/agent/app/service/iptables.go +++ b/agent/app/service/iptables.go @@ -310,11 +310,11 @@ func initPreRules() error { if len(panelPort) == 0 { return errors.New("find 1panel service port failed") } - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.AllowSSH); err != nil { - return err - } - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %s -j ACCEPT", panelPort)); err != nil { - return err + ports := []string{"80", "443", panelPort, loadSSHPort()} + for _, item := range ports { + if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", item)); err != nil { + return err + } } if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAll); err != nil { return err diff --git a/agent/app/service/ssh.go b/agent/app/service/ssh.go index 7a10de178..a4e74378b 100644 --- a/agent/app/service/ssh.go +++ b/agent/app/service/ssh.go @@ -887,3 +887,22 @@ func updateSSHSocketFile(newPort string) error { _ = controller.HandleRestart("ssh.socket") return nil } + +func loadSSHPort() string { + port := "22" + sshConf, err := os.ReadFile(sshPath) + if err != nil { + return port + } + lines := strings.Split(string(sshConf), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "Port ") { + portStr := strings.ReplaceAll(line, "Port ", "") + portItem, _ := strconv.Atoi(portStr) + if portItem > 0 && portItem < 65535 { + return portStr + } + } + } + return port +} diff --git a/agent/init/firewall/firwall.go b/agent/init/firewall/firwall.go index 59981b6ea..e1d1ab9e9 100644 --- a/agent/init/firewall/firwall.go +++ b/agent/init/firewall/firwall.go @@ -3,7 +3,6 @@ package firewall import ( "github.com/1Panel-dev/1Panel/agent/utils/firewall" "github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables" - "github.com/1Panel-dev/1Panel/agent/utils/re" ) func Init() { @@ -11,8 +10,6 @@ func Init() { if err != nil { return } - re.RegisterRegex(iptables.Chian1PanelBasicPortPattern) - re.RegisterRegex(iptables.Chain1PanelBasicAddressPattern) clientName := client.Name() if clientName == "ufw" || clientName == "iptables" { _ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName) diff --git a/agent/utils/firewall/client/info.go b/agent/utils/firewall/client/info.go index 76069b8c5..dff1ac181 100644 --- a/agent/utils/firewall/client/info.go +++ b/agent/utils/firewall/client/info.go @@ -1,7 +1,8 @@ package client type FireInfo struct { - ID uint `json:"uint"` + ID uint `json:"id"` + Chain string `json:"chain"` Family string `json:"family"` // ipv4 ipv6 Address string `json:"address"` // Anywhere Port string `json:"port"` diff --git a/agent/utils/firewall/client/iptables.go b/agent/utils/firewall/client/iptables.go index a2e7b8298..807c0fee2 100644 --- a/agent/utils/firewall/client/iptables.go +++ b/agent/utils/firewall/client/iptables.go @@ -9,7 +9,6 @@ import ( "github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables" - "github.com/1Panel-dev/1Panel/agent/utils/re" ) type Iptables struct{} @@ -59,91 +58,52 @@ func (i *Iptables) Version() (string, error) { } func (i *Iptables) ListPort() ([]FireInfo, error) { - stdout, err := iptables.RunWithStd(iptables.FilterTab, fmt.Sprintf("-S %s", iptables.Chain1PanelBasic)) - if err != nil { - return nil, fmt.Errorf("failed to list 1PANEL_BASIC rules: %w", err) - } - var datas []FireInfo - lines := strings.Split(stdout, "\n") - - chainPortRegex := re.GetRegex(iptables.Chian1PanelBasicPortPattern) - for _, line := range lines { - line = strings.TrimSpace(line) - if !strings.HasPrefix(line, fmt.Sprintf("-A %s", iptables.Chain1PanelBasic)) { + basicRules, err := iptables.ReadFilterRulesByChain(iptables.Chain1PanelBasic) + if err != nil { + return nil, err + } + beforeRules, _ := iptables.ReadFilterRulesByChain(iptables.Chain1PanelBasicBefore) + basicRules = append(basicRules, beforeRules...) + for _, item := range basicRules { + if item.DstPort == 0 { continue } - - if matches := chainPortRegex.FindStringSubmatch(line); len(matches) == 5 { - address := matches[1] - protocol := matches[2] - port := strings.ReplaceAll(matches[3], ":", "-") - action := strings.ToLower(matches[4]) - - strategy := "accept" - if action == "drop" || action == "reject" { - strategy = "drop" - } - - datas = append(datas, FireInfo{ - Address: address, - Protocol: protocol, - Port: port, - Strategy: strategy, - Family: "ipv4", - }) + if item.Strategy == "drop" || item.Strategy == "reject" { + item.Strategy = "drop" } + datas = append(datas, FireInfo{ + Chain: item.Chain, + Address: item.SrcIP, + Protocol: item.Protocol, + Port: fmt.Sprintf("%v", item.DstPort), + Strategy: item.Strategy, + Family: "ipv4", + }) } return datas, nil } func (i *Iptables) ListAddress() ([]FireInfo, error) { - stdout, err := iptables.RunWithStd(iptables.FilterTab, fmt.Sprintf("-S %s", iptables.Chain1PanelBasic)) - if err != nil { - return nil, fmt.Errorf("failed to list 1PANEL_BASIC address rules: %w", err) - } - var datas []FireInfo - lines := strings.Split(stdout, "\n") - addressMap := make(map[string]FireInfo) - - chainAddressRegex := re.GetRegex(iptables.Chain1PanelBasicAddressPattern) - for _, line := range lines { - line = strings.TrimSpace(line) - if !strings.HasPrefix(line, fmt.Sprintf("-A %s", iptables.Chain1PanelBasic)) { + basicRules, err := iptables.ReadFilterRulesByChain(iptables.Chain1PanelBasic) + if err != nil { + return nil, err + } + for _, item := range basicRules { + if item.DstPort != 0 || item.SrcPort != 0 { continue } - - if matches := chainAddressRegex.FindStringSubmatch(line); len(matches) >= 4 { - address := matches[1] - if address == "" { - address = matches[2] - } - if address == "" { - continue - } - action := strings.ToLower(matches[3]) - - strategy := "accept" - if action == "drop" || action == "reject" { - strategy = "drop" - } - - if _, exists := addressMap[address]; !exists { - addressMap[address] = FireInfo{ - Address: address, - Strategy: strategy, - Family: "ipv4", - } - } + if item.Strategy == "drop" || item.Strategy == "reject" { + item.Strategy = "drop" } + datas = append(datas, FireInfo{ + Address: item.SrcIP, + Strategy: item.Strategy, + Family: "ipv4", + }) } - - for _, info := range addressMap { - datas = append(datas, info) - } - return datas, nil } @@ -151,6 +111,9 @@ func (i *Iptables) Port(port FireInfo, operation string) error { if operation != "add" && operation != "remove" { return buserr.New("ErrCmdIllegal") } + if len(port.Chain) == 0 { + port.Chain = iptables.Chain1PanelBasic + } portSpec, err := normalizePortSpec(port.Port) if err != nil { @@ -174,17 +137,19 @@ func (i *Iptables) Port(port FireInfo, operation string) error { ruleArgs = append(ruleArgs, fmt.Sprintf("--dport %s", portSpec), fmt.Sprintf("-j %s", action)) ruleSpec := strings.Join(ruleArgs, " ") if operation == "add" { - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasic, ruleSpec); err != nil { + if err := iptables.AddRule(iptables.FilterTab, port.Chain, ruleSpec); err != nil { return err } } else { - if err := iptables.DeleteRule(iptables.FilterTab, iptables.Chain1PanelBasic, ruleSpec); err != nil { + if err := iptables.DeleteRule(iptables.FilterTab, port.Chain, ruleSpec); err != nil { return err } } - if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil { - global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err) + if port.Chain == iptables.Chain1PanelBasic { + if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil { + global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err) + } } return nil } @@ -193,6 +158,9 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error { if operation != "add" && operation != "remove" { return buserr.New("ErrCmdIllegal") } + if len(rule.Chain) == 0 { + rule.Chain = iptables.Chain1PanelBasic + } address := strings.TrimSpace(rule.Address) if strings.EqualFold(address, "Anywhere") { @@ -235,17 +203,19 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error { ruleArgs = append(ruleArgs, fmt.Sprintf("-j %s", action)) ruleSpec := strings.Join(ruleArgs, " ") if operation == "add" { - if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasic, ruleSpec); err != nil { + if err := iptables.AddRule(iptables.FilterTab, rule.Chain, ruleSpec); err != nil { return err } } else { - if err := iptables.DeleteRule(iptables.FilterTab, iptables.Chain1PanelBasic, ruleSpec); err != nil { + if err := iptables.DeleteRule(iptables.FilterTab, rule.Chain, ruleSpec); err != nil { return err } } - if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil { - global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err) + if rule.Chain == iptables.Chain1PanelBasic { + if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil { + global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err) + } } return nil } diff --git a/agent/utils/firewall/client/iptables/common.go b/agent/utils/firewall/client/iptables/common.go index f932ea1a1..ec9840f6f 100644 --- a/agent/utils/firewall/client/iptables/common.go +++ b/agent/utils/firewall/client/iptables/common.go @@ -42,11 +42,6 @@ const ( NatTab = "nat" ) -var ( - Chain1PanelBasicAddressPattern = fmt.Sprintf(`-A\s+%s\s+(?:-s\s+(\S+)|(?:-d\s+(\S+)))?\s+-j\s+(\w+)`, Chain1PanelBasic) - Chian1PanelBasicPortPattern = fmt.Sprintf(`-A\s+%s\s+(?:-s\s+(\S+)\s+)?-p\s+(\w+)(?:\s+-m\s+\w+)*\s+--dport\s+(\d+(?::\d+)?)\s+-j\s+(\w+)`, Chain1PanelBasic) -) - func RunWithStd(tab, rule string) (string, error) { cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(20*time.Second)) stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -t %s %s", cmd.SudoHandleCmd(), tab, rule) @@ -56,7 +51,7 @@ func RunWithStd(tab, rule string) (string, error) { } return stdout, nil } -func RunWithoutIgnrore(tab, rule string) (string, error) { +func RunWithoutIgnore(tab, rule string) (string, error) { cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(20 * time.Second)) stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -t %s %s", cmd.SudoHandleCmd(), tab, rule) if err != nil { @@ -112,7 +107,7 @@ func CheckChainBind(tab, parentChain, chain string) (bool, error) { return true, nil } func CheckRuleExist(tab, chain, rule string) bool { - _, err := RunWithoutIgnrore(tab, fmt.Sprintf("-C %s %s", chain, rule)) + _, err := RunWithoutIgnore(tab, fmt.Sprintf("-C %s %s", chain, rule)) return err == nil } diff --git a/agent/utils/firewall/client/iptables/filter.go b/agent/utils/firewall/client/iptables/filter.go index 60efbd323..bf258a3e3 100644 --- a/agent/utils/firewall/client/iptables/filter.go +++ b/agent/utils/firewall/client/iptables/filter.go @@ -11,6 +11,7 @@ import ( type FilterRules struct { ID uint `json:"id"` + Chain string `json:"chain"` Protocol string `json:"protocol"` SrcPort uint `json:"srcPort"` DstPort uint `json:"dstPort"` @@ -70,23 +71,28 @@ func DeleteFilterRule(chain string, policy FilterRules) error { func ReadFilterRulesByChain(chain string) ([]FilterRules, error) { var rules []FilterRules cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(20*time.Second)) - stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -t %s -L %s", cmd.SudoHandleCmd(), FilterTab, chain) + stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -w -t %s -nL %s", cmd.SudoHandleCmd(), FilterTab, chain) if err != nil { return rules, fmt.Errorf("load filter fules by chain %s failed, %v", chain, err) } lines := strings.Split(stdout, "\n") for i := 0; i < len(lines); i++ { fields := strings.Fields(lines[i]) - if len(fields) < 7 { + if len(fields) < 5 { + continue + } + strategy := strings.ToLower(fields[0]) + if strategy != "accept" && strategy != "drop" && strategy != "reject" { continue } itemRule := FilterRules{ + Chain: chain, Protocol: fields[1], - SrcPort: loadPort("src", fields[6]), - DstPort: loadPort("dst", fields[6]), + SrcPort: loadPort("src", fields), + DstPort: loadPort("dst", fields), SrcIP: loadIP(fields[3]), DstIP: loadIP(fields[4]), - Strategy: fields[0], + Strategy: strategy, } rules = append(rules, itemRule) } @@ -95,7 +101,7 @@ func ReadFilterRulesByChain(chain string) ([]FilterRules, error) { func LoadDefaultStrategy(chain string) (string, error) { cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1(), cmd.WithTimeout(20*time.Second)) - stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -t %s -L %s", cmd.SudoHandleCmd(), FilterTab, chain) + stdout, err := cmdMgr.RunWithStdoutBashCf("%s iptables -w -t %s -L %s", cmd.SudoHandleCmd(), FilterTab, chain) if err != nil { return "", fmt.Errorf("load filter fules by chain %s failed, %v", chain, err) } @@ -112,13 +118,17 @@ func LoadDefaultStrategy(chain string) (string, error) { return ACCEPT, nil } -func loadPort(position, portStr string) uint { - var portItem string - if strings.Contains(portStr, "spt:") && position == "src" { - portItem = strings.ReplaceAll(portStr, "spt:", "") +func loadPort(position string, portStr []string) uint { + if len(portStr) < 7 { + return 0 } - if strings.Contains(portStr, "dpt:") && position == "dst" { - portItem = strings.ReplaceAll(portStr, "dpt:", "") + + var portItem string + if strings.Contains(portStr[6], "spt:") && position == "src" { + portItem = strings.ReplaceAll(portStr[6], "spt:", "") + } + if strings.Contains(portStr[6], "dpt:") && position == "dst" { + portItem = strings.ReplaceAll(portStr[6], "dpt:", "") } if len(portItem) == 0 { return 0 diff --git a/frontend/src/components/license-import/index.vue b/frontend/src/components/license-import/index.vue index f8efad712..ffa9e40ff 100644 --- a/frontend/src/components/license-import/index.vue +++ b/frontend/src/components/license-import/index.vue @@ -90,7 +90,7 @@ const acceptParams = (params: DialogProps) => { uploaderFiles.value = []; uploadRef.value?.clearFiles(); isImport.value = params?.isImport; - withoutReload.value = params.withoutReload; + withoutReload.value = params?.withoutReload; open.value = true; }; diff --git a/frontend/src/views/host/firewall/ip/index.vue b/frontend/src/views/host/firewall/ip/index.vue index bf94b4377..45e9cd975 100644 --- a/frontend/src/views/host/firewall/ip/index.vue +++ b/frontend/src/views/host/firewall/ip/index.vue @@ -5,7 +5,7 @@