【cdp】windows持久化运行cdp浏览器

【CDP】Windows 持久化运行 CDP 浏览器

背景

最近在 Windows 服务器上使用 Edge 浏览器的 CDP 调试模式,让 Agent 通过 Chrome DevTools Protocol 控制浏览器执行自动化操作。

Edge 启动命令大致如下:

bat 复制代码
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --remote-debugging-port=9222 --user-data-dir="E:\llq"

本地访问:

bat 复制代码
curl http://127.0.0.1:9222/json/version

可以正常返回 CDP 信息。

但是在远程 Windows 服务器上长期运行时,遇到了几个问题:

  1. 通过 MSTSC 手动启动 Edge,过一段时间后 Edge 进程可能退出。
  2. 127.0.0.1:9222 本地可访问,但远程 IP 的 9222 访问失败。
  3. netsh interface portproxy show all 规则还在,但 portproxy 实际没有监听。
  4. 重启 iphlpsvc 后恢复正常。
  5. 需要让 Edge CDP 能够长期稳定运行,异常退出后自动恢复。

最终采用的方案是:

text 复制代码
Edge CDP 启动脚本
+
Windows 任务计划程序
+
portproxy 端口转发
+
watchdog 定时检测和恢复

一、整体架构

最终访问链路如下:

text 复制代码
Agent
  |
  | 访问 http://192.168.113.193:9222
  v
Windows portproxy
  |
  | 转发到 127.0.0.1:9222
  v
Edge CDP

Edge 浏览器只监听本机:

text 复制代码
127.0.0.1:9222

通过 Windows portproxy 暴露给远程 Agent:

text 复制代码
192.168.113.193:9222 -> 127.0.0.1:9222

二、创建运行 CDP 的 BAT 启动脚本

创建目录:

bat 复制代码
mkdir C:\cdp-edge

创建启动脚本:

bat 复制代码
notepad C:\cdp-edge\start-edge-cdp.bat

写入以下内容:

bat 复制代码
@echo off
set EDGE=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
set PROFILE=E:\llq

curl -s http://127.0.0.1:9222/json/version >nul 2>&1
if %errorlevel%==0 exit /b 0

start "" "%EDGE%" ^
  --remote-debugging-port=9222 ^
  --remote-allow-origins=* ^
  --user-data-dir="%PROFILE%" ^
  --no-first-run ^
  --no-default-browser-check ^
  --disable-popup-blocking

参数说明

参数 说明
--remote-debugging-port=9222 开启 CDP 调试端口
--remote-allow-origins=* 允许远程调试连接,避免部分 CDP 客户端连接失败
--user-data-dir=E:\llq 指定独立浏览器用户目录,避免和默认 Edge 用户目录冲突
--no-first-run 禁用首次启动引导
--no-default-browser-check 禁用默认浏览器检查
--disable-popup-blocking 禁用弹窗拦截,减少自动化场景异常

为什么要先 curl 检测?

脚本中有这一段:

bat 复制代码
curl -s http://127.0.0.1:9222/json/version >nul 2>&1
if %errorlevel%==0 exit /b 0

目的是避免重复启动多个 Edge CDP 实例。

如果 127.0.0.1:9222/json/version 已经正常返回,说明 Edge CDP 已经在运行,脚本直接退出。


三、配置 portproxy

如果 Agent 和 Edge 不在同一台机器上,需要让远程机器可以访问 Windows 服务器上的 CDP 端口。

假设 Windows 服务器 IP 是:

text 复制代码
192.168.113.193

添加 portproxy 规则:

bat 复制代码
netsh interface portproxy add v4tov4 listenaddress=192.168.113.193 listenport=9222 connectaddress=127.0.0.1 connectport=9222

查看规则:

bat 复制代码
netsh interface portproxy show all

正常应该看到:

text 复制代码
侦听 ipv4:                 连接到 ipv4:

地址            端口        地址            端口
--------------- ----------  --------------- ----------
192.168.113.193 9222        127.0.0.1       9222

注意:不要这样配置

不要配置成:

bat 复制代码
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=9222 connectaddress=127.0.0.1 connectport=9222

因为 0.0.0.0:9222 会包含 127.0.0.1:9222,很容易造成 portproxy 自己转发给自己,出现大量 ESTABLISHEDTIME_WAIT 连接。

错误链路类似:

text 复制代码
0.0.0.0:9222
  -> 127.0.0.1:9222
      -> 又命中 0.0.0.0:9222
          -> 继续转发

这种情况可能导致 9222 端口异常,甚至短时间内出现大量 TIME_WAIT。


四、配置防火墙策略

