Skip to content

Commit ea544f5

Browse files
committed
feat: improve iptables firewall
1 parent 85c5a28 commit ea544f5

File tree

14 files changed

+256
-115
lines changed

14 files changed

+256
-115
lines changed

agent/app/service/iptables_filter.go

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func (s *IptablesFilterService) AddRule(req dto.IptablesFilterRuleOperate) error
145145
if (req.Action == "DROP" || req.Action == "REJECT") &&
146146
req.Protocol == "" && req.SourceIP == "" && req.DestIP == "" &&
147147
req.SourcePort == 0 && req.DestPort == 0 {
148-
return fmt.Errorf("不允许添加无条件 %s 规则,这会锁定系统", req.Action)
148+
return fmt.Errorf("Iptables Rule Security Check: unconditional %s rules are not allowed, this may lock you out of the system", req.Action)
149149
}
150150

151151
ctx := context.Background()
@@ -298,7 +298,7 @@ func (s *IptablesFilterService) ApplyFirewall() error {
298298
if (p.Action == "DROP" || p.Action == "REJECT") &&
299299
p.Protocol == "" && p.SourceIP == "" && p.DestIP == "" &&
300300
p.SrcPort == 0 && p.DstPort == 0 {
301-
return fmt.Errorf(" %s 包含无条件 %s 规则,不允许应用", Chain1PanelInput, p.Action)
301+
return fmt.Errorf("Chain %s includes unconditional %s rule, not allowed to apply", Chain1PanelInput, p.Action)
302302
}
303303
item = item.Next()
304304
}
@@ -312,59 +312,21 @@ func (s *IptablesFilterService) ApplyFirewall() error {
312312
if (p.Action == "DROP" || p.Action == "REJECT") &&
313313
p.Protocol == "" && p.SourceIP == "" && p.DestIP == "" &&
314314
p.SrcPort == 0 && p.DstPort == 0 {
315-
return fmt.Errorf(" %s 包含无条件 %s 规则,不允许应用", Chain1PanelOutput, p.Action)
315+
return fmt.Errorf("Chain %s includes unconditional %s rule, not allowed to apply", Chain1PanelOutput, p.Action)
316316
}
317317
item = item.Next()
318318
}
319319
}
320320

