diff --git a/.gitignore b/.gitignore index 0f6fc6d..99775e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # ========================================== # 操作系统生成的文件 # ========================================== +flutter_app/ # macOS .DS_Store @@ -51,7 +52,7 @@ $RECYCLE.BIN/ *.iml *.ipr out/ - +go-gost/ss/ # VS Code .vscode/ *.code-workspace diff --git a/go-gost/gost b/go-gost/gost index 5059e6c..2f7acb2 100755 Binary files a/go-gost/gost and b/go-gost/gost differ diff --git a/gost.sql b/gost.sql index 5ae3eb3..493d0dd 100644 --- a/gost.sql +++ b/gost.sql @@ -37,6 +37,7 @@ CREATE TABLE `forward` ( `out_port` int(10) DEFAULT NULL, `remote_addr` longtext NOT NULL, `strategy` varchar(100) NOT NULL DEFAULT 'fifo', + `interface_name` varchar(200) DEFAULT NULL, `in_flow` bigint(20) NOT NULL DEFAULT '0', `out_flow` bigint(20) NOT NULL DEFAULT '0', `created_time` bigint(20) NOT NULL, @@ -98,6 +99,7 @@ CREATE TABLE `tunnel` ( `out_ip` varchar(100) NOT NULL, `type` int(10) NOT NULL, `protocol` varchar(10) NOT NULL DEFAULT 'tls', + `interface_name` varchar(200) DEFAULT NULL, `flow` int(10) NOT NULL, `tcp_listen_addr` varchar(100) NOT NULL DEFAULT '0.0.0.0', `udp_listen_addr` varchar(100) NOT NULL DEFAULT '0.0.0.0', diff --git a/panel_install.sh b/panel_install.sh index 3c93002..e4f63d7 100755 --- a/panel_install.sh +++ b/panel_install.sh @@ -779,6 +779,42 @@ UPDATE \`forward\` SET \`inx\` = 0 WHERE \`inx\` IS NULL; +-- tunnel 表:添加 interface_name 字段(如果不存在) +SET @sql = ( + SELECT IF( + NOT EXISTS ( + SELECT 1 + FROM information_schema.COLUMNS + WHERE table_schema = DATABASE() + AND table_name = 'tunnel' + AND column_name = 'interface_name' + ), + 'ALTER TABLE \`tunnel\` ADD COLUMN \`interface_name\` VARCHAR(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;', + 'SELECT "Column \`interface_name\` already exists in \`tunnel\`";' + ) +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- forward 表:添加 interface_name 字段(如果不存在) +SET @sql = ( + SELECT IF( + NOT EXISTS ( + SELECT 1 + FROM information_schema.COLUMNS + WHERE table_schema = DATABASE() + AND table_name = 'forward' + AND column_name = 'interface_name' + ), + 'ALTER TABLE \`forward\` ADD COLUMN \`interface_name\` VARCHAR(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL;', + 'SELECT "Column \`interface_name\` already exists in \`forward\`";' + ) +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + -- 创建 vite_config 表(如果不存在) CREATE TABLE IF NOT EXISTS \`vite_config\` ( \`id\` int(10) NOT NULL AUTO_INCREMENT, diff --git a/springboot-backend/src/main/java/com/admin/common/dto/ForwardDto.java b/springboot-backend/src/main/java/com/admin/common/dto/ForwardDto.java index 6dfc939..4318a7f 100644 --- a/springboot-backend/src/main/java/com/admin/common/dto/ForwardDto.java +++ b/springboot-backend/src/main/java/com/admin/common/dto/ForwardDto.java @@ -1,5 +1,7 @@ package com.admin.common.dto; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -27,4 +29,6 @@ public class ForwardDto { @Max(value = 65535, message = "端口号不能大于65535") private Integer inPort; + private String interfaceName; + } \ No newline at end of file diff --git a/springboot-backend/src/main/java/com/admin/common/dto/ForwardUpdateDto.java b/springboot-backend/src/main/java/com/admin/common/dto/ForwardUpdateDto.java index 2f89e17..0b9361d 100644 --- a/springboot-backend/src/main/java/com/admin/common/dto/ForwardUpdateDto.java +++ b/springboot-backend/src/main/java/com/admin/common/dto/ForwardUpdateDto.java @@ -1,5 +1,7 @@ package com.admin.common.dto; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -32,4 +34,7 @@ public class ForwardUpdateDto { @Min(value = 1, message = "端口号不能小于1") @Max(value = 65535, message = "端口号不能大于65535") private Integer inPort; + + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String interfaceName; } \ No newline at end of file diff --git a/springboot-backend/src/main/java/com/admin/common/dto/ForwardWithTunnelDto.java b/springboot-backend/src/main/java/com/admin/common/dto/ForwardWithTunnelDto.java index 073a192..84874a2 100644 --- a/springboot-backend/src/main/java/com/admin/common/dto/ForwardWithTunnelDto.java +++ b/springboot-backend/src/main/java/com/admin/common/dto/ForwardWithTunnelDto.java @@ -87,4 +87,6 @@ public class ForwardWithTunnelDto { private String strategy; private Integer inx; + + private String interfaceName; } \ No newline at end of file diff --git a/springboot-backend/src/main/java/com/admin/common/dto/TunnelDto.java b/springboot-backend/src/main/java/com/admin/common/dto/TunnelDto.java index e77caa3..8ba6ebb 100644 --- a/springboot-backend/src/main/java/com/admin/common/dto/TunnelDto.java +++ b/springboot-backend/src/main/java/com/admin/common/dto/TunnelDto.java @@ -31,6 +31,8 @@ public class TunnelDto { @DecimalMin(value = "0.0", message = "流量倍率不能小于0.0") @DecimalMax(value = "100.0", message = "流量倍率不能大于100.0") private BigDecimal trafficRatio = new BigDecimal("1.0"); + + private String interfaceName; // 协议类型,默认为tls private String protocol; diff --git a/springboot-backend/src/main/java/com/admin/common/dto/TunnelUpdateDto.java b/springboot-backend/src/main/java/com/admin/common/dto/TunnelUpdateDto.java index 2ceed52..10ca96f 100644 --- a/springboot-backend/src/main/java/com/admin/common/dto/TunnelUpdateDto.java +++ b/springboot-backend/src/main/java/com/admin/common/dto/TunnelUpdateDto.java @@ -1,5 +1,7 @@ package com.admin.common.dto; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -36,4 +38,7 @@ public class TunnelUpdateDto { // UDP监听地址 @NotBlank private String udpListenAddr; + + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String interfaceName; } \ No newline at end of file diff --git a/springboot-backend/src/main/java/com/admin/common/utils/GostUtil.java b/springboot-backend/src/main/java/com/admin/common/utils/GostUtil.java index 3817d0f..d28f14a 100644 --- a/springboot-backend/src/main/java/com/admin/common/utils/GostUtil.java +++ b/springboot-backend/src/main/java/com/admin/common/utils/GostUtil.java @@ -5,6 +5,7 @@ import com.admin.common.dto.GostDto; import com.admin.entity.Tunnel; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; import org.aspectj.apache.bcel.generic.RET; import java.util.Objects; @@ -31,21 +32,21 @@ public class GostUtil { return WebSocketServer.send_msg(node_id, req, "DeleteLimiters"); } - public static GostDto AddService(Long node_id, String name, Integer in_port, Integer limiter, String remoteAddr, Integer fow_type, Tunnel tunnel, String strategy) { + public static GostDto AddService(Long node_id, String name, Integer in_port, Integer limiter, String remoteAddr, Integer fow_type, Tunnel tunnel, String strategy, String interfaceName) { JSONArray services = new JSONArray(); String[] protocols = {"tcp", "udp"}; for (String protocol : protocols) { - JSONObject service = createServiceConfig(name, in_port, limiter, remoteAddr, protocol, fow_type, tunnel, strategy); + JSONObject service = createServiceConfig(name, in_port, limiter, remoteAddr, protocol, fow_type, tunnel, strategy, interfaceName); services.add(service); } return WebSocketServer.send_msg(node_id, services, "AddService"); } - public static GostDto UpdateService(Long node_id, String name, Integer in_port, Integer limiter, String remoteAddr, Integer fow_type, Tunnel tunnel, String strategy) { + public static GostDto UpdateService(Long node_id, String name, Integer in_port, Integer limiter, String remoteAddr, Integer fow_type, Tunnel tunnel, String strategy, String interfaceName) { JSONArray services = new JSONArray(); String[] protocols = {"tcp", "udp"}; for (String protocol : protocols) { - JSONObject service = createServiceConfig(name, in_port, limiter, remoteAddr, protocol, fow_type, tunnel, strategy); + JSONObject service = createServiceConfig(name, in_port, limiter, remoteAddr, protocol, fow_type, tunnel, strategy, interfaceName); services.add(service); } return WebSocketServer.send_msg(node_id, services, "UpdateService"); @@ -60,10 +61,18 @@ public class GostUtil { return WebSocketServer.send_msg(node_id, data, "DeleteService"); } - public static GostDto AddRemoteService(Long node_id, String name, Integer out_port, String remoteAddr, String protocol, String strategy) { + public static GostDto AddRemoteService(Long node_id, String name, Integer out_port, String remoteAddr, String protocol, String strategy, String interfaceName) { JSONObject data = new JSONObject(); data.put("name", name + "_tls"); data.put("addr", ":" + out_port); + + if (StringUtils.isNotBlank(interfaceName)) { + JSONObject metadata = new JSONObject(); + metadata.put("interface", interfaceName); + data.put("metadata", metadata); + } + + JSONObject handler = new JSONObject(); handler.put("type", "relay"); data.put("handler", handler); @@ -89,7 +98,7 @@ public class GostUtil { JSONObject selector = new JSONObject(); selector.put("strategy", strategy); selector.put("maxFails", 1); - selector.put("failTimeout", "10s"); + selector.put("failTimeout", "600s"); forwarder.put("selector", selector); data.put("forwarder", forwarder); @@ -98,10 +107,18 @@ public class GostUtil { return WebSocketServer.send_msg(node_id, services, "AddService"); } - public static GostDto UpdateRemoteService(Long node_id, String name, Integer out_port, String remoteAddr,String protocol, String strategy) { + public static GostDto UpdateRemoteService(Long node_id, String name, Integer out_port, String remoteAddr,String protocol, String strategy, String interfaceName) { JSONObject data = new JSONObject(); data.put("name", name + "_tls"); data.put("addr", ":" + out_port); + + if (StringUtils.isNotBlank(interfaceName)) { + JSONObject metadata = new JSONObject(); + metadata.put("interface", interfaceName); + data.put("metadata", metadata); + } + + JSONObject handler = new JSONObject(); handler.put("type", "relay"); data.put("handler", handler); @@ -127,7 +144,7 @@ public class GostUtil { JSONObject selector = new JSONObject(); selector.put("strategy", strategy); selector.put("maxFails", 1); - selector.put("failTimeout", "10s"); + selector.put("failTimeout", "600s"); forwarder.put("selector", selector); data.put("forwarder", forwarder); @@ -178,7 +195,7 @@ public class GostUtil { return WebSocketServer.send_msg(node_id, data, "ResumeService"); } - public static GostDto AddChains(Long node_id, String name, String remoteAddr, String protocol) { + public static GostDto AddChains(Long node_id, String name, String remoteAddr, String protocol, String interfaceName) { JSONObject dialer = new JSONObject(); dialer.put("type", protocol); if (Objects.equals(protocol, "quic")){ @@ -200,6 +217,11 @@ public class GostUtil { node.put("connector", connector); node.put("dialer", dialer); + if (StringUtils.isNotBlank(interfaceName)) { + node.put("interface", interfaceName); + } + + JSONArray nodes = new JSONArray(); nodes.add(node); @@ -217,7 +239,7 @@ public class GostUtil { return WebSocketServer.send_msg(node_id, data, "AddChains"); } - public static GostDto UpdateChains(Long node_id, String name, String remoteAddr, String protocol) { + public static GostDto UpdateChains(Long node_id, String name, String remoteAddr, String protocol, String interfaceName) { JSONObject dialer = new JSONObject(); dialer.put("type", protocol); @@ -238,6 +260,10 @@ public class GostUtil { node.put("connector", connector); node.put("dialer", dialer); + if (StringUtils.isNotBlank(interfaceName)) { + node.put("interface", interfaceName); + } + JSONArray nodes = new JSONArray(); nodes.add(node); @@ -272,7 +298,7 @@ public class GostUtil { return data; } - private static JSONObject createServiceConfig(String name, Integer in_port, Integer limiter, String remoteAddr, String protocol, Integer fow_type, Tunnel tunnel, String strategy) { + private static JSONObject createServiceConfig(String name, Integer in_port, Integer limiter, String remoteAddr, String protocol, Integer fow_type, Tunnel tunnel, String strategy, String interfaceName) { JSONObject service = new JSONObject(); service.put("name", name + "_" + protocol); if (Objects.equals(protocol, "tcp")){ @@ -281,6 +307,13 @@ public class GostUtil { service.put("addr", tunnel.getUdpListenAddr() + ":" + in_port); } + if (StringUtils.isNotBlank(interfaceName)) { + JSONObject metadata = new JSONObject(); + metadata.put("interface", interfaceName); + service.put("metadata", metadata); + } + + // 添加限流器配置 if (limiter != null) { service.put("limiter", limiter.toString()); @@ -348,7 +381,7 @@ public class GostUtil { JSONObject selector = new JSONObject(); selector.put("strategy", strategy); selector.put("maxFails", 1); - selector.put("failTimeout", "10s"); + selector.put("failTimeout", "600s"); forwarder.put("selector", selector); return forwarder; } diff --git a/springboot-backend/src/main/java/com/admin/entity/Forward.java b/springboot-backend/src/main/java/com/admin/entity/Forward.java index 52e87df..d249287 100644 --- a/springboot-backend/src/main/java/com/admin/entity/Forward.java +++ b/springboot-backend/src/main/java/com/admin/entity/Forward.java @@ -32,6 +32,8 @@ public class Forward extends BaseEntity{ private String remoteAddr; + private String interfaceName; + private String strategy; private Long inFlow; diff --git a/springboot-backend/src/main/java/com/admin/entity/Tunnel.java b/springboot-backend/src/main/java/com/admin/entity/Tunnel.java index 1499019..7c2f5ee 100644 --- a/springboot-backend/src/main/java/com/admin/entity/Tunnel.java +++ b/springboot-backend/src/main/java/com/admin/entity/Tunnel.java @@ -68,4 +68,6 @@ public class Tunnel extends BaseEntity { private String tcpListenAddr; private String udpListenAddr; + + private String interfaceName; } diff --git a/springboot-backend/src/main/java/com/admin/service/impl/ForwardServiceImpl.java b/springboot-backend/src/main/java/com/admin/service/impl/ForwardServiceImpl.java index 480a704..f5c910a 100644 --- a/springboot-backend/src/main/java/com/admin/service/impl/ForwardServiceImpl.java +++ b/springboot-backend/src/main/java/com/admin/service/impl/ForwardServiceImpl.java @@ -103,8 +103,7 @@ public class ForwardServiceImpl extends ServiceImpl impl } // 7. 调用Gost服务创建转发 - R gostResult = createGostServices(forward, tunnel, permissionResult.getLimiter(), - nodeInfo, permissionResult.getUserTunnel()); + R gostResult = createGostServices(forward, tunnel, permissionResult.getLimiter(), nodeInfo, permissionResult.getUserTunnel()); if (gostResult.getCode() != 0) { this.removeById(forward.getId()); @@ -949,19 +948,18 @@ public class ForwardServiceImpl extends ServiceImpl impl /** * 创建Gost服务 */ - private R createGostServices(Forward forward, Tunnel tunnel, Integer limiter, - NodeInfo nodeInfo, UserTunnel userTunnel) { + private R createGostServices(Forward forward, Tunnel tunnel, Integer limiter, NodeInfo nodeInfo, UserTunnel userTunnel) { String serviceName = buildServiceName(forward.getId(), forward.getUserId(), userTunnel); // 隧道转发需要创建链和远程服务 if (tunnel.getType() == TUNNEL_TYPE_TUNNEL_FORWARD) { - R chainResult = createChainService(nodeInfo.getInNode(), serviceName, tunnel.getOutIp(), forward.getOutPort(), tunnel.getProtocol()); + R chainResult = createChainService(nodeInfo.getInNode(), serviceName, tunnel.getOutIp(), forward.getOutPort(), tunnel.getProtocol(), tunnel.getInterfaceName()); if (chainResult.getCode() != 0) { GostUtil.DeleteChains(nodeInfo.getInNode().getId(), serviceName); return chainResult; } - R remoteResult = createRemoteService(nodeInfo.getOutNode(), serviceName, forward, tunnel.getProtocol()); + R remoteResult = createRemoteService(nodeInfo.getOutNode(), serviceName, forward, tunnel.getProtocol(), forward.getInterfaceName()); if (remoteResult.getCode() != 0) { GostUtil.DeleteChains(nodeInfo.getInNode().getId(), serviceName); GostUtil.DeleteRemoteService(nodeInfo.getOutNode().getId(), serviceName); @@ -969,9 +967,14 @@ public class ForwardServiceImpl extends ServiceImpl impl } } - + String interfaceName = null; // 创建主服务 - R serviceResult = createMainService(nodeInfo.getInNode(), serviceName, forward, limiter, tunnel.getType(), tunnel, forward.getStrategy()); + if (tunnel.getType() != TUNNEL_TYPE_TUNNEL_FORWARD) { // 不是隧道转发服务才会存在网络接口 + interfaceName = forward.getInterfaceName(); + } + + + R serviceResult = createMainService(nodeInfo.getInNode(), serviceName, forward, limiter, tunnel.getType(), tunnel, forward.getStrategy(), interfaceName); if (serviceResult.getCode() != 0) { GostUtil.DeleteChains(nodeInfo.getInNode().getId(), serviceName); if (nodeInfo.getOutNode() != null) { @@ -991,21 +994,25 @@ public class ForwardServiceImpl extends ServiceImpl impl // 隧道转发需要更新链和远程服务 if (tunnel.getType() == TUNNEL_TYPE_TUNNEL_FORWARD) { - R chainResult = updateChainService(nodeInfo.getInNode(), serviceName, tunnel.getOutIp(), forward.getOutPort(), tunnel.getProtocol()); + R chainResult = updateChainService(nodeInfo.getInNode(), serviceName, tunnel.getOutIp(), forward.getOutPort(), tunnel.getProtocol(), tunnel.getInterfaceName()); if (chainResult.getCode() != 0) { updateForwardStatusToError(forward); return chainResult; } - R remoteResult = updateRemoteService(nodeInfo.getOutNode(), serviceName, forward, tunnel.getProtocol()); + R remoteResult = updateRemoteService(nodeInfo.getOutNode(), serviceName, forward, tunnel.getProtocol(), forward.getInterfaceName()); if (remoteResult.getCode() != 0) { updateForwardStatusToError(forward); return remoteResult; } } - + String interfaceName = null; + // 创建主服务 + if (tunnel.getType() != TUNNEL_TYPE_TUNNEL_FORWARD) { // 不是隧道转发服务才会存在网络接口 + interfaceName = forward.getInterfaceName(); + } // 更新主服务 - R serviceResult = updateMainService(nodeInfo.getInNode(), serviceName, forward, limiter, tunnel.getType(), tunnel, forward.getStrategy()); + R serviceResult = updateMainService(nodeInfo.getInNode(), serviceName, forward, limiter, tunnel.getType(), tunnel, forward.getStrategy(), interfaceName); if (serviceResult.getCode() != 0) { updateForwardStatusToError(forward); return serviceResult; @@ -1017,8 +1024,7 @@ public class ForwardServiceImpl extends ServiceImpl impl /** * 隧道变化时更新Gost服务:先删除原配置,再创建新配置 */ - private R updateGostServicesWithTunnelChange(Forward existForward, Forward updatedForward, Tunnel newTunnel, - Integer limiter, NodeInfo nodeInfo, UserTunnel userTunnel) { + private R updateGostServicesWithTunnelChange(Forward existForward, Forward updatedForward, Tunnel newTunnel, Integer limiter, NodeInfo nodeInfo, UserTunnel userTunnel) { // 1. 获取原隧道信息 Tunnel oldTunnel = tunnelService.getById(existForward.getTunnelId()); if (oldTunnel == null) { @@ -1124,43 +1130,43 @@ public class ForwardServiceImpl extends ServiceImpl impl /** * 创建链服务 */ - private R createChainService(Node inNode, String serviceName, String outIp, Integer outPort, String protocol) { + private R createChainService(Node inNode, String serviceName, String outIp, Integer outPort, String protocol, String interfaceName) { String remoteAddr = outIp + ":" + outPort; if (outIp.contains(":")) { remoteAddr = "[" + outIp + "]:" + outPort; } - GostDto result = GostUtil.AddChains(inNode.getId(), serviceName, remoteAddr, protocol); + GostDto result = GostUtil.AddChains(inNode.getId(), serviceName, remoteAddr, protocol, interfaceName); return isGostOperationSuccess(result) ? R.ok() : R.err(result.getMsg()); } /** * 创建远程服务 */ - private R createRemoteService(Node outNode, String serviceName, Forward forward, String protocol) { - GostDto result = GostUtil.AddRemoteService(outNode.getId(), serviceName, forward.getOutPort(), forward.getRemoteAddr(), protocol, forward.getStrategy()); + private R createRemoteService(Node outNode, String serviceName, Forward forward, String protocol, String interfaceName) { + GostDto result = GostUtil.AddRemoteService(outNode.getId(), serviceName, forward.getOutPort(), forward.getRemoteAddr(), protocol, forward.getStrategy(), interfaceName); return isGostOperationSuccess(result) ? R.ok() : R.err(result.getMsg()); } /** * 创建主服务 */ - private R createMainService(Node inNode, String serviceName, Forward forward, Integer limiter, Integer tunnelType, Tunnel tunnel, String strategy) { - GostDto result = GostUtil.AddService(inNode.getId(), serviceName, forward.getInPort(), limiter, forward.getRemoteAddr(), tunnelType, tunnel, strategy); + private R createMainService(Node inNode, String serviceName, Forward forward, Integer limiter, Integer tunnelType, Tunnel tunnel, String strategy, String interfaceName) { + GostDto result = GostUtil.AddService(inNode.getId(), serviceName, forward.getInPort(), limiter, forward.getRemoteAddr(), tunnelType, tunnel, strategy, interfaceName); return isGostOperationSuccess(result) ? R.ok() : R.err(result.getMsg()); } /** * 更新链服务 */ - private R updateChainService(Node inNode, String serviceName, String outIp, Integer outPort, String protocol) { + private R updateChainService(Node inNode, String serviceName, String outIp, Integer outPort, String protocol, String interfaceName) { // 创建新链 String remoteAddr = outIp + ":" + outPort; if (outIp.contains(":")) { remoteAddr = "[" + outIp + "]:" + outPort; } - GostDto createResult = GostUtil.UpdateChains(inNode.getId(), serviceName, remoteAddr, protocol); + GostDto createResult = GostUtil.UpdateChains(inNode.getId(), serviceName, remoteAddr, protocol, interfaceName); if (createResult.getMsg().contains(GOST_NOT_FOUND_MSG)) { - createResult = GostUtil.AddChains(inNode.getId(), serviceName, remoteAddr, protocol); + createResult = GostUtil.AddChains(inNode.getId(), serviceName, remoteAddr, protocol, interfaceName); } return isGostOperationSuccess(createResult) ? R.ok() : R.err(createResult.getMsg()); } @@ -1168,15 +1174,11 @@ public class ForwardServiceImpl extends ServiceImpl impl /** * 更新远程服务 */ - private R updateRemoteService(Node outNode, String serviceName, Forward forward, String protocol) { + private R updateRemoteService(Node outNode, String serviceName, Forward forward, String protocol, String interfaceName) { // 创建新远程服务 - GostDto createResult = GostUtil.UpdateRemoteService(outNode.getId(), - serviceName, forward.getOutPort(), - forward.getRemoteAddr(), protocol, forward.getStrategy()); + GostDto createResult = GostUtil.UpdateRemoteService(outNode.getId(), serviceName, forward.getOutPort(), forward.getRemoteAddr(), protocol, forward.getStrategy(), interfaceName); if (createResult.getMsg().contains(GOST_NOT_FOUND_MSG)) { - createResult = GostUtil.AddRemoteService(outNode.getId(), - serviceName, forward.getOutPort(), - forward.getRemoteAddr(),protocol, forward.getStrategy()); + createResult = GostUtil.AddRemoteService(outNode.getId(), serviceName, forward.getOutPort(), forward.getRemoteAddr(),protocol, forward.getStrategy(), interfaceName); } return isGostOperationSuccess(createResult) ? R.ok() : R.err(createResult.getMsg()); } @@ -1184,11 +1186,11 @@ public class ForwardServiceImpl extends ServiceImpl impl /** * 更新主服务 */ - private R updateMainService(Node inNode, String serviceName, Forward forward, Integer limiter, Integer tunnelType, Tunnel tunnel, String strategy) { - GostDto result = GostUtil.UpdateService(inNode.getId(), serviceName, forward.getInPort(), limiter, forward.getRemoteAddr(), tunnelType, tunnel, strategy); + private R updateMainService(Node inNode, String serviceName, Forward forward, Integer limiter, Integer tunnelType, Tunnel tunnel, String strategy, String interfaceName) { + GostDto result = GostUtil.UpdateService(inNode.getId(), serviceName, forward.getInPort(), limiter, forward.getRemoteAddr(), tunnelType, tunnel, strategy, interfaceName); if (result.getMsg().contains(GOST_NOT_FOUND_MSG)) { - result = GostUtil.AddService(inNode.getId(), serviceName, forward.getInPort(), limiter, forward.getRemoteAddr(), tunnelType, tunnel, strategy); + result = GostUtil.AddService(inNode.getId(), serviceName, forward.getInPort(), limiter, forward.getRemoteAddr(), tunnelType, tunnel, strategy, interfaceName); } return isGostOperationSuccess(result) ? R.ok() : R.err(result.getMsg()); diff --git a/springboot-backend/src/main/java/com/admin/service/impl/TunnelServiceImpl.java b/springboot-backend/src/main/java/com/admin/service/impl/TunnelServiceImpl.java index 6a9d016..b5038c6 100644 --- a/springboot-backend/src/main/java/com/admin/service/impl/TunnelServiceImpl.java +++ b/springboot-backend/src/main/java/com/admin/service/impl/TunnelServiceImpl.java @@ -22,6 +22,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.Data; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; @@ -176,10 +177,12 @@ public class TunnelServiceImpl extends ServiceImpl impleme int up = 0; if (!Objects.equals(existingTunnel.getTcpListenAddr(), tunnelUpdateDto.getTcpListenAddr()) || !Objects.equals(existingTunnel.getUdpListenAddr(), tunnelUpdateDto.getUdpListenAddr()) || - !Objects.equals(existingTunnel.getProtocol(), tunnelUpdateDto.getProtocol())) { + !Objects.equals(existingTunnel.getProtocol(), tunnelUpdateDto.getProtocol()) || + !Objects.equals(existingTunnel.getInterfaceName(), tunnelUpdateDto.getInterfaceName())) { up++; } + // 5. 更新允许修改的字段 existingTunnel.setName(tunnelUpdateDto.getName()); existingTunnel.setFlow(tunnelUpdateDto.getFlow()); @@ -187,9 +190,11 @@ public class TunnelServiceImpl extends ServiceImpl impleme existingTunnel.setUdpListenAddr(tunnelUpdateDto.getUdpListenAddr()); existingTunnel.setTrafficRatio(tunnelUpdateDto.getTrafficRatio()); existingTunnel.setProtocol(tunnelUpdateDto.getProtocol()); + existingTunnel.setInterfaceName(tunnelUpdateDto.getInterfaceName()); this.updateById(existingTunnel); int err = 0; - if (up == 1){ + if (up != 0){ + System.out.println("123123"); List tunnel = forwardService.list(new QueryWrapper().eq("tunnel_id", tunnelUpdateDto.getId())); if (!tunnel.isEmpty()) { for (Forward forward : tunnel) { @@ -201,6 +206,7 @@ public class TunnelServiceImpl extends ServiceImpl impleme forwardUpdateDto.setRemoteAddr(forward.getRemoteAddr()); forwardUpdateDto.setStrategy(forward.getStrategy()); forwardUpdateDto.setInPort(forward.getInPort()); + forwardUpdateDto.setInterfaceName(forward.getInterfaceName()); R r = forwardService.updateForward(forwardUpdateDto); if (r.getCode() != 0){ err++; diff --git a/springboot-backend/src/main/java/com/admin/service/impl/UserTunnelServiceImpl.java b/springboot-backend/src/main/java/com/admin/service/impl/UserTunnelServiceImpl.java index ff3b907..b29a5f5 100644 --- a/springboot-backend/src/main/java/com/admin/service/impl/UserTunnelServiceImpl.java +++ b/springboot-backend/src/main/java/com/admin/service/impl/UserTunnelServiceImpl.java @@ -498,8 +498,14 @@ public class UserTunnelServiceImpl extends ServiceImpl t.id === forward.tunnelId); @@ -535,6 +540,7 @@ export default function ForwardPage() { tunnelId: form.tunnelId, inPort: form.inPort, remoteAddr: processedRemoteAddr, + interfaceName: form.interfaceName, strategy: addressCount > 1 ? form.strategy : 'fifo' }; res = await updateForward(updateData); @@ -545,6 +551,7 @@ export default function ForwardPage() { tunnelId: form.tunnelId, inPort: form.inPort, remoteAddr: processedRemoteAddr, + interfaceName: form.interfaceName, strategy: addressCount > 1 ? form.strategy : 'fifo' }; res = await createForward(createData); @@ -1620,6 +1627,17 @@ export default function ForwardPage() { maxRows={6} /> + setForm(prev => ({ ...prev, interfaceName: e.target.value }))} + isInvalid={!!errors.interfaceName} + errorMessage={errors.interfaceName} + variant="bordered" + description="用于多IP服务器指定使用那个IP请求远程地址,不懂的默认为空就行" + /> + {getAddressCount(form.remoteAddr) > 1 && ( setForm(prev => ({ ...prev, interfaceName: e.target.value }))} + isInvalid={!!errors.interfaceName} + errorMessage={errors.interfaceName} + variant="bordered" + /> + )} + {/* 隧道转发时显示出口配置 */} {form.type === 2 && ( <> @@ -830,6 +848,13 @@ export default function TunnelPage() { description="V6或者双栈填写[::],V4填写0.0.0.0。不懂的就去看文档网站内的说明" className="mt-4" /> +