如果远程 Agent 需要访问 192.168.113.193:9222,需要放行 Windows 防火墙。

建议只允许 Agent 所在机器 IP 访问,不要暴露给所有地址。

假设 Agent IP 是:

text 复制代码
192.168.113.100

添加防火墙规则:

bat 复制代码
netsh advfirewall firewall add rule name="Allow Edge CDP 9222 From Agent" dir=in action=allow protocol=TCP localip=192.168.113.193 localport=9222 remoteip=192.168.113.100

如果是测试环境,也可以先放开当前内网段:

bat 复制代码
netsh advfirewall firewall add rule name="Allow Edge CDP 9222 From LAN" dir=in action=allow protocol=TCP localip=192.168.113.193 localport=9222 remoteip=192.168.113.0/24

不建议使用:

bat 复制代码
remoteip=any

CDP 端口权限很高,如果被非授权人员访问,可能会直接控制浏览器。


五、创建 watchdog 检测脚本

创建 watchdog 脚本:

bat 复制代码
notepad C:\cdp-edge\watchdog-edge-cdp.ps1

写入以下内容:

powershell 复制代码
$ErrorActionPreference = "SilentlyContinue"

$ListenIp = "192.168.113.193"
$ListenPort = 9222
$LocalCdpUrl = "http://127.0.0.1:9222/json/version"
$RemoteCdpUrl = "http://192.168.113.193:9222/json/version"

$EdgeExe = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
$Profile = "E:\llq"
$LogFile = "C:\cdp-edge\watchdog.log"

function Write-Log($msg) {
    $time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    "$time $msg" | Out-File -Append -Encoding utf8 $LogFile
}

function Test-Url($url) {
    try {
        $r = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5
        return ($r.StatusCode -eq 200)
    } catch {
        return $false
    }
}

function Ensure-IpHelper {
    $svc = Get-Service iphlpsvc
    if ($svc.Status -ne "Running") {
        Write-Log "iphlpsvc not running, starting..."
        Start-Service iphlpsvc
        Start-Sleep -Seconds 3
    }
}

function Ensure-PortProxy {
    $rulesText = (netsh interface portproxy show all) -join "`n"

    $expected = "$ListenIp\s+$ListenPort\s+127\.0\.0\.1\s+$ListenPort"

    if ($rulesText -notmatch $expected) {
        Write-Log "portproxy rule missing, recreating..."

        netsh interface portproxy delete v4tov4 listenaddress=$ListenIp listenport=$ListenPort | Out-Null
        netsh interface portproxy add v4tov4 listenaddress=$ListenIp listenport=$ListenPort connectaddress=127.0.0.1 connectport=$ListenPort | Out-Null

        Restart-Service iphlpsvc -Force
        Start-Sleep -Seconds 3
    }
}

