mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-17 21:08:25 +08:00
fix: Fix the issue of abnormal iptables rule persistence (#11056)
Refs #11027
This commit is contained in:
parent
9d73d74c63
commit
496c0b50b4
5 changed files with 139 additions and 53 deletions
|
|
@ -269,7 +269,7 @@ func (b *BaseApi) OperateFilterRule(c *gin.Context) {
|
|||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := iptablesService.OperateRule(req); err != nil {
|
||||
if err := iptablesService.OperateRule(req, true); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
type IIptablesService interface {
|
||||
Search(req dto.SearchPageWithType) (int64, interface{}, error)
|
||||
OperateRule(req dto.IptablesRuleOp) error
|
||||
OperateRule(req dto.IptablesRuleOp, withSave bool) error
|
||||
BatchOperate(req dto.IptablesBatchOperate) error
|
||||
LoadChainStatus(req dto.OperationWithName) dto.IptablesChainStatus
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ func (s *IptablesService) Search(req dto.SearchPageWithType) (int64, interface{}
|
|||
return int64(total), records, nil
|
||||
}
|
||||
|
||||
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
|
||||
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp, withSave bool) error {
|
||||
action := "ACCEPT"
|
||||
if req.Strategy == "drop" {
|
||||
action = "DROP"
|
||||
|
|
@ -122,6 +122,9 @@ func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
|
|||
}
|
||||
}
|
||||
|
||||
if !withSave {
|
||||
return nil
|
||||
}
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, req.Chain, name); err != nil {
|
||||
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
|
||||
}
|
||||
|
|
@ -129,11 +132,23 @@ func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
|
|||
}
|
||||
|
||||
func (s *IptablesService) BatchOperate(req dto.IptablesBatchOperate) error {
|
||||
if len(req.Rules) == 0 {
|
||||
return errors.New("no rules to operate")
|
||||
}
|
||||
for _, rule := range req.Rules {
|
||||
if err := s.OperateRule(rule); err != nil {
|
||||
if err := s.OperateRule(rule, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
chain := iptables.Chain1PanelInput
|
||||
fileName := iptables.InputFileName
|
||||
if req.Rules[0].Chain == iptables.Chain1PanelOutput {
|
||||
chain = iptables.Chain1PanelOutput
|
||||
fileName = iptables.OutputFileName
|
||||
}
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, chain, fileName); err != nil {
|
||||
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +183,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
|
||||
}
|
||||
return nil
|
||||
case "init-forward":
|
||||
return client.EnableIptablesForward()
|
||||
|
|
@ -310,16 +331,7 @@ func initPreRules() error {
|
|||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); err != nil {
|
||||
return err
|
||||
}
|
||||
panelPort := ""
|
||||
if !global.IsMaster {
|
||||
panelPort = global.CONF.Base.Port
|
||||
} else {
|
||||
var portSetting model.Setting
|
||||
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
|
||||
if len(portSetting.Value) != 0 {
|
||||
panelPort = portSetting.Value
|
||||
}
|
||||
}
|
||||
panelPort := LoadPanelPort()
|
||||
if len(panelPort) == 0 {
|
||||
return errors.New("find 1panel service port failed")
|
||||
}
|
||||
|
|
@ -337,3 +349,16 @@ func initPreRules() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadPanelPort() string {
|
||||
if !global.IsMaster {
|
||||
return global.CONF.Base.Port
|
||||
} else {
|
||||
var portSetting model.Setting
|
||||
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
|
||||
if len(portSetting.Value) != 0 {
|
||||
return portSetting.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
package firewall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/service"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
|
||||
)
|
||||
|
|
@ -12,13 +17,73 @@ func Init() {
|
|||
}
|
||||
clientName := client.Name()
|
||||
if clientName == "ufw" || clientName == "iptables" {
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName)
|
||||
_ = iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPreRouting, iptables.ForwardFileName1)
|
||||
_ = iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPostRouting, iptables.ForwardFileName2)
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName); err != nil {
|
||||
global.LOG.Errorf("load forward rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPreRouting, iptables.ForwardFileName1); err != nil {
|
||||
global.LOG.Errorf("load prerouting rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPostRouting, iptables.ForwardFileName2); err != nil {
|
||||
global.LOG.Errorf("load postrouting rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("loaded iptables rules for forward from file successfully")
|
||||
}
|
||||
if clientName == "ufw" {
|
||||
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter)
|
||||
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore)
|
||||
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic)
|
||||
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput)
|
||||
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainOutput, iptables.Chain1PanelOutput)
|
||||
}
|
||||
if clientName == "iptables" {
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName)
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName)
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName)
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
|
||||
global.LOG.Errorf("load basic before rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
|
||||
global.LOG.Errorf("load basic rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
|
||||
global.LOG.Errorf("load basic after rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName); err != nil {
|
||||
global.LOG.Errorf("load input rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName); err != nil {
|
||||
global.LOG.Errorf("load output rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("loaded iptables rules for basic, input and output from file successfully")
|
||||
|
||||
panelPort := service.LoadPanelPort()
|
||||
if len(panelPort) == 0 {
|
||||
global.LOG.Errorf("find 1panel service port failed")
|
||||
return
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", panelPort)); err != nil {
|
||||
global.LOG.Errorf("add port accept rule %v failed, err: %v", panelPort, err)
|
||||
return
|
||||
}
|
||||
|
||||
iptablesService := service.IptablesService{}
|
||||
if err := iptablesService.Operate(dto.IptablesOp{Operate: "bind-base"}); err != nil {
|
||||
global.LOG.Errorf("bind base chains failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelOutput, Operate: "bind"}); err != nil {
|
||||
global.LOG.Errorf("bind output chains failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelInput, Operate: "bind"}); err != nil {
|
||||
global.LOG.Errorf("bind input chains failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,8 +144,12 @@ func (i *Iptables) Port(port FireInfo, operation string) error {
|
|||
}
|
||||
}
|
||||
|
||||
name := iptables.BasicFileName
|
||||
if port.Chain == iptables.Chain1PanelBasicBefore {
|
||||
name = iptables.BasicBeforeFileName
|
||||
}
|
||||
if port.Chain == iptables.Chain1PanelBasic {
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, port.Chain, name); err != nil {
|
||||
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -207,8 +211,12 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error {
|
|||
}
|
||||
}
|
||||
|
||||
name := iptables.BasicFileName
|
||||
if rule.Chain == iptables.Chain1PanelBasicBefore {
|
||||
name = iptables.BasicBeforeFileName
|
||||
}
|
||||
if rule.Chain == iptables.Chain1PanelBasic {
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, rule.Chain, name); err != nil {
|
||||
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,14 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
BasicFileName = "1panel_basic.rules"
|
||||
InputFileName = "1panel_input.rules"
|
||||
OutputFileName = "1panel_out.rules"
|
||||
ForwardFileName = "1panel_forward.rules"
|
||||
ForwardFileName1 = "1panel_forward_pre.rules"
|
||||
ForwardFileName2 = "1panel_forward_post.rules"
|
||||
BasicBeforeFileName = "1panel_basic_before.rules"
|
||||
BasicFileName = "1panel_basic.rules"
|
||||
BasicAfterFileName = "1panel_basic_after.rules"
|
||||
InputFileName = "1panel_input.rules"
|
||||
OutputFileName = "1panel_out.rules"
|
||||
ForwardFileName = "1panel_forward.rules"
|
||||
ForwardFileName1 = "1panel_forward_pre.rules"
|
||||
ForwardFileName2 = "1panel_forward_post.rules"
|
||||
)
|
||||
|
||||
func SaveRulesToFile(tab, chain, fileName string) error {
|
||||
|
|
@ -63,39 +65,25 @@ func LoadRulesFromFile(tab, chain, fileName string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Open(rulesFile)
|
||||
if err := AddChain(tab, chain); err != nil {
|
||||
global.LOG.Errorf("create chain %s failed: %v", chain, err)
|
||||
return err
|
||||
}
|
||||
data, err := os.ReadFile(rulesFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open rules file: %w", err)
|
||||
global.LOG.Errorf("read rules from file %s failed, err: %v", rulesFile, err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var rules []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
rules = append(rules, line)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return fmt.Errorf("failed to read rules file: %w", err)
|
||||
}
|
||||
|
||||
rules := strings.Split(string(data), "\n")
|
||||
if err := ClearChain(tab, chain); err != nil {
|
||||
global.LOG.Warnf("Failed to clear existing rules from %s: %v", chain, err)
|
||||
global.LOG.Warnf("clear existing rules from %s failed, err: %v", chain, err)
|
||||
}
|
||||
|
||||
appliedCount := 0
|
||||
for _, rule := range rules {
|
||||
if strings.HasPrefix(rule, fmt.Sprintf("-A %s", chain)) {
|
||||
ruleArgs := strings.TrimPrefix(rule, "-A ")
|
||||
if err := Run(tab, "-A "+ruleArgs); err != nil {
|
||||
global.LOG.Errorf("Failed to apply rule '%s': %v", rule, err)
|
||||
continue
|
||||
if err := Run(tab, rule); err != nil {
|
||||
global.LOG.Errorf("apply rule '%s' failed, err: %v", rule, err)
|
||||
}
|
||||
appliedCount++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue