From 4fef8eeb325c30e8ac74a0a4e83fb295af521495 Mon Sep 17 00:00:00 2001 From: qaq <1937228092@qq.com> Date: Wed, 19 Nov 2025 16:32:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=87=BA=E5=8F=A3=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E6=97=A0=E6=B3=95=E9=80=89=E6=8B=A9=EF=BC=8C=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E8=87=AA=E5=AE=9A=E4=B9=89=E8=BD=AC=E5=8F=91=E7=AB=AF?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E5=A2=9E=E5=8A=A0arm=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/docker-build.yml | 59 +++++++++++---- docker-compose-v4.yml | 4 +- docker-compose-v6.yml | 4 +- install.sh | 2 +- panel_install.sh | 4 +- .../java/com/admin/common/dto/ForwardDto.java | 2 + .../admin/common/dto/ForwardUpdateDto.java | 2 + .../java/com/admin/service/TunnelService.java | 2 +- .../service/impl/ForwardServiceImpl.java | 11 ++- .../admin/service/impl/NodeServiceImpl.java | 2 +- .../admin/service/impl/TunnelServiceImpl.java | 9 ++- vite-frontend/src/config/site.ts | 2 +- vite-frontend/src/pages/forward.tsx | 28 +++++++ vite-frontend/src/pages/tunnel.tsx | 73 ++++++++++++++----- 14 files changed, 157 insertions(+), 47 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 52096f7..688e2c0 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -2,7 +2,7 @@ name: Build and Push Images Based on Version # 在这里定义统一版本号 env: - VERSION: "2.0.1-beta" + VERSION: "2.0.2-beta" on: push: @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - fetch-depth: 0 # 获取所有历史和 tags + fetch-depth: 0 - name: Display version run: | @@ -67,22 +67,38 @@ jobs: sudo mv upx-4.2.1-amd64_linux/upx /usr/local/bin/ rm -rf upx-4.2.1-amd64_linux* - - name: Build GOST binary + - name: Build GOST binary (AMD64) working-directory: ./go-gost run: | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o gost - - name: Compress with UPX + - name: Build GOST binary (ARM64) + working-directory: ./go-gost + run: | + CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o gost-arm64 + + - name: Compress with UPX (AMD64) working-directory: ./go-gost run: | upx --best --lzma gost - - name: Upload GOST artifact + - name: Compress with UPX (ARM64) + working-directory: ./go-gost + run: | + upx --best --lzma gost-arm64 + + - name: Upload GOST AMD64 artifact uses: actions/upload-artifact@v4 with: - name: gost-binary + name: gost-binary-amd64 path: ./go-gost/gost + - name: Upload GOST ARM64 artifact + uses: actions/upload-artifact@v4 + with: + name: gost-binary-arm64 + path: ./go-gost/gost-arm64 + build-vite: name: Build & Push Vite Frontend needs: check-version @@ -109,7 +125,7 @@ jobs: run: | VERSION="${{ needs.check-version.outputs.version }}" docker buildx build \ - --platform linux/amd64 \ + --platform linux/amd64,linux/arm64 \ --push \ -t bqlpfy/vite-frontend:latest \ -t bqlpfy/vite-frontend:${VERSION} \ @@ -153,7 +169,7 @@ jobs: run: | VERSION="${{ needs.check-version.outputs.version }}" docker buildx build \ - --platform linux/amd64 \ + --platform linux/amd64,linux/arm64 \ --push \ -t bqlpfy/springboot-backend:latest \ -t bqlpfy/springboot-backend:${VERSION} \ @@ -169,11 +185,22 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Download GOST binary + - name: Download GOST AMD64 binary uses: actions/download-artifact@v4 with: - name: gost-binary - path: ./artifacts + name: gost-binary-amd64 + path: ./artifacts/amd64 + + - name: Download GOST ARM64 binary + uses: actions/download-artifact@v4 + with: + name: gost-binary-arm64 + path: ./artifacts/arm64 + + - name: Rename binaries + run: | + mv ./artifacts/amd64/gost ./artifacts/gost + mv ./artifacts/arm64/gost-arm64 ./artifacts/gost-arm64 - name: Create Release env: @@ -202,9 +229,10 @@ jobs: - **Commit**: [\`${GITHUB_SHA:0:7}\`](https://github.com/${{ github.repository }}/commit/${{ github.sha }}) ## 📦 Components - - **GOST Binary** (Linux AMD64, compressed with UPX) - - **Vite Frontend** Docker Image: \`bqlpfy/vite-frontend:${VERSION}\` / \`bqlpfy/vite-frontend:latest\` - - **Spring Boot Backend** Docker Image: \`bqlpfy/springboot-backend:${VERSION}\` / \`bqlpfy/springboot-backend:latest\` + - **GOST Binary AMD64** - \`gost\` (Linux AMD64, compressed with UPX) + - **GOST Binary ARM64** - \`gost-arm64\` (Linux ARM64, compressed with UPX) + - **Vite Frontend** Docker Image: \`bqlpfy/vite-frontend:${VERSION}\` / \`bqlpfy/vite-frontend:latest\` (支持 AMD64/ARM64) + - **Spring Boot Backend** Docker Image: \`bqlpfy/springboot-backend:${VERSION}\` / \`bqlpfy/springboot-backend:latest\` (支持 AMD64/ARM64) ## 📥 Installation Files - \`install.sh\` - GOST 客户端安装脚本 @@ -218,8 +246,9 @@ jobs: --repo ${{ github.repository }} # 上传所有文件到 release - echo "📤 上传 GOST 二进制..." + echo "📤 上传 GOST 二进制文件..." gh release upload "${VERSION}" ./artifacts/gost --clobber + gh release upload "${VERSION}" ./artifacts/gost-arm64 --clobber echo "📤 上传安装脚本..." gh release upload "${VERSION}" ./install.sh --clobber diff --git a/docker-compose-v4.yml b/docker-compose-v4.yml index cae15ff..89f0eb0 100644 --- a/docker-compose-v4.yml +++ b/docker-compose-v4.yml @@ -1,6 +1,6 @@ services: backend: - image: bqlpfy/springboot-backend:2.0.1-beta + image: bqlpfy/springboot-backend:2.0.2-beta container_name: springboot-backend restart: unless-stopped environment: @@ -23,7 +23,7 @@ services: start_period: 60s frontend: - image: bqlpfy/vite-frontend:2.0.1-beta + image: bqlpfy/vite-frontend:2.0.2-beta container_name: vite-frontend restart: unless-stopped ports: diff --git a/docker-compose-v6.yml b/docker-compose-v6.yml index b7e4930..23d35c3 100644 --- a/docker-compose-v6.yml +++ b/docker-compose-v6.yml @@ -1,6 +1,6 @@ services: backend: - image: bqlpfy/springboot-backend:2.0.1-beta + image: bqlpfy/springboot-backend:2.0.2-beta container_name: springboot-backend restart: unless-stopped environment: @@ -23,7 +23,7 @@ services: start_period: 60s frontend: - image: bqlpfy/vite-frontend:2.0.1-beta + image: bqlpfy/vite-frontend:2.0.2-beta container_name: vite-frontend restart: unless-stopped ports: diff --git a/install.sh b/install.sh index 963fe6c..b9ff574 100644 --- a/install.sh +++ b/install.sh @@ -1,6 +1,6 @@ #!/bin/bash # 下载地址 -DOWNLOAD_URL="https://github.com/bqlpfy/flux-panel/releases/download/2.0.1-beta/gost" +DOWNLOAD_URL="https://github.com/bqlpfy/flux-panel/releases/download/2.0.2-beta/gost" INSTALL_DIR="/etc/flux_agent" COUNTRY=$(curl -s https://ipinfo.io/country) if [ "$COUNTRY" = "CN" ]; then diff --git a/panel_install.sh b/panel_install.sh index 0902353..d7de1a6 100755 --- a/panel_install.sh +++ b/panel_install.sh @@ -8,8 +8,8 @@ export LC_ALL=C # 全局下载地址配置 -DOCKER_COMPOSEV4_URL="https://github.com/bqlpfy/flux-panel/releases/download/2.0.1-beta/docker-compose-v4.yml" -DOCKER_COMPOSEV6_URL="https://github.com/bqlpfy/flux-panel/releases/download/2.0.1-beta/docker-compose-v6.yml" +DOCKER_COMPOSEV4_URL="https://github.com/bqlpfy/flux-panel/releases/download/2.0.2-beta/docker-compose-v4.yml" +DOCKER_COMPOSEV6_URL="https://github.com/bqlpfy/flux-panel/releases/download/2.0.2-beta/docker-compose-v6.yml" COUNTRY=$(curl -s https://ipinfo.io/country) if [ "$COUNTRY" = "CN" ]; then 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 442caa0..59ddfd2 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 @@ -21,4 +21,6 @@ public class ForwardDto { private String remoteAddr; private String strategy; + + private Integer inPort; } \ 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 5b17120..24a4bec 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 @@ -25,4 +25,6 @@ public class ForwardUpdateDto { private String strategy; + private Integer inPort; + } \ No newline at end of file diff --git a/springboot-backend/src/main/java/com/admin/service/TunnelService.java b/springboot-backend/src/main/java/com/admin/service/TunnelService.java index 800e399..7b1e995 100644 --- a/springboot-backend/src/main/java/com/admin/service/TunnelService.java +++ b/springboot-backend/src/main/java/com/admin/service/TunnelService.java @@ -57,5 +57,5 @@ public interface TunnelService extends IService { */ R diagnoseTunnel(Long tunnelId); - Integer getNodePort(Long nodeId, Integer type); + Integer getNodePort(Long nodeId, Integer type, Integer port); } 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 f150687..4fcf716 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 @@ -163,7 +163,7 @@ public class ForwardServiceImpl extends ServiceImpl impl List chainTunnels = chainTunnelService.list(new QueryWrapper().eq("tunnel_id", tunnel.getId()).eq("chain_type", 1)); for (ChainTunnel chainTunnel : chainTunnels) { - Integer nodePort = tunnelService.getNodePort(chainTunnel.getNodeId(), 2); + Integer nodePort = tunnelService.getNodePort(chainTunnel.getNodeId(), 2, forwardDto.getInPort()); ForwardPort forwardPort = new ForwardPort(); forwardPort.setForwardId(forward.getId()); @@ -205,7 +205,7 @@ public class ForwardServiceImpl extends ServiceImpl impl return R.err(permissionResult.getErrorMessage()); } - UserTunnel userTunnel = null; + UserTunnel userTunnel; if (currentUser.getRoleId() != 0) { userTunnel = getUserTunnel(currentUser.getUserId(), tunnel.getId().intValue()); if (userTunnel == null) { @@ -236,6 +236,13 @@ public class ForwardServiceImpl extends ServiceImpl impl if (forwardPort == null){ return R.err("部分节点不存在1"); } + if (forwardUpdateDto.getInPort() != null && !forwardUpdateDto.getInPort().equals(forwardPort.getPort())) { + Integer nodePort = tunnelService.getNodePort(forwardPort.getNodeId(), 2, forwardUpdateDto.getInPort()); + if (Objects.equals(nodePort, forwardUpdateDto.getInPort())) { + forwardPort.setPort(nodePort); + forwardPortService.updateById(forwardPort); + } + } GostUtil.AddAndUpdateService(serviceName, limiter, node, existForward, forwardPort, tunnel, "UpdateService"); } diff --git a/springboot-backend/src/main/java/com/admin/service/impl/NodeServiceImpl.java b/springboot-backend/src/main/java/com/admin/service/impl/NodeServiceImpl.java index 48a380c..d8584ea 100644 --- a/springboot-backend/src/main/java/com/admin/service/impl/NodeServiceImpl.java +++ b/springboot-backend/src/main/java/com/admin/service/impl/NodeServiceImpl.java @@ -125,7 +125,7 @@ public class NodeServiceImpl extends ServiceImpl implements No ViteConfig viteConfig = viteConfigService.getOne(new QueryWrapper().eq("name", "ip")); if (viteConfig == null) return R.err("请先前往网站配置中设置ip"); StringBuilder command = new StringBuilder(); - command.append("curl -L https://github.com/bqlpfy/flux-panel/releases/download/2.0.1-beta/install.sh") + command.append("curl -L https://github.com/bqlpfy/flux-panel/releases/download/2.0.2-beta/install.sh") .append(" -o ./install.sh && chmod +x ./install.sh && "); String processedServerAddr = processServerAddress(viteConfig.getValue()); command.append("./install.sh") 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 2f7e2bb..186e4b2 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 @@ -81,7 +81,7 @@ public class TunnelServiceImpl extends ServiceImpl impleme Node node = nodeService.getById(chain_node.getNodeId()); if (node == null) return R.err("节点不存在"); nodes.put(node.getId(), node); - Integer nodePort = getNodePort(chain_node.getNodeId(), 1); + Integer nodePort = getNodePort(chain_node.getNodeId(), 1, null); chain_node.setPort(nodePort); chain_node.setInx(inx); // 设置转发链序号 chainTunnels.add(chain_node); @@ -93,7 +93,7 @@ public class TunnelServiceImpl extends ServiceImpl impleme Node node = nodeService.getById(out_node.getNodeId()); if (node == null) return R.err("节点不存在"); nodes.put(node.getId(), node); - Integer nodePort = getNodePort(out_node.getNodeId(), 1); + Integer nodePort = getNodePort(out_node.getNodeId(), 1, null); out_node.setPort(nodePort); chainTunnels.add(out_node); } @@ -472,7 +472,7 @@ public class TunnelServiceImpl extends ServiceImpl impleme } @Override - public Integer getNodePort(Long nodeId,Integer type) { + public Integer getNodePort(Long nodeId,Integer type, Integer port) { Node node = nodeService.getById(nodeId); if (node == null){ @@ -508,6 +508,9 @@ public class TunnelServiceImpl extends ServiceImpl impleme if (type == 1) { return availablePorts.getLast(); }else { + if (port != null && availablePorts.contains(port)) { + return port; + } return availablePorts.getFirst(); } } diff --git a/vite-frontend/src/config/site.ts b/vite-frontend/src/config/site.ts index ed4cd68..33910e1 100644 --- a/vite-frontend/src/config/site.ts +++ b/vite-frontend/src/config/site.ts @@ -4,7 +4,7 @@ export type SiteConfig = typeof siteConfig; // 缓存相关常量 const CACHE_PREFIX = 'vite_config_'; -const VERSION = "2.0.1-beta"; +const VERSION = "2.0.2-beta"; const APP_VERSION = "1.0.3"; const getInitialConfig = () => { diff --git a/vite-frontend/src/pages/forward.tsx b/vite-frontend/src/pages/forward.tsx index a43a2df..18e1393 100644 --- a/vite-frontend/src/pages/forward.tsx +++ b/vite-frontend/src/pages/forward.tsx @@ -406,6 +406,14 @@ export default function ForwardPage() { newErrors.tunnelId = '请选择关联隧道'; } + // 验证入口端口(可选,如果填写则验证) + if (form.inPort !== null && form.inPort !== undefined) { + const port = Number(form.inPort); + if (isNaN(port) || port < 1 || port > 65535) { + newErrors.inPort = '端口必须在 1-65535 之间'; + } + } + if (!form.remoteAddr.trim()) { newErrors.remoteAddr = '请输入远程地址'; } else { @@ -526,6 +534,7 @@ export default function ForwardPage() { userId: form.userId, name: form.name, tunnelId: form.tunnelId, + inPort: form.inPort, remoteAddr: processedRemoteAddr, strategy: addressCount > 1 ? form.strategy : 'fifo' }; @@ -535,6 +544,7 @@ export default function ForwardPage() { const createData = { name: form.name, tunnelId: form.tunnelId, + inPort: form.inPort, remoteAddr: processedRemoteAddr, strategy: addressCount > 1 ? form.strategy : 'fifo' }; @@ -1605,6 +1615,24 @@ export default function ForwardPage() { ))} + + { + const value = e.target.value; + setForm(prev => ({ + ...prev, + inPort: value ? parseInt(value) : null + })); + }} + isInvalid={!!errors.inPort} + errorMessage={errors.inPort} + variant="bordered" + description="指定入口端口,留空则从节点可用端口中自动分配" + />