diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 6152ac1..48ebf07 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -20,6 +20,8 @@ services: MANAGED_PORTAL_HOST_SCAN_IMAGE: "managed-portal:${IMAGE_VERSION:-dev}" volumes: - /var/run/docker.sock:/var/run/docker.sock + ports: + - "${MANAGED_PORTAL_FORWARD_PORT_RANGE:-31000-31255}:31000-31255" networks: - managed-portal diff --git a/internal/webdevice/service.go b/internal/webdevice/service.go index 331f960..8ada553 100644 --- a/internal/webdevice/service.go +++ b/internal/webdevice/service.go @@ -128,13 +128,22 @@ func (s *Service) Scan(r *http.Request) (*ScanResult, error) { } s.allowIP(device.IP) + forwardPort, forwardErr := s.EnsureForwarder(device.IP) + if forwardErr != nil { + result.Errors = append(result.Errors, fmt.Sprintf("%s: 启动%s透明转发失败: %v", iface.Name, device.IP, forwardErr)) + continue + } + + scheme, host := requestBase(r) deviceInfo := DeviceInfo{ - IP: device.IP, - Interface: iface.Name, - Port: device.Port, - TargetURL: fmt.Sprintf("http://%s/", device.IP), - ProxyURL: fmt.Sprintf("/proxy/web/%s/", device.IP), + IP: device.IP, + Interface: iface.Name, + Port: device.Port, + TargetURL: fmt.Sprintf("http://%s/", device.IP), + ProxyURL: fmt.Sprintf("/proxy/web/%s/", device.IP), + DirectURL: buildDirectURL(scheme, host, forwardPort), + ForwardPort: forwardPort, } result.Devices = append(result.Devices, deviceInfo) } diff --git a/internal/webdevice/service_test.go b/internal/webdevice/service_test.go index e4583c5..0e43ea0 100644 --- a/internal/webdevice/service_test.go +++ b/internal/webdevice/service_test.go @@ -71,8 +71,11 @@ func TestScanBuildsProxyURLAndAllowList(t *testing.T) { if result.Devices[0].ProxyURL != "/proxy/web/192.168.1.124/" { t.Fatalf("ProxyURL = %q", result.Devices[0].ProxyURL) } - if result.Devices[0].DirectURL != "" { - t.Fatalf("DirectURL = %q, want empty", result.Devices[0].DirectURL) + if result.Devices[0].DirectURL != "http://10.8.0.14:31124/" { + t.Fatalf("DirectURL = %q", result.Devices[0].DirectURL) + } + if result.Devices[0].ForwardPort != 31124 { + t.Fatalf("ForwardPort = %d, want 31124", result.Devices[0].ForwardPort) } } diff --git a/web/src/views/WebDevices.vue b/web/src/views/WebDevices.vue index a4bf223..4f6cec2 100644 --- a/web/src/views/WebDevices.vue +++ b/web/src/views/WebDevices.vue @@ -37,8 +37,8 @@ show-overflow-tooltip /> @@ -99,7 +99,7 @@ async function handleScan() { } function openDevice(row) { - const url = row?.proxy_url || row?.direct_url; + const url = row?.direct_url || row?.proxy_url; if (!url) { ElMessage.error("设备打开地址无效"); return;