手动保留常用端口,解决 Windows 端口被 Hyper-V / WinNAT 占用的问题

对于 Windows 10 及 Windows 11,当启用 Hyper-V 或者虚拟机平台后,Windows NAT 服务会随机保留一些端口以便于提供 NAT (网络地址转换) 服务,以实现虚拟机的上网。这些端口范围是随机确定的,因此很容易导致开发时遇到端口占用问题。比如会遇到以下错误:

  • Error: listen EADDRINUSE: address already in use :::3000
  • 以一种访问权限不允许的方式做了一个访问套接字的尝试。
  • An attempt was made to access a socket in a way forbidden by its access permissions

除此以外,还可能会遇到明明服务启动成功但是却访问不了的问题,这也很有可能是因为端口被 WinNAT 给占了。

解决方案

网络上普遍建议重新设置一下「TCP 动态端口范围」(如文章 解决 Windows 10 端口被 Hyper-V 随机保留(占用)的问题 ),但是这种方法并不总是有效,因为你并不知道自己未来会即兴用到哪些端口,如果端口分的少了,又会导致其他问题,比如因为可用端口不够用而妨碍上网。

好在,Windows有一个很有趣的特性,就是用户可以 自行保留端口 给用户态程序使用。被用户保留的端口只能被用户态程序分配使用,却不能被内核驱动程序和服务使用。比如我设置保留 1080 端口后,Clash 这类普通用户态程序可以直接申请到这个端口,但是 IIS、WinNAT 等内核驱动程序和服务试图申请时却会被系统拒绝。这样一来,就可以避免端口被 WinNAT 占用的问题。

操作步骤

  1. 以管理员身份打开命令提示符(Win+X,A)。
  2. 运行以下命令,查看目前「TCP 动态端口」的范围
netsh int ipv4 show dynamicport tcp

得到类似如下的输出:

协议 tcp 端口排除范围

开始端口    结束端口
----------    --------
         6           6
        80          80
      1080        1088     *
      5357        5357
      7058        7058
      8000        8079     *
     50000       50059     *
     53317       53317     *
     56052       56151
     56152       56251
     56252       56351
     56352       56451
     56452       56551
     ... 省略 ...

* - 管理的端口排除。

需要注意一下这个输出:

  • 首先前几行列出(表中为 6、80)的是 IIS 使用的端口。如果你的端口是在这里被占用了,那么你需要看看 IIS 那边是怎么个事。
  • 然后,有 * 标记的是我们自行保留的端口,其他的就是被 Windows NAT 服务随机保留的端口。
  • 剩下的,就是 Windows NAT 服务随机保留的端口。这些端口是不固定的,每次重启都会变。
  1. 暂时停止 WinNAT 服务

必须先停止 WinNAT 服务以释放被占用的端口。

net stop winnat
  1. 保留想要使用端口

startport 表示起始端口,numberofports 表示要保留的端口数量。比如保留 1080~1089 端口:

netsh int ipv4 add excludedportrange protocol=tcp startport=1080 numberofports=10

如果提示 另一个程序正在使用此文件,进程无法访问 ,请先关掉所有已占用这个范围的端口的程序。

  1. 重新启动 winnat 服务
net start winnat
  1. 完成

同理可以设置 UDP 的端口保留,但是 WinNAT 并不会占用 UDP 端口,因此一般不需要设置。通常也不需要设置 IPv6 的端口保留,因为 Windows 压根就不支持 IPv6 NAT / NAT66,自然不存在端口占用一说。

附:删除保留的端口

可以使用以下命令删除自行保留的端口:

netsh int ipv4 del excludedportrange protocol=tcp startport=1080 numberofports=9

正在加载评论。你可能需要科学上网才能正常加载评论区