【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 服务器上长期运行时,遇到了几个问题:
- 通过 MSTSC 手动启动 Edge,过一段时间后 Edge 进程可能退出。
127.0.0.1:9222本地可访问,但远程 IP 的9222访问失败。netsh interface portproxy show all规则还在,但portproxy实际没有监听。- 重启
iphlpsvc后恢复正常。 - 需要让 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 自己转发给自己,出现大量 ESTABLISHED 和 TIME_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 本身正常,问题大概率在 portproxy 或 iphlpsvc,脚本会重启 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,需要注意:
- 关闭远程桌面窗口,通常只是断开连接,Edge 一般还会继续运行。
- 如果执行了注销,Edge 一定会退出。
- 如果服务器配置了远程桌面会话超时注销策略,断开一段时间后 Edge 也可能退出。
- 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 每分钟检测和恢复
最终实现效果:
- Edge 异常退出后自动拉起。
iphlpsvc异常后自动恢复。- portproxy 规则丢失后自动重建。
- CDP 本地和远程访问都可以自动检测。
- Agent 可以长期稳定连接 Windows 上的 Edge CDP。