在 Windows 上登录 Codex 客户端时,我遇到了一个看起来像账号问题、实际卡在本地端口上的故障:点击“继续登录”,客户端提示无法启动登录服务器,错误码是 os error 10013。
排查发现,登录需要的 1455 端口落在 Windows 的排除端口范围 1359–1458 内。临时停止 WinNAT 后,登录成功;随后重新启动 WinNAT,客户端仍能正常使用。
这次排障最值得记住的是:没有进程监听某个端口,并不意味着应用就能绑定它。
问题现象:登录服务器还没启动就失败了
当时的完整报错是:
登录失败:failed to start login server: 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013)报错中有两条线索:failed to start login server 指向本地登录服务启动失败,10013 则是 Windows Winsock 的 WSAEACCES,表示套接字访问被拒绝。
排查重点因此落在本地网络绑定环节。仅凭这条报错,还不能判断账号或远端服务是否存在其他问题。
本次涉及的本地地址是:
127.0.0.1:1455浏览器登录需要把认证结果交回本地客户端,因此客户端会先启动一个回调服务。OpenAI 的认证文档也说明,Codex CLI 的浏览器登录使用本地回调,默认地址为 localhost:1455。这能解释此类流程对本地端口的依赖;其他客户端或版本应以实际日志为准。OpenAI 认证文档
本文记录的是这次 Codex Windows 客户端的故障,不把它泛化为所有 ChatGPT 客户端的登录机制。
排查过程:从监听进程查到系统排除范围
先检查端口是否被占用
最直接的检查方式是:
netstat -ano | findstr :1455需要留意输出中的本地地址、状态和 PID:文本匹配到 1455,不一定代表本地 1455 正在监听。PowerShell 也可以直接筛选监听状态:
Get-NetTCPConnection -LocalPort 1455 -State Listen -ErrorAction SilentlyContinue如果查到监听进程,可以通过实际 PID 确认程序身份,再决定如何处理:
# 将 12345 替换为查询到的实际 PIDGet-Process -Id 12345本次没有查到监听 1455 的进程,但客户端依然无法启动登录服务。这说明,检查不能停在“哪个程序占用了端口”这一层。
再检查 Windows 排除端口范围
在管理员 PowerShell 中查看 IPv4 TCP 排除范围:
netsh interface ipv4 show excludedportrange protocol=tcp本次输出中包含:
开始端口 结束端口---------- ----------1359 14581455 位于这个区间内。这是比“机器上装过虚拟化软件”更直接的线索:目标端口确实处于系统排除范围。
如果应用监听 IPv6 地址,还需要检查对应范围;IPv4 和 IPv6 的结果不能相互替代:
netsh interface ipv6 show excludedportrange protocol=tcpnetstat 展示连接和监听状态,而排除范围属于另一类系统网络状态。因此,“没有监听进程”和“端口受系统限制”可以同时成立。
错误码是线索,不能单独定因
这两个错误码需要区分:
| 错误码 | 名称 | 排查含义 |
|---|---|---|
10048 | WSAEADDRINUSE | 地址已在使用,优先检查绑定冲突 |
10013 | WSAEACCES | 访问被拒绝,需要结合权限、绑定方式和系统端口状态判断 |
不能把它们机械理解成“10048 就是进程占用,10013 就是系统保留”。微软文档指出,其他应用、服务或内核驱动独占绑定同一地址,也可能触发 10013。Microsoft Winsock 错误码说明
本次判断依赖的是一组证据:没有发现监听进程、目标端口落入排除范围,以及后续停止 WinNAT 后登录恢复。
本次处理:暂时停止 WinNAT,完成登录后恢复
WinNAT 与 Windows 的 NAT 网络功能有关。停止它可能影响依赖相关网络的虚拟机、容器或其他任务,因此操作前应先确认这些任务可以暂时中断。
以下步骤在本次排障中有效,不是所有 10013 错误的通用修复方法。
1. 停止 WinNAT
在管理员 PowerShell 中执行:
net stop winnat确认服务成功停止后,再尝试登录。如果停止失败,不应假设端口限制已经解除。
2. 重新发起客户端登录
重新打开客户端的登录流程,点击“继续登录”,随后在浏览器中完成认证。
本次操作后,本地登录服务器成功启动,客户端也成功获得登录状态。
3. 恢复 WinNAT
登录完成后执行:
net start winnat如果前面成功停止了服务,即使登录没有成功,也应恢复服务。恢复后可以检查状态,并确认原先使用的虚拟机或容器网络正常:
Get-Service -Name winnat本次恢复 WinNAT 后,Codex 仍然能够正常使用。
为什么有效,以及这个结论的边界
本次观察支持的解释是:WinNAT 相关的网络状态影响了目标端口的可绑定性;停止服务后,这个阻碍暂时消失,使本地登录回调服务能够启动。
不过,现有记录没有追踪该排除范围究竟由哪个组件创建,也没有记录停止前后的完整端口范围变化。因此,不宜断言一定是 HNS、WSL2、Docker 或 Podman 中的某一个组件造成了故障。
简化后的登录过程是:
客户端启动本地回调服务 ↓浏览器完成账号认证 ↓认证结果回到本地客户端 ↓客户端保存并使用登录状态本地回调服务承担登录阶段的工作。OpenAI 文档说明,Codex 会缓存认证信息并在使用期间刷新令牌,这解释了为什么恢复网络服务后,已经建立的登录状态仍可继续使用。OpenAI 登录缓存说明
这次处理只验证了“完成当前登录”的效果。如果以后退出账号、凭据失效或需要重新认证,且端口冲突仍然存在,问题可能再次出现。这是临时绕过,不能据此宣称已经永久修复。
下次遇到类似问题,如何少走弯路
可以按下面的顺序缩小范围:
- 确认失败环节和端口。 从报错或日志中确认是否是本地服务绑定失败,不要预设所有客户端都使用
1455。 - 检查监听进程。 如果有结果,确认本地地址、状态和进程身份。
- 检查对应协议的排除范围。 无监听结果时,也要考虑系统对端口使用的限制。
- 根据证据选择验证动作。 只有在相关证据指向 WinNAT、且能接受网络中断时,才考虑本文的临时处理。
- 恢复服务并复查。 同时验证客户端登录结果和原有网络任务,保留操作前后的记录。
如果需要继续调查系统端口策略,可以先做只读检查:
netsh int ipv4 show dynamicport tcp动态端口范围与排除端口范围不是同一个概念,不能看到端口冲突就直接重设动态端口策略。本次没有通过修改全局端口范围解决问题,也没有验证这类修改的长期效果。
另外,如果实际使用的是 Codex CLI,官方文档提供了设备码登录方式,用于本地回调受阻等场景;能否使用取决于账号或工作区设置。这不是本次执行的步骤,也不代表桌面客户端一定提供相同入口。OpenAI 设备码登录说明
留下的经验:把端口可用性拆成两层检查
这次故障暴露了一个容易忽略的区别:进程有没有使用端口,与系统是否允许应用使用端口,是两个问题。
在带有虚拟网络的 Windows 开发环境中,仅查看监听进程往往不足以解释所有绑定失败。把错误码、监听状态、排除范围和实际操作结果放在一起,才能建立比较可靠的判断。
对这次案例而言,最有复用价值的是在 netstat 没有结果时,知道下一步该检查什么。