321-
// 检查 INPUT 链是否已有跳转规则
322-
inputChains, _ := s.iptablesClient.ReadFilter([]string{ChainInput})
323-
hasInputRule := false
324-
if inputChain, ok := inputChains[ChainInput]; ok {
325-
item := inputChain.FirstRule
326-
for item != nil {
327-
if item.P.Action == Chain1PanelInput {
328-
hasInputRule = true
329-
break
330-
}
331-
item = item.Next()
332-
}
333-
}
334-
335-
// 应用到 INPUT 链
336-
if !hasInputRule {
337-
if err := s.iptablesClient.Run(client.FilterTab, fmt.Sprintf("-I %s 1 -j %s", ChainInput, Chain1PanelInput)); err != nil {
338-
return fmt.Errorf("failed to apply %s to %s: %w", Chain1PanelInput, ChainInput, err)
339-
}
340-
global.LOG.Infof("Applied %s to %s chain", Chain1PanelInput, ChainInput)
341-
} else {
342-
global.LOG.Infof("%s already applied to %s chain", Chain1PanelInput, ChainInput)
321+
if err := s.iptablesClient.Setup1PanelFirewallChains("input"); err != nil {
322+
return fmt.Errorf("failed to apply %s to %s: %w", Chain1PanelInput, ChainInput, err)
343323
}
324+
global.LOG.Infof("Applied %s to %s chain", Chain1PanelInput, ChainInput)
344325

345-
// 检查 OUTPUT 链是否已有跳转规则
346-
outputChains, _ := s.iptablesClient.ReadFilter([]string{ChainOutput})
347-
hasOutputRule := false
348-
if outputChain, ok := outputChains[ChainOutput]; ok {
349-
item := outputChain.FirstRule
350-
for item != nil {
351-
if item.P.Action == Chain1PanelOutput {
352-
hasOutputRule = true
353-
break
354-
}
355-
item = item.Next()
356-
}
357-
}
358-
359-
// 应用到 OUTPUT 链
360-
if !hasOutputRule {
361-
if err := s.iptablesClient.Run(client.FilterTab, fmt.Sprintf("-I %s 1 -j %s", ChainOutput, Chain1PanelOutput)); err != nil {
362-
return fmt.Errorf("failed to apply %s to %s: %w", Chain1PanelOutput, ChainOutput, err)
363-
}
364-
global.LOG.Infof("Applied %s to %s chain", Chain1PanelOutput, ChainOutput)
365-
} else {
366-
global.LOG.Infof("%s already applied to %s chain", Chain1PanelOutput, ChainOutput)
326+
if err := s.iptablesClient.Setup1PanelFirewallChains("output"); err != nil {
327+
return fmt.Errorf("failed to apply %s to %s: %w", Chain1PanelInput, ChainInput, err)
367328
}
329+
global.LOG.Infof("Applied %s to %s chain", Chain1PanelInput, ChainInput)
368330

369331
return nil
370332
}

agent/utils/firewall/client/iptables.go

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ import (
1212
)
1313

1414
const (
15-
PreRoutingChain = "1PANEL_PREROUTING"
16-
PostRoutingChain = "1PANEL_POSTROUTING"
17-
ForwardChain = "1PANEL_FORWARD"
15+
PreRoutingChain = "1PANEL_PREROUTING"
16+
PostRoutingChain = "1PANEL_POSTROUTING"
17+
ForwardChain = "1PANEL_FORWARD"
18+
ChainInput = "INPUT"
19+
ChainOutput = "OUTPUT"
20+
Chain1PanelInput = "1PANEL_INPUT"
21+
Chain1PanelOutput = "1PANEL_OUTPUT"
1822
)
1923

2024
const (
@@ -432,3 +436,57 @@ func (iptables *Iptables) DeletePolicy(chain string, policy IptablesPolicy) erro
432436

433437
return iptables.run(FilterTab, iptablesArg)
434438
}
439+
440+
// CheckPolicyExists 检查策略是否存在
441+
func (iptables *Iptables) CheckPolicyExists(chain string, policyStr string) bool {
442+
err := iptables.run(FilterTab, fmt.Sprintf("-C %s %s", chain, policyStr))
443+
if err != nil {
444+
return false
445+
}
446+
return true
447+
}
448+
449+
const (
450+
establishedRule = "-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT"
451+
ioRuleIn = "-i lo -j ACCEPT"
452+
ioRuleOut = "-o lo -j ACCEPT"
453+
)
454+
455+
func (iptables *Iptables) setupEstablishedRules(direction string) {
456+
if direction == "input" {
457+
if !iptables.CheckPolicyExists("INPUT", ioRuleIn) {
458+
iptables.run(FilterTab, fmt.Sprintf("-I INPUT 1 %s", ioRuleIn))
459+
}
460+
461+
if !iptables.CheckPolicyExists("INPUT", establishedRule) {
462+
iptables.run(FilterTab, fmt.Sprintf("-I INPUT 2 %s", establishedRule))
463+
}
464+
}
465+
466+
if direction == "output" {
467+
if !iptables.CheckPolicyExists("OUTPUT", ioRuleOut) {
468+
iptables.run(FilterTab, fmt.Sprintf("-I OUTPUT 1 %s", ioRuleOut))
469+
}
470+
if !iptables.CheckPolicyExists("OUTPUT", establishedRule) {
471+
iptables.run(FilterTab, fmt.Sprintf("-I OUTPUT 2 %s", establishedRule))
472+
}
473+
}
474+
}
475+
476+
func (iptables *Iptables) Setup1PanelFirewallChains(direction string) error {
477+
iptables.setupEstablishedRules(direction)
478+
if direction == "input" {
479+
if !iptables.CheckPolicyExists(ChainInput, fmt.Sprintf("-j %s", Chain1PanelInput)) {
480+
if err := iptables.run(FilterTab, fmt.Sprintf("-I %s 3 -j %s", ChainInput, Chain1PanelInput)); err != nil {
481+
return err
482+
}
483+
}
484+
} else if direction == "output" {
485+
if !iptables.CheckPolicyExists(ChainOutput, fmt.Sprintf("-j %s", Chain1PanelOutput)) {
486+
if err := iptables.run(FilterTab, fmt.Sprintf("-I %s 3 -j %s", ChainOutput, Chain1PanelOutput)); err != nil {
487+
return err
488+
}
489+
}
490+
}
491+
return nil
492+
}

frontend/src/lang/modules/en.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,6 +2868,9 @@ const message = {
28682868
changeStrategyHelper:
28692869
'Change [{1}] {0} strategy to [{2}]. After setting, {0} will access {2} externally. Do you want to continue?',
28702870
portHelper: 'Multiple ports can be entered, e.g. 80,81, or range ports, e.g. 80-88',
2871+
allPorts: 'All Ports',
2872+
ruleTemplate: 'Rule template',
2873+
28712874
strategy: 'Strategy',
28722875
accept: 'Accept',
28732876
drop: 'Drop',
@@ -2888,6 +2891,8 @@ const message = {
28882891
createIpRule: '@:commons.button.create @:firewall.ipRule',
28892892
userAgent: 'User-Agent filter',
28902893
sourcePort: 'Source port',
2894+
inboundDirection: 'Inbound',
2895+
outboundDirection: 'Outbound',
28912896
targetIP: 'Destination IP',
28922897
targetPort: 'Destination port',
28932898
forwardHelper1: 'If you want to forward to the local port, the destination IP should be set to "127.0.0.1".',

frontend/src/lang/modules/es-es.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,6 +2839,9 @@ const message = {
28392839
changeStrategyHelper:
28402840
'Cambiar estrategia de {0} [{1}] a [{2}]. Después de configurarla, {0} tendrá acceso externo como {2}. ¿Deseas continuar?',
28412841
portHelper: 'Se pueden ingresar múltiples puertos, ej. 80,81, o rangos, ej. 80-88',
2842+
allPorts: 'Todos los puertos',
2843+
ruleTemplate: 'Plantilla de regla',
2844+
28422845
strategy: 'Estrategia',
28432846
accept: 'Aceptar',
28442847
drop: 'Rechazar',
@@ -2859,6 +2862,8 @@ const message = {
28592862
createIpRule: '@:commons.button.create @:firewall.ipRule',
28602863
userAgent: 'Filtro User-Agent',
28612864
sourcePort: 'Puerto de origen',
2865+
inboundDirection: 'Entrada',
2866+
outboundDirection: 'Salida',
28622867
targetIP: 'IP de destino',
28632868
targetPort: 'Puerto de destino',
28642869
forwardHelper1: 'Si quieres reenviar al puerto local, la IP de destino debe ser "127.0.0.1".',

frontend/src/lang/modules/ja.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,6 +2785,9 @@ const message = {
27852785
changeStrategyHelper:
27862786
'[{1}] {0}戦略を[{2}]に変更します。設定後、{0}は外部から{2}にアクセスします。続けたいですか?',
27872787
portHelper: '複数のポートを入力できます。80,81、または範囲ポート、例えば80-88',
2788+
allPorts: 'すべてのポート',
2789+
ruleTemplate: 'ルールテンプレート',
2790+
27882791
strategy: '戦略',
27892792
accept: '受け入れる',
27902793
drop: '落とす',
@@ -2805,6 +2808,8 @@ const message = {
28052808
createIpRule: '@:commons.button.create @:firewall.iprule',
28062809
userAgent: 'ユーザーエージェントフィルター',
28072810
sourcePort: 'ソースポート',
2811+
inboundDirection: '受信方向',
2812+
outboundDirection: '送信方向',
28082813
targetIP: '宛先IP',
28092814
targetPort: '宛先ポート',
28102815
forwardHelper1: 'ローカルポートに転送する場合は、宛先IPを「127.0.0.1」に設定する必要があります。',

frontend/src/lang/modules/ko.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2735,6 +2735,9 @@ const message = {
27352735
changeStrategyHelper:
27362736
'[{1}] {0} 전략을 [{2}]로 변경합니다. 설정 후 {0}은(는) {2}로 외부 접근을 허용합니다. 계속하시겠습니까?',
27372737
portHelper: '여러 포트를 입력할 수 있습니다. 예: 80, 81 또는 포트 범위, 예: 80-88',
2738+
allPorts: '모든 포트',
2739+
ruleTemplate: '규칙 템플릿',
2740+
27382741
strategy: '전략',
27392742
accept: '허용',
27402743
drop: '차단',
@@ -2755,6 +2758,8 @@ const message = {
27552758
createIpRule: '@:commons.button.create @:firewall.ipRule',
27562759
userAgent: 'User-Agent 필터',
27572760
sourcePort: '소스 포트',
2761+
inboundDirection: '인바운드',
2762+
outboundDirection: '아웃바운드',
27582763
targetIP: '대상 IP',
27592764
targetPort: '대상 포트',
27602765
forwardHelper1: "로컬 포트로 전달하려면, 대상 IP 를 '127.0.0.1'로 설정해야 합니다.",

frontend/src/lang/modules/ms.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2850,6 +2850,9 @@ const message = {
28502850
changeStrategyHelper:
28512851
'Tukar strategi {0} [{1}] kepada [{2}]. Selepas tetapan, {0} akan mengakses {2} secara luaran. Adakah anda mahu meneruskan?',
28522852
portHelper: 'Pelbagai port boleh dimasukkan, contohnya 80,81, atau rentang port, contohnya 80-88',
2853+
allPorts: 'Semua port',
2854+
ruleTemplate: 'Templat peraturan',
2855+
28532856
strategy: 'Strategi',
28542857
accept: 'Terima',
28552858
drop: 'Lumpuhkan',
@@ -2870,6 +2873,8 @@ const message = {
28702873
createIpRule: '@:commons.button.create @:firewall.ipRule',
28712874
userAgent: 'Penapis User-Agent',
28722875
sourcePort: 'Port sumber',
2876+
inboundDirection: 'Masuk',
2877+
outboundDirection: 'Keluar',
28732878
targetIP: 'IP sasaran',
28742879
targetPort: 'Port sasaran',
28752880
forwardHelper1: 'Jika anda ingin memajukan ke port tempatan, IP sasaran harus ditetapkan kepada "127.0.0.1".',

frontend/src/lang/modules/pt-br.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,6 +2853,9 @@ const message = {
28532853
changeStrategyHelper:
28542854
'Alterar a estratégia [{1}] {0} para [{2}]. Após a definição, {0} acessará {2} externamente. Deseja continuar?',
28552855
portHelper: 'Várias portas podem ser inseridas, ex.: 80,81, ou faixas de portas, ex.: 80-88',
2856+
allPorts: 'Todas as portas',
2857+
ruleTemplate: 'Modelo de regra',
2858+
28562859
strategy: 'Estratégia',
28572860
accept: 'Aceitar',
28582861
drop: 'Bloquear',
@@ -2873,6 +2876,8 @@ const message = {
28732876
createIpRule: '@:commons.button.create @:firewall.ipRule',
28742877
userAgent: 'Filtro User-Agent',
28752878
sourcePort: 'Porta de origem',
2879+
inboundDirection: 'Entrada',
2880+
outboundDirection: 'Saída',
28762881
targetIP: 'IP de destino',
28772882
targetPort: 'Porta de destino',
28782883
forwardHelper1:

frontend/src/lang/modules/ru.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,6 +2849,9 @@ const message = {
28492849
changeStrategyHelper:
28502850
'Изменить стратегию {0} [{1}] на [{2}]. После установки {0} будет иметь внешний доступ {2}. Хотите продолжить?',
28512851
portHelper: 'Можно ввести несколько портов, например 80,81, или диапазон портов, например 80-88',
2852+
allPorts: 'Все порты',
2853+
ruleTemplate: 'Шаблон правила',
2854+
28522855
strategy: 'Стратегия',
28532856
accept: 'Принять',
28542857
drop: 'Отбросить',
@@ -2869,6 +2872,8 @@ const message = {
28692872
createIpRule: '@:commons.button.create @:firewall.ipRule',
28702873
userAgent: 'Фильтр User-Agent',
28712874
sourcePort: 'Исходный порт',
2875+
inboundDirection: 'Входящий',
2876+
outboundDirection: 'Исходящий',
28722877
targetIP: 'Целевой IP',
28732878
targetPort: 'Целевой порт',
28742879
forwardHelper1:

frontend/src/lang/modules/tr.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2907,6 +2907,8 @@ const message = {
29072907
changeStrategyHelper:
29082908
'[{1}] {0} stratejisini [{2}] olarak değiştirin. Ayar yapıldıktan sonra {0}, dışarıdan {2} erişimi sağlayacak. Devam etmek istiyor musunuz?',
29092909
portHelper: 'Birden fazla port girilebilir, ör. 80,81 veya aralık portları, ör. 80-88',
2910+
allPorts: 'Tüm portlar',
2911+
ruleTemplate: 'Kural şablonu',
29102912
strategy: 'Strateji',
29112913
accept: 'Kabul Et',
29122914
drop: 'Reddet',
@@ -2927,6 +2929,8 @@ const message = {
29272929
createIpRule: '@:commons.button.create @:firewall.ipRule',
29282930
userAgent: 'Kullanıcı-Aracısı filtresi',
29292931
sourcePort: 'Kaynak port',
2932+
inboundDirection: 'Gelen',
2933+
outboundDirection: 'Giden',
29302934
targetIP: 'Hedef IP',
29312935
targetPort: 'Hedef port',
29322936
forwardHelper1: 'Yerel porta yönlendirmek istiyorsanız, hedef IP "127.0.0.1" olarak ayarlanmalıdır.',

0 commit comments

Comments
 (0)