function Start-EdgeCdp {
    Write-Log "starting Edge CDP..."

    Start-Process -FilePath $EdgeExe -ArgumentList @(
        "--remote-debugging-port=9222",
        "--remote-allow-origins=*",
        "--user-data-dir=`"$Profile`"",
        "--no-first-run",
        "--no-default-browser-check",
        "--disable-popup-blocking",
        "--disable-features=TranslateUI"
    )

    Start-Sleep -Seconds 5
}

Ensure-IpHelper
Ensure-PortProxy

$localOk = Test-Url $LocalCdpUrl
$remoteOk = Test-Url $RemoteCdpUrl

if ($localOk -and $remoteOk) {
    Write-Log "OK local and remote CDP healthy."
    exit 0
}

if (-not $localOk) {
    Write-Log "local CDP failed, restarting Edge..."

    Get-Process msedge | Stop-Process -Force
    Start-Sleep -Seconds 3

    Start-EdgeCdp
}

$localOk = Test-Url $LocalCdpUrl
$remoteOk = Test-Url $RemoteCdpUrl

if ($localOk -and -not $remoteOk) {
    Write-Log "local OK but remote failed, restarting iphlpsvc..."

    Restart-Service iphlpsvc -Force
    Start-Sleep -Seconds 3
}

$localOk = Test-Url $LocalCdpUrl
$remoteOk = Test-Url $RemoteCdpUrl

if ($localOk -and $remoteOk) {
    Write-Log "RECOVERED."
} else {
    Write-Log "FAILED after recovery. localOk=$localOk remoteOk=$remoteOk"
}

六、watchdog 脚本逻辑说明

这个脚本主要做几件事。

1. 检查 IP Helper 服务

portproxy 依赖 Windows 的 iphlpsvc 服务。

如果 iphlpsvc 没有运行,脚本会自动启动:

powershell 复制代码
Ensure-IpHelper

2. 检查 portproxy 规则

脚本会执行:

powershell 复制代码
netsh interface portproxy show all

然后判断是否存在:

text 复制代码
192.168.113.193 9222 127.0.0.1 9222

如果规则不存在,就自动重建:

powershell 复制代码
netsh interface portproxy add v4tov4 listenaddress=$ListenIp listenport=$ListenPort connectaddress=127.0.0.1 connectport=$ListenPort

3. 检查本地 CDP

本地检测地址:

text 复制代码
http://127.0.0.1:9222/json/version

如果本地不通,说明 Edge CDP 没有正常运行,脚本会重启 Edge。

4. 检查远程 CDP

远程检测地址:

text 复制代码
http://192.168.113.193:9222/json/version

如果本地通、远程不通,说明 Edge 本身正常,问题大概率在 portproxyiphlpsvc,脚本会重启 iphlpsvc


七、手动测试 watchdog

执行:

bat 复制代码
powershell.exe -ExecutionPolicy Bypass -File C:\cdp-edge\watchdog-edge-cdp.ps1

查看日志:

bat 复制代码
type C:\cdp-edge\watchdog.log

正常日志类似:

text 复制代码
2026-06-11 15:24:05 OK local and remote CDP healthy.

如果看到:

text 复制代码
portproxy rule missing, recreating...

说明脚本检测到 portproxy 规则不存在,并进行了重建。

如果每分钟都出现:

text 复制代码
portproxy rule missing, recreating...

则需要检查 Ensure-PortProxy 函数中的正则匹配逻辑,尤其注意 netsh interface portproxy show all 返回的是多行内容,需要先 join 成字符串:

powershell 复制代码
$rulesText = (netsh interface portproxy show all) -join "`n"

同时 127.0.0.1 里的点号需要转义:

powershell 复制代码
127\.0\.0\.1

八、创建登录启动任务

使用 Windows 任务计划程序,在用户登录时自动启动 Edge CDP。

执行:

bat 复制代码
schtasks /Create /TN "Start Edge CDP On Logon" /TR "C:\cdp-edge\start-edge-cdp.bat" /SC ONLOGON /RL HIGHEST /F

参数说明:

参数 说明
/TN 任务名称
/TR 要执行的命令或脚本
/SC ONLOGON 用户登录时执行
/RL HIGHEST 使用最高权限运行
/F 如果任务已存在则覆盖

手动执行一次:

bat 复制代码
schtasks /Run /TN "Start Edge CDP On Logon"

九、创建 watchdog 定时任务

每分钟执行一次 watchdog 检查:

bat 复制代码
schtasks /Create /TN "Watchdog Edge CDP" /TR "powershell.exe -ExecutionPolicy Bypass -File C:\cdp-edge\watchdog-edge-cdp.ps1" /SC MINUTE /MO 1 /RL HIGHEST /F

手动执行一次:

bat 复制代码
schtasks /Run /TN "Watchdog Edge CDP"

查看任务状态:

bat 复制代码
schtasks /Query /TN "Watchdog Edge CDP" /V /FO LIST

十、验证命令

1. 检查 Edge 本地 CDP

bat 复制代码
curl http://127.0.0.1:9222/json/version

正常会返回类似:

json 复制代码
{
   "Browser": "Microsoft Edge/...",
   "Protocol-Version": "1.3",
   "webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/browser/..."
}

2. 检查远程访问入口

bat 复制代码
curl http://192.168.113.193:9222/json/version

如果这个也正常,说明 portproxy 转发正常。

3. 检查端口监听

bat 复制代码
netstat -ano | findstr :9222

正常情况下应该看到类似:

text 复制代码
TCP    127.0.0.1:9222          0.0.0.0:0      LISTENING    Edge_PID
TCP    192.168.113.193:9222    0.0.0.0:0      LISTENING    svchost_PID

其中:

text 复制代码
127.0.0.1:9222

是 Edge CDP 本地监听。

text 复制代码
192.168.113.193:9222

是 portproxy 对外监听。

4. 检查 portproxy 规则

bat 复制代码
netsh interface portproxy show all

5. 检查 IP Helper 服务

bat 复制代码
sc query iphlpsvc

如果 portproxy 规则存在,但远程 IP 访问失败,可以尝试重启:

bat 复制代码
net stop iphlpsvc
net start iphlpsvc

十一、MSTSC 远程桌面注意事项

如果是在远程 Windows 服务器上通过 MSTSC 手动启动 Edge,需要注意:

  1. 关闭远程桌面窗口,通常只是断开连接,Edge 一般还会继续运行。
  2. 如果执行了注销,Edge 一定会退出。
  3. 如果服务器配置了远程桌面会话超时注销策略,断开一段时间后 Edge 也可能退出。
  4. Edge 是桌面进程,不建议简单用 Windows Service 方式运行。

所以更推荐:

text 复制代码
任务计划程序启动 Edge
+
watchdog 定时检测恢复

而不是单纯依赖 MSTSC 手工启动。


十二、常见问题排查

1. 本地 127.0.0.1:9222 正常,远程 IP:9222 不通

优先检查:

bat 复制代码
netstat -ano | findstr :9222

如果只看到:

text 复制代码
127.0.0.1:9222 LISTENING

没有:

text 复制代码
192.168.113.193:9222 LISTENING

说明 portproxy 没有实际监听。

处理方式:

bat 复制代码
net stop iphlpsvc
net start iphlpsvc

2. portproxy show all 有规则,但实际不监听

这是本次遇到的主要问题之一。

现象:

bat 复制代码
netsh interface portproxy show all

能看到规则。

但是:

bat 复制代码
netstat -ano | findstr :9222

看不到 192.168.113.193:9222 LISTENING

解决:

bat 复制代码
net stop iphlpsvc
net start iphlpsvc

3. 出现大量 TIME_WAIT

如果之前配置过:

text 复制代码
0.0.0.0:9222 -> 127.0.0.1:9222

可能导致 portproxy 自循环。

先删除错误规则:

bat 复制代码
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=9222

然后改成监听具体 IP:

bat 复制代码
netsh interface portproxy add v4tov4 listenaddress=192.168.113.193 listenport=9222 connectaddress=127.0.0.1 connectport=9222

4. Edge 自动退出

检查是否是远程桌面会话被注销:

bat 复制代码
query session

如果会话被注销,用户桌面进程会退出。

建议通过任务计划程序在登录时自动启动,并由 watchdog 定时恢复。


十三、最终部署检查清单

部署完成后,建议确认以下内容。

1. Edge CDP 本地正常

bat 复制代码
curl http://127.0.0.1:9222/json/version

2. 远程入口正常

bat 复制代码
curl http://192.168.113.193:9222/json/version

3. portproxy 规则正常

bat 复制代码
netsh interface portproxy show all

4. 端口监听正常

bat 复制代码
netstat -ano | findstr :9222

5. watchdog 日志正常

bat 复制代码
type C:\cdp-edge\watchdog.log

6. 任务计划存在

bat 复制代码
schtasks /Query /TN "Start Edge CDP On Logon" /V /FO LIST
schtasks /Query /TN "Watchdog Edge CDP" /V /FO LIST

总结

在 Windows 服务器上持久化运行 Edge CDP,不能只依赖 MSTSC 手工启动浏览器。

比较稳定的方式是:

text 复制代码
Edge 使用独立 user-data-dir 启动
portproxy 暴露远程访问入口
防火墙限制访问来源
任务计划程序登录时自动启动 Edge
watchdog 每分钟检测和恢复

最终实现效果:

  1. Edge 异常退出后自动拉起。
  2. iphlpsvc 异常后自动恢复。
  3. portproxy 规则丢失后自动重建。
  4. CDP 本地和远程访问都可以自动检测。
  5. Agent 可以长期稳定连接 Windows 上的 Edge CDP。
相关推荐
前端开发江鸟1 天前
Agent 能跑通以后,我才发现代码不是交付物
agent
花椒技术1 天前
一个人已经有 Agent 了,我们为什么还要建设统 Agent 平台
人工智能·agent·ai编程
百工蜂Agent1 天前
万物皆工具
agent·ai编程
阿里云云原生1 天前
AI Agent 的“自述”不可信:如何构建可取证、可评估、可进化的 Agent 生产流水线?
agent
Jodie同志1 天前
第16~23天:持久化、HITL、流式、MCP与安全
前端·后端·agent
小当家.1051 天前
Prompt工程与上下文管理实战:从模板到Agent Loop的演进
prompt·agent·上下文·loop agent
Jodie同志1 天前
第1~15天:原生Agent、RAG与LangGraph基础(完整代码实操)
前端·后端·agent
for_ever_love__1 天前
python基础语法学习: 数据容器
windows·python·学习
用户469368483201 天前
kimi-code 深度掌握系列文章-终端里的 Agent 界面:CLI/TUI 架构(十五)
agent
Oliver_NI1 天前
RAG 检索为什么需要 Hybrid Search?从 Dense、BM25 到 Reranker
人工智能·agent