Skip to content

Commit 5624d48

Browse files
committed
fix: Fix the issue of abnormal iptables rule persistence
1 parent 63f9368 commit 5624d48

File tree

5 files changed

+139
-53
lines changed

5 files changed

+139
-53
lines changed

agent/app/api/v2/firewall.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func (b *BaseApi) OperateFilterRule(c *gin.Context) {
269269
if err := helper.CheckBindAndValidate(&req, c); err != nil {
270270
return
271271
}
272-
if err := iptablesService.OperateRule(req); err != nil {
272+
if err := iptablesService.OperateRule(req, true); err != nil {
273273
helper.InternalServer(c, err)
274274
return
275275
}

agent/app/service/iptables.go

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616

1717
type IIptablesService interface {
1818
Search(req dto.SearchPageWithType) (int64, interface{}, error)
19-
OperateRule(req dto.IptablesRuleOp) error
19+
OperateRule(req dto.IptablesRuleOp, withSave bool) error
2020
BatchOperate(req dto.IptablesBatchOperate) error
2121
LoadChainStatus(req dto.OperationWithName) dto.IptablesChainStatus
2222

@@ -63,7 +63,7 @@ func (s *IptablesService) Search(req dto.SearchPageWithType) (int64, interface{}
6363
return int64(total), records, nil
6464
}
6565

66-
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
66+
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp, withSave bool) error {
6767
action := "ACCEPT"
6868
if req.Strategy == "drop" {
6969
action = "DROP"
@@ -122,18 +122,33 @@ func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
122122
}
123123
}
124124

125+
if !withSave {
126+
return nil
127+
}
125128
if err := iptables.SaveRulesToFile(iptables.FilterTab, req.Chain, name); err != nil {
126129
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
127130
}
128131
return nil
129132
}
130133

131134
func (s *IptablesService) BatchOperate(req dto.IptablesBatchOperate) error {
135+
if len(req.Rules) == 0 {
136+
return errors.New("no rules to operate")
137+
}
132138
for _, rule := range req.Rules {
133-
if err := s.OperateRule(rule); err != nil {
139+
if err := s.OperateRule(rule, false); err != nil {
134140
return err
135141
}
136142
}
143+
chain := iptables.Chain1PanelInput
144+
fileName := iptables.InputFileName
145+
if req.Rules[0].Chain == iptables.Chain1PanelOutput {
146+
chain = iptables.Chain1PanelOutput
147+
fileName = iptables.OutputFileName
148+
}
149+
if err := iptables.SaveRulesToFile(iptables.FilterTab, chain, fileName); err != nil {
150+
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
151+
}
137152
return nil
138153
}
139154

@@ -168,6 +183,12 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
168183
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil {
169184
return err
170185
}
186+
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
187+
return err
188+
}
189+
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
190+
return err
191+
}
171192
return nil
172193
case "init-forward":
173194
return client.EnableIptablesForward()
@@ -310,16 +331,7 @@ func initPreRules() error {
310331
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); err != nil {
311332
return err
312333
}
313-
panelPort := ""
314-
if !global.IsMaster {
315-
panelPort = global.CONF.Base.Port
316-
} else {
317-
var portSetting model.Setting
318-
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
319-
if len(portSetting.Value) != 0 {
320-
panelPort = portSetting.Value
321-
}
322-
}
334+
panelPort := LoadPanelPort()
323335
if len(panelPort) == 0 {
324336
return errors.New("find 1panel service port failed")
325337
}
@@ -337,3 +349,16 @@ func initPreRules() error {
337349
}
338350
return nil
339351
}
352+
353+
func LoadPanelPort() string {
354+
if !global.IsMaster {
355+
return global.CONF.Base.Port
356+
} else {
357+
var portSetting model.Setting
358+
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
359+
if len(portSetting.Value) != 0 {
360+
return portSetting.Value
361+
}
362+
}
363+
return ""
364+
}

agent/init/firewall/firwall.go

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package firewall
22

33
import (
4+
"fmt"
5+
6+
"github.com/1Panel-dev/1Panel/agent/app/dto"
7+
"github.com/1Panel-dev/1Panel/agent/app/service"
8+
"github.com/1Panel-dev/1Panel/agent/global"
49
"github.com/1Panel-dev/1Panel/agent/utils/firewall"
510
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
611
)
@@ -12,13 +17,73 @@ func Init() {
1217
}
1318
clientName := client.Name()
1419
if clientName == "ufw" || clientName == "iptables" {
15-
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName)
16-
_ = iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPreRouting, iptables.ForwardFileName1)
17-
_ = iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPostRouting, iptables.ForwardFileName2)
20+
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName); err != nil {
21+
global.LOG.Errorf("load forward rules from file failed, err: %v", err)
22+
return
23+
}
24+
if err := iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPreRouting, iptables.ForwardFileName1); err != nil {
25+
global.LOG.Errorf("load prerouting rules from file failed, err: %v", err)
26+
return
27+
}
28+
if err := iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPostRouting, iptables.ForwardFileName2); err != nil {
29+
global.LOG.Errorf("load postrouting rules from file failed, err: %v", err)
30+
return
31+
}
32+
global.LOG.Infof("loaded iptables rules for forward from file successfully")
33+
}
34+
if clientName == "ufw" {
35+
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter)
36+
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore)
37+
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic)
38+
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput)
39+
_ = iptables.UnbindChain(iptables.FilterTab, iptables.ChainOutput, iptables.Chain1PanelOutput)
1840
}
1941
if clientName == "iptables" {
20-
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName)
21-
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName)
22-
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName)
42+
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
43+
global.LOG.Errorf("load basic before rules from file failed, err: %v", err)
44+
return
45+
}
46+
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
47+
global.LOG.Errorf("load basic rules from file failed, err: %v", err)
48+
return
49+
}
50+
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
51+
global.LOG.Errorf("load basic after rules from file failed, err: %v", err)
52+
return
53+
}
54+
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName); err != nil {
55+
global.LOG.Errorf("load input rules from file failed, err: %v", err)
56+
return
57+
}
58+
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName); err != nil {
59+
global.LOG.Errorf("load output rules from file failed, err: %v", err)
60+
return
61+
}
62+
global.LOG.Infof("loaded iptables rules for basic, input and output from file successfully")
63+
64+
panelPort := service.LoadPanelPort()
65+
if len(panelPort) == 0 {
66+
global.LOG.Errorf("find 1panel service port failed")
67+
return
68+
}
69+
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", panelPort)); err != nil {
70+
global.LOG.Errorf("add port accept rule %v failed, err: %v", panelPort, err)
71+
return
72+
}
73+
74+
iptablesService := service.IptablesService{}
75+
if err := iptablesService.Operate(dto.IptablesOp{Operate: "bind-base"}); err != nil {
76+
global.LOG.Errorf("bind base chains failed, err: %v", err)
77+
return
78+
}
79+
if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelOutput, Operate: "bind"}); err != nil {
80+
global.LOG.Errorf("bind output chains failed, err: %v", err)
81+
return
82+
}
83+
if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelInput, Operate: "bind"}); err != nil {
84+
global.LOG.Errorf("bind input chains failed, err: %v", err)
85+
return
86+
}
2387
}
88+
2489
}

