Windows端口耗尽问题的诊断与解决
Windows端口耗尽问题的诊断与解决
端口耗尽是Windows系统中常见的网络问题,主要表现为无法建立新的TCP/UDP连接。本文将详细介绍端口耗尽的概念、症状、诊断方法和解决方案,帮助系统管理员快速定位和解决问题。
端口耗尽问题简介
TCP和UDP协议基于端口号工作,任何需要建立TCP/UDP连接的应用程序或服务都需要使用端口。端口分为两种类型:
- 临时端口(动态端口):每台计算机默认用于建立出站连接的端口集。
- 已知端口:特定应用程序或服务的定义端口,如文件服务器服务使用445端口,HTTPS使用443端口,HTTP使用80端口,RPC使用135端口。
当客户端设备与应用程序或服务建立连接时,会使用临时端口连接到已知端口。例如,浏览器会使用临时端口连接到https://www.microsoft.com
的443端口。如果同一浏览器正在与多个网站创建许多连接,则对于浏览器尝试的任何新连接,将使用临时端口。一段时间后,你会注意到连接将开始失败,并且此失败的可能性很大,因为浏览器已使用所有可用端口在外部建立连接,任何建立连接的新尝试都将失败,因为没有更多可用端口。使用计算机上的所有端口时,我们将其称为端口耗尽。
TCP/IP的默认动态端口范围
为了符合Internet分配号码颁发机构(IANA)建议,Microsoft增加了传出连接的动态客户端端口范围。新的默认起始端口为49152,新的默认结束端口为65535。此增加是使用默认端口范围为1025到5000的早期版本的Windows配置的更改。
可以使用以下命令查看计算机上的动态端口范围:
netsh int ipv4 show dynamicport tcp
netsh int ipv4 show dynamicport udp
netsh int ipv6 show dynamicport tcp
netsh int ipv6 show dynamicport udp
范围是针对每个传输(TCP或UDP)单独设置的。端口范围现在是一个具有起点和终点的范围。Microsoft部署运行Windows Server的服务器的客户在内部网络上使用防火墙时,可能会影响服务器之间的RPC通信。在这些情况下,建议重新配置防火墙,以允许49152到65535的动态端口范围内服务器之间的流量。此范围除了服务和应用程序使用的已知端口之外。或者,可以在每台服务器上修改服务器使用的端口范围。使用netsh命令调整此范围,如下所示。上述命令设置TCP的动态端口范围。
netsh int <ipv4|ipv6> set dynamic <tcp|udp> start=number num=range
起始端口为数字,端口总数为范围。下面是示例命令:
netsh int ipv4 set dynamicport tcp start=10000 num=1000
netsh int ipv4 set dynamicport udp start=10000 num=1000
netsh int ipv6 set dynamicport tcp start=10000 num=1000
netsh int ipv6 set dynamicport udp start=10000 num=1000
这些示例命令将动态端口范围设置为从端口10000开始,并在端口10999(1000端口)处结束。可设置的最小端口数范围为255。可设置的最小起始端口为1025。最大结束端口(基于所配置的范围)不能超过65535。要复制Windows Server 2003的默认行为,请使用1025作为启动端口,然后使用3976作为TCP和UDP的范围。此使用模式导致起始端口为1025,结束端口为5000。
端口耗尽的症状
由于出站连接开始失败,你将看到以下行为的许多实例:
- 无法使用域凭据登录计算机,但可以使用本地帐户登录。域登录将要求你联系DC进行身份验证,该身份验证再次是出站连接。如果已设置缓存凭据,则域登录可能仍然有效。
- 组策略更新失败
- 无法访问文件共享
- 来自受影响的服务器的RDP失败
- 计算机上运行的任何其他应用程序都将开始发出错误
重新启动服务器将暂时解决问题,但一段时间后,你会看到所有症状都会恢复。
确认端口耗尽状态
如果怀疑计算机处于端口耗尽状态:
- 尝试建立出站连接。从服务器/计算机访问远程共享,或尝试通过RDP连接到另一个服务器或telnet到端口上的服务器。如果所有这些选项的出站连接失败,请转到下一步。
- 打开事件查看器并在系统日志下查找明确指示当前状态的事件:
- 事件ID4227
- 事件ID4231
- 运行
netstat -anob
命令从服务器收集输出。netstat输出将显示单个PID的TIME_WAIT状态的大量条目。 - 在管理员模式下打开命令提示符,并运行以下命令:
Netsh trace start scenario=netconnection capture=yes tracefile=c:\Server.etl
- 使用网络监视器打开server.etl文件,并在筛选器部分应用筛选器
Wscore_MicrosoftWindowsWinsockAFD.AFD_EVENT_BIND.Status.LENTStatus.Code == 0x209
。应会看到显示STATUS_TOO_MANY_ADDRESSES的条目。如果未找到任何条目,则服务器仍不离开端口。如果找到这些条目,则可以确认服务器处于端口耗尽状态。
排查端口耗尽问题
关键是确定哪个进程或应用程序正在使用所有端口。以下是一些可用于隔离到单个进程的工具:
方法1
首先,查看netstat输出。如果你使用的是Windows 10或Windows Server 2016,则可以运行该命令netstat -anobq
并检查进程ID是否具有最大条目作为BOUND。或者,也可以运行以下PowerShell命令来确定进程:
Get-NetTCPConnection | Group-Object -Property State, OwningProcess | Select -Property Count, Name, @{Name="ProcessName";Expression={(Get-Process -PID ($_.Name.Split(',')[-1].Trim(' '))).Name}}, Group | Sort Count -Descending
大多数端口泄漏都是由于用户模式进程在遇到错误时未正确关闭端口引起的。在用户模式级别,端口(实际套接字)是句柄。TaskManager和ProcessExplorer都能够显示句柄计数,这使你可以确定哪个进程正在使用所有端口。
对于Windows 7和Windows Server 2008 R2,可以更新PowerShell版本以包含上述cmdlet。
方法2
如果方法1没有帮助你识别过程(在Windows 10和Windows Server 2012 R2之前),请查看任务管理器:
- 在详细信息/进程下添加名为“handles”的列。
- 对“handles”列进行排序以确定具有最多句柄数的进程。通常,处理大于3000的进程可能是罪魁祸首,但诸如System、lsass.exe、store.exe、sqlsvr.exe等进程除外。
- 如果这些进程以外的任何其他进程具有更高的数字,请停止该进程,然后尝试使用域凭据登录,并查看它是否成功。
方法3
如果任务管理器没有帮助确定该过程,请使用进程资源管理器调查问题。
使用“进程资源管理器”的步骤:
- 下载进程资源管理器并运行它提升。
- Alt + 选择列标题,选择“选择列”,然后在“进程性能”选项卡上添加句柄计数。
- 选择“视图>显示下窗格”。
- 选择“**查看>****下窗格”视图>**句柄。
- 选择要按该值排序的“句柄”列。
- 检查句柄计数高于其他进程的进程(如果无法建立出站连接,可能会超过10,000)。
- 单击以突出显示一个具有高句柄计数的进程。
- 在下部窗格中,下面列出的句柄是套接字。 (套接字在技术上是文件句柄)。
- 有些是正常的,但大量的不是(数十到千)。关闭有问题的进程。如果还原出站连接,则进一步证明应用是原因。联系该应用的供应商。
最后,如果上述方法没有帮助你隔离进程,建议收集处于问题状态的计算机的完整内存转储。转储将会告诉你哪个进程具有最大句柄数。
解决方案
解决方法是,重启计算机将恢复正常状态,并帮助你暂时解决问题。但是,无法重启时,还可以考虑使用以下命令增加计算机上的端口数:
netsh int ipv4 set dynamicport tcp start=10000 num=1000
此命令将动态端口范围设置为从端口10000开始,并在端口10999(1000端口)处结束。可设置的最小端口数范围为255。可设置的最小起始端口为1025。最大结束端口(基于所配置的范围)不能超过65535。
注意:请注意,增加动态端口范围不是永久解决方案,而是临时的。需要跟踪哪些进程/处理器消耗了最大端口数,并从该进程的角度进行故障排除,了解它消耗如此多的端口数量的原因。
对于Windows 7和Windows Server 2008 R2,可以使用以下脚本以定义的频率收集netstat输出。从输出中,可以看到端口使用趋势。
@ECHO ON
set v=%1
:loop
set /a v+=1
ECHO %date% %time% >> netstat.txt
netstat -ano >> netstat.txt
PING 1.1.1.1 -n 1 -w 60000 >NUL
goto loop
参考资料
- 端口耗尽和你!- 本文详细介绍了netstat状态,以及如何使用netstat输出来确定端口状态
- 检测临时端口耗尽:本文包含将在循环中运行的脚本来报告端口状态。 (适用于Windows 2012 R2、Windows 8、Windows 10和Windows 11)
本文原文来自微软官方文档