From 90d426f9add9b310c3929bc72f8dd0ad34174cb2 Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Mon, 23 Feb 2026 14:00:26 +0800 Subject: [PATCH] fix(cli): gateway status probe with TLS when bind=lan - Use wss:// scheme when TLS is enabled (specifically for bind=lan) - Load TLS runtime to get certificate fingerprint - Pass fingerprint to probeGatewayStatus for self-signed cert trust --- src/cli/daemon-cli/probe.ts | 2 ++ src/cli/daemon-cli/status.gather.ts | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cli/daemon-cli/probe.ts b/src/cli/daemon-cli/probe.ts index 759dad667..9398220f0 100644 --- a/src/cli/daemon-cli/probe.ts +++ b/src/cli/daemon-cli/probe.ts @@ -6,6 +6,7 @@ export async function probeGatewayStatus(opts: { url: string; token?: string; password?: string; + tlsFingerprint?: string; timeoutMs: number; json?: boolean; configPath?: string; @@ -22,6 +23,7 @@ export async function probeGatewayStatus(opts: { url: opts.url, token: opts.token, password: opts.password, + tlsFingerprint: opts.tlsFingerprint, method: "status", timeoutMs: opts.timeoutMs, clientName: GATEWAY_CLIENT_NAMES.CLI, diff --git a/src/cli/daemon-cli/status.gather.ts b/src/cli/daemon-cli/status.gather.ts index d705dba44..0cdae6c6f 100644 --- a/src/cli/daemon-cli/status.gather.ts +++ b/src/cli/daemon-cli/status.gather.ts @@ -19,6 +19,7 @@ import { type PortUsageStatus, } from "../../infra/ports.js"; import { pickPrimaryTailnetIPv4 } from "../../infra/tailnet.js"; +import { loadGatewayTlsRuntime } from "../../infra/tls/gateway.js"; import { probeGatewayStatus } from "./probe.js"; import { normalizeListenerAddress, parsePortFromArgs, pickProbeHostForBind } from "./shared.js"; import type { GatewayRpcOpts } from "./types.js"; @@ -182,7 +183,8 @@ export async function gatherDaemonStatus( const probeHost = pickProbeHostForBind(bindMode, tailnetIPv4, customBindHost); const probeUrlOverride = typeof opts.rpc.url === "string" && opts.rpc.url.trim().length > 0 ? opts.rpc.url.trim() : null; - const probeUrl = probeUrlOverride ?? `ws://${probeHost}:${daemonPort}`; + const scheme = daemonCfg.gateway?.tls?.enabled === true ? "wss" : "ws"; + const probeUrl = probeUrlOverride ?? `${scheme}://${probeHost}:${daemonPort}`; const probeNote = !probeUrlOverride && bindMode === "lan" ? `bind=lan listens on 0.0.0.0 (all interfaces); probing via ${probeHost}.` @@ -220,6 +222,10 @@ export async function gatherDaemonStatus( const timeoutMsRaw = Number.parseInt(String(opts.rpc.timeout ?? "10000"), 10); const timeoutMs = Number.isFinite(timeoutMsRaw) && timeoutMsRaw > 0 ? timeoutMsRaw : 10_000; + // Load TLS config for secure WebSocket connections + const tlsEnabled = daemonCfg.gateway?.tls?.enabled === true; + const tlsRuntime = tlsEnabled ? await loadGatewayTlsRuntime(daemonCfg.gateway?.tls) : undefined; + const rpc = opts.probe ? await probeGatewayStatus({ url: probeUrl, @@ -231,6 +237,7 @@ export async function gatherDaemonStatus( opts.rpc.password || mergedDaemonEnv.OPENCLAW_GATEWAY_PASSWORD || daemonCfg.gateway?.auth?.password, + tlsFingerprint: tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined, timeoutMs, json: opts.rpc.json, configPath: daemonConfigSummary.path,