agent/utils/firewall/client/iptables.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,12 @@ func (i *Iptables) Port(port FireInfo, operation string) error {
144144
}
145145
}
146146

147+
name := iptables.BasicFileName
148+
if port.Chain == iptables.Chain1PanelBasicBefore {
149+
name = iptables.BasicBeforeFileName
150+
}
147151
if port.Chain == iptables.Chain1PanelBasic {
148-
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
152+
if err := iptables.SaveRulesToFile(iptables.FilterTab, port.Chain, name); err != nil {
149153
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
150154
}
151155
}
@@ -207,8 +211,12 @@ func (i *Iptables) RichRules(rule FireInfo, operation string) error {
207211
}
208212
}
209213

214+
name := iptables.BasicFileName
215+
if rule.Chain == iptables.Chain1PanelBasicBefore {
216+
name = iptables.BasicBeforeFileName
217+
}
210218
if rule.Chain == iptables.Chain1PanelBasic {
211-
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
219+
if err := iptables.SaveRulesToFile(iptables.FilterTab, rule.Chain, name); err != nil {
212220
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
213221
}
214222
}

agent/utils/firewall/client/iptables/persistence.go

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import (
1111
)
1212

1313
const (
14-
BasicFileName = "1panel_basic.rules"
15-
InputFileName = "1panel_input.rules"
16-
OutputFileName = "1panel_out.rules"
17-
ForwardFileName = "1panel_forward.rules"
18-
ForwardFileName1 = "1panel_forward_pre.rules"
19-
ForwardFileName2 = "1panel_forward_post.rules"
14+
BasicBeforeFileName = "1panel_basic_before.rules"
15+
BasicFileName = "1panel_basic.rules"
16+
BasicAfterFileName = "1panel_basic_after.rules"
17+
InputFileName = "1panel_input.rules"
18+
OutputFileName = "1panel_out.rules"
19+
ForwardFileName = "1panel_forward.rules"
20+
ForwardFileName1 = "1panel_forward_pre.rules"
21+
ForwardFileName2 = "1panel_forward_post.rules"
2022
)
2123

2224
func SaveRulesToFile(tab, chain, fileName string) error {
@@ -63,39 +65,25 @@ func LoadRulesFromFile(tab, chain, fileName string) error {
6365
return nil
6466
}
6567

66-
file, err := os.Open(rulesFile)
67-
if err != nil {
68-
return fmt.Errorf("failed to open rules file: %w", err)
68+
if err := AddChain(tab, chain); err != nil {
69+
global.LOG.Errorf("create chain %s failed: %v", chain, err)
70+
return err
6971
}
70-
defer file.Close()
71-
72-
var rules []string
73-
scanner := bufio.NewScanner(file)
74-
for scanner.Scan() {
75-
line := strings.TrimSpace(scanner.Text())
76-
if line == "" || strings.HasPrefix(line, "#") {
77-
continue
78-
}
79-
rules = append(rules, line)
80-
}
81-
82-
if err := scanner.Err(); err != nil {
83-
return fmt.Errorf("failed to read rules file: %w", err)
72+
data, err := os.ReadFile(rulesFile)
73+
if err != nil {
74+
global.LOG.Errorf("read rules from file %s failed, err: %v", rulesFile, err)
75+
return err
8476
}
85-
77+
rules := strings.Split(string(data), "\n")
8678
if err := ClearChain(tab, chain); err != nil {
87-
global.LOG.Warnf("Failed to clear existing rules from %s: %v", chain, err)
79+
global.LOG.Warnf("clear existing rules from %s failed, err: %v", chain, err)
8880
}
8981

90-
appliedCount := 0
9182
for _, rule := range rules {
9283
if strings.HasPrefix(rule, fmt.Sprintf("-A %s", chain)) {
93-
ruleArgs := strings.TrimPrefix(rule, "-A ")
94-
if err := Run(tab, "-A "+ruleArgs); err != nil {
95-
global.LOG.Errorf("Failed to apply rule '%s': %v", rule, err)
96-
continue
84+
if err := Run(tab, rule); err != nil {
85+
global.LOG.Errorf("apply rule '%s' failed, err: %v", rule, err)
9786
}
98-
appliedCount++
9987
}
10088
}
10189

0 commit comments

Comments
 (0)