Skip to content

Codex 登录端口冲突问题复盘

日期:2026-06-07 问题:Codex 登录时报错 Sign-in failed: failed to start login server: 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013)


一、问题现象

在 Windows 终端执行 codex login 时,登录流程失败,终端报错:

Sign-in failed: failed to start login server: 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013)

二、Codex 登录原理

终端执行 codex login


Codex 在本地启动 HTTP 服务器,监听 localhost:3000


打开浏览器跳转到 OAuth 登录页面


用户授权成功,浏览器回调 http://localhost:3000/callback?token=xxx


本地服务器接收 token,完成登录

关键依赖:Codex 必须能在 localhost:3000 上成功绑定并监听。

三、根因分析

3.1 Windows 动态端口机制

Windows 在处理外向网络连接时,需要从动态端口池中分配一个临时端口作为本地发送方地址。通过以下命令查看:

cmd
netsh int ipv4 show dynamicport tcp

该机器的动态端口范围为 1024 ~ 15000

3.2 冲突原因

因素说明
Codex 需要的端口3000(固定)
动态端口范围1024 ~ 15000
3000 是否在范围内

3000 落在动态端口池内,当系统随机将 3000 分配给某个外向连接作为临时端口后,该端口即被标记为"使用中"。此时 Codex 尝试绑定 3000 进行监听,Windows 返回 WSAEACCES (10013) 错误——不是权限不够,而是端口已被占用。

3.3 为什么 macOS/Linux 不出这个问题

macOS/Linux 的动态端口范围通常从 3276849152 开始,远高于开发常用的 3000/8000/8080,因此几乎不会冲突。

3.4 影响因素

  • 开机时间越长,临时端口消耗越多,冲突概率越高
  • Docker Desktop / WSL2 / Hyper-V 的 WinNAT 服务会大量预留端口
  • 后台网络活动频繁会加速端口分配

四、排查过程

4.1 检查端口是否被进程占用

cmd
netstat -ano | findstr :3000

结果:3000 端口没有被任何进程监听(LISTENING),但仍无法绑定。

这说明 3000 不是被某个服务"监听"了,而是被系统作为临时端口"标记"了占用。

4.2 检查 WinNAT 服务

cmd
sc query winnat

WinNAT 服务正在运行,它会预留大量端口范围。

4.3 查看端口排除范围

cmd
netsh int ipv4 show excludedportrange protocol=tcp

3000 不在任何排除范围内,属于动态端口池的一部分。

4.4 确认动态端口范围

cmd
netsh int ipv4 show dynamicport tcp

确认起始端口为 1024,覆盖了 3000。

五、解决方案

5.1 永久排除 3000 端口(推荐)

管理员身份打开 PowerShell 或 CMD,依次执行:

powershell
# PowerShell 用分号分隔
net stop winnat; netsh int ipv4 add excludedportrange protocol=tcp startport=3000 numberofports=1; net start winnat
cmd
# CMD 用 && 分隔
net stop winnat && netsh int ipv4 add excludedportrange protocol=tcp startport=3000 numberofports=1 && net start winnat

验证

cmd
netsh int ipv4 show excludedportrange protocol=tcp

列表中出现 3000 即成功。此排除永久生效,重启不丢失。

5.2 临时方案(重启后失效)

仅重启 WinNAT 释放当前被占的临时端口:

cmd
net stop winnat
net start winnat

见效快但不持久,下次遇到同样的端口冲突仍需重复执行。

5.3 终极方案(慎用)

将动态端口范围起始值移到 15000 以后:

cmd
netsh int ipv4 set dynamicport tcp start=15000 num=50535

一劳永逸,但会改变系统网络行为,影响面较大,仅在其他方案无效时考虑。

六、预防措施

6.1 开发常用端口排除

如果你在本机做开发,建议一次性排除常用端口,避免同类问题:

cmd
net stop winnat
netsh int ipv4 add excludedportrange protocol=tcp startport=3000 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=3001 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=4000 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=5000 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=8000 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=8080 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=8443 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=9000 numberofports=1
net start winnat

6.2 识别问题模式

以后遇到类似的 os error 10013EADDRINUSE 报错时,排查思路:

端口绑定失败

    ├─ 有进程在监听? → netstat -ano | findstr :端口号 → taskkill /PID <pid> /F

    └─ 无进程监听但仍失败? → 动态端口冲突

                                    ├─ netsh int ipv4 show excludedportrange protocol=tcp(检查是否已排除)
                                    ├─ netsh int ipv4 show dynamicport tcp(检查动态端口范围)
                                    └─ 排除目标端口(5.1 方案)

6.3 适用于所有 Windows 开发者

该问题不只影响 Codex,任何需要在 Windows 上本地监听端口的服务(开发服务器、OAuth 回调等)都可能遇到。建议新机器环境初始化时就做好端口排除。

七、参考命令速查

场景命令
查看动态端口范围netsh int ipv4 show dynamicport tcp
查看已排除端口netsh int ipv4 show excludedportrange protocol=tcp
排除单个端口netsh int ipv4 add excludedportrange protocol=tcp startport=端口号 numberofports=1
删除排除规则netsh int ipv4 delete excludedportrange protocol=tcp startport=端口号 numberofports=1
重启 WinNATnet stop winnat && net start winnat
查看端口占用netstat -ano | findstr :端口号

八、总结

项目内容
问题本质Windows 动态端口范围过大(1024起),覆盖了开发常用端口
错误码WSAEACCES 10013(端口已被系统临时占用,非权限问题)
最佳修复将常用端口加入 excludedportrange(永久排除)
预防手段新机器初始化时批量排除开发端口
识别口诀10013 + 无进程监听 = 动态端口冲突

Powered by VitePress