From 81a9338d343c89351c903b7da4c2d083e8e40dc8 Mon Sep 17 00:00:00 2001
From: endymx <345793738@qq.com>
Date: Thu, 4 Dec 2025 16:40:22 +0800
Subject: [PATCH] feat(iptables): range forward
---
.../utils/firewall/client/iptables/forward.go | 2 ++
frontend/src/lang/modules/en.ts | 1 +
frontend/src/lang/modules/zh.ts | 1 +
.../host/firewall/forward/operate/index.vue | 19 +++++++++++++++++--
4 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/agent/utils/firewall/client/iptables/forward.go b/agent/utils/firewall/client/iptables/forward.go
index c13ac0a54..1b369d933 100644
--- a/agent/utils/firewall/client/iptables/forward.go
+++ b/agent/utils/firewall/client/iptables/forward.go
@@ -6,6 +6,8 @@ import (
)
func AddForward(protocol, srcPort, dest, destPort, iface string, save bool) error {
+ // iptabels destPort 范围端口规则为:%d-%d
+ destPort = strings.ReplaceAll(destPort, ":", "-")
if dest != "" && dest != "127.0.0.1" && dest != "localhost" {
iptablesArg := fmt.Sprintf("-A %s", Chain1PanelPreRouting)
if iface != "" {
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index 7f5f663e6..07726b519 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -2915,6 +2915,7 @@ const message = {
targetPort: 'Destination port',
forwardHelper1: 'If you want to forward to the local port, the destination IP should be set to "127.0.0.1".',
forwardHelper2: 'Leave the destination IP blank to forward to the local port.',
+ forwardPortHelper: 'Support port range, e.g. 80:90',
forwardInboundInterface: 'Forward Inbound Network Interface',
exportHelper: 'About to export {0} firewall rules. Continue?',
importSuccess: 'Successfully imported {0} rules',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index eff185c14..dbb0dc583 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -2703,6 +2703,7 @@ const message = {
targetPort: '目标端口',
forwardHelper1: '如果是本机端口转发,目标IP为:127.0.0.1',
forwardHelper2: '如果目标IP不填写,则默认为本机端口转发',
+ forwardPortHelper: '支持端口范围,如:80:90',
forwardInboundInterface: '转发入站网卡',
exportHelper: '即将导出 {0} 条防火墙规则,是否继续?',
importSuccess: '成功导入 {0} 条规则',
diff --git a/frontend/src/views/host/firewall/forward/operate/index.vue b/frontend/src/views/host/firewall/forward/operate/index.vue
index 7514c6379..af8046b9c 100644
--- a/frontend/src/views/host/firewall/forward/operate/index.vue
+++ b/frontend/src/views/host/firewall/forward/operate/index.vue
@@ -14,6 +14,7 @@
+ {{ $t('firewall.forwardPortHelper') }}
@@ -24,6 +25,7 @@
+ {{ $t('firewall.forwardPortHelper') }}
@@ -103,8 +105,21 @@ function checkPortRule(rule: any, value: string, callback: any) {
if (!value) {
return callback(new Error(i18n.global.t('firewall.portFormatError')));
}
- if (checkPort(value)) {
- return callback(new Error(i18n.global.t('firewall.portFormatError')));
+ if (value.indexOf(':') !== -1) {
+ const ports = value.split(':');
+ if (ports.length !== 2) {
+ return callback(new Error(i18n.global.t('firewall.portFormatError')));
+ }
+ if (checkPort(ports[0]) || checkPort(ports[1])) {
+ return callback(new Error(i18n.global.t('firewall.portFormatError')));
+ }
+ if (Number(ports[0]) > Number(ports[1])) {
+ return callback(new Error(i18n.global.t('firewall.portFormatError')));
+ }
+ } else {
+ if (checkPort(value)) {
+ return callback(new Error(i18n.global.t('firewall.portFormatError')));
+ }
}
callback();
}