5.36 调整XP SP2并发半开出连接上限 https://scz.617.cn/network/200612262105.txt A: scz@nsfocus XP SP2在tcpip.sys中将并发半开出连接上限固化成10。 所谓并发半开出连接上限,可以理解成建立TCP连接的初始SYN包的并发数目上限。宏 观上同一时刻最多只允许有10个初始SYN包发出,宏观上同一时刻出现的第11个初始 SYN包是直接丢弃还是排队等待处理我就未深究了。 并发半开出连接上限不是并发TCP连接上限。ESTABLISHED状态的TCP连接数目与并发 半开出连接上限无关。 -------------------------------------------------------------------------- Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters] "TcpNumConnections"=dword:00fffffe -------------------------------------------------------------------------- TcpNumConnections这个键值控制的是并发TCP连接上限,有效范围[0,0x00FFFFFE], 缺省值为0x00FFFFFE。你在regedit中很可能找不到这个键值,此时使用缺省值,也 就是最大有效值,没事别创建并修改该键值数据。 在XP SP2上用一个多线程扫描程序扫描几个C类地址,并发线程数指定为256,同时执 行如下命令观察SYN_SENT状态的数目: netstat -na -p tcp | find "SYN_SENT" 或 netstat -na -p tcp | find /C "SYN_SENT" 后一条命令将只显示数目,你看到的应该是10或更小。 过段时间在eventvwr.msc中将看到"Event ID 4226",TCP/IP已经达到并发TCP连接尝 试次数的安全限制。 除了XP SP2,其它早期OS(包括2003 SP1)都没有这个并发半开出连接上限。Vista什 么情况我不知。 最近被迫从XP SP1升级到XP SP2,一时忘了这茬。某日进行多线程扫描时偶然发现指 定单个IP可以获得期待中的信息,并发256个线程扫描时这个IP死活扫不出来,动用 Wireshark抓包,居然连到该IP的SYN包都没有看到,这才想起传说中的限制。 这个限制是固化在tcpip.sys中的,没有注册表项调整它,只能硬剁tcpip.sys。网上 有很多现成的补丁程序,其原理就是直接修改tcpip.sys: http://www.lvllord.de/?lang=en&url=downloads#4226patch 假设你已经应用过这些现成的补丁程序,之后微软的某个Hotfix中包含有tcpip.sys, 那前面的硬剁效果就失去了。此时需要等待别人提供更新后的补丁程序并应用。 下面介绍自剁办法,以英文XP SP2所带5.1.2600.2892版tcpip.sys为例。 -------------------------------------------------------------------------- 0005F560 _InitTCPConn@0 proc near 0005F560 0005F560 6A 00 push 0 ; Depth 0005F562 68 54 43 50 43 push 43504354h ; Tag 0005F567 6A 44 push 44h ; Size 0005F569 6A 00 push 0 ; Flags 0005F56B 68 C2 12 02 00 push offset _TcpConnFree@4 ; Free 0005F570 68 6C AE 01 00 push offset _TcpConnAllocate@12 ; Allocate 0005F575 E8 CE 86 FC FF call _PplCreatePool@24 0005F57A 85 C0 test eax, eax 0005F57C A3 44 44 05 00 mov _TcpConnPool, eax 0005F581 0F 84 67 37 00 00 jz locret_62CEE 0005F587 56 push esi 0005F588 8B 35 B0 F1 04 00 mov esi, ds:__imp__KeInitializeSpinLock@4 0005F58E 68 9C 3E 05 00 push offset _ConnTableLock 0005F593 FF D6 call esi ; KeInitializeSpinLock(x) 0005F595 68 20 43 05 00 push offset _ActiveOpenLock 0005F59A FF D6 call esi ; KeInitializeSpinLock(x) 0005F59C C7 05 1C 00 05 00 0A 00 00 00 mov _ActiveOpenProgressThreshold, 0Ah ; XP SP2在tcpip.sys中将并发半开出连接上限固化成10。 0005F5A6 B8 20 3F 05 00 mov eax, offset _ActiveOpenTable 0005F5AB 5E pop esi 0005F5AC 0005F5AC InitTCPConn_loop: 0005F5AC 89 40 04 mov [eax+4], eax 0005F5AF 89 00 mov [eax], eax 0005F5B1 83 C0 08 add eax, 8 0005F5B4 3D 20 43 05 00 cmp eax, offset _ActiveOpenLock 0005F5B9 7C F1 jl short InitTCPConn_loop 0005F5BB 57 push edi 0005F5BC 68 3F C3 04 00 push offset _ActiveOpenLimitLogCallback@8 0005F5C1 68 00 3F 05 00 push offset _ActiveOpenLimitLogEvent 0005F5C6 E8 83 B6 FB FF call _CTEInitEvent@8 0005F5CB A1 80 96 05 00 mov eax, _TCPTime 0005F5D0 05 00 F0 FF FF add eax, 0FFFFF000h 0005F5D5 6A 14 push 14h 0005F5D7 A3 24 00 05 00 mov _ActiveOpenLimitLogTick, eax 0005F5DC 59 pop ecx 0005F5DD 33 C0 xor eax, eax 0005F5DF BF A0 3E 05 00 mov edi, offset _ConnectCancelArray 0005F5E4 F3 AB rep stosd 0005F5E6 40 inc eax 0005F5E7 5F pop edi 0005F5E8 C3 retn 0005F5E8 _InitTCPConn@0 endp -------------------------------------------------------------------------- 用IDA分析tcpip.sys,加载PDB,在Names窗口中找InitTCPConn,上例中0x0005F59C 处操作的ActiveOpenProgressThreshold即并发半开出连接上限。将0x0005F5A2处的 "0A 00 00 00"改成"FE FF FF 00",意味着上限被调整成16711679。在IDA中直接可 以看到VA/0x0005F5A2对应Offset/0x0004F5A2。 分别备份如下两处的tcpip.sys。这不是必要步骤,但有备无患,强烈建议: %systemroot%\system32\drivers\tcpip.sys tcpip.sys.old %systemroot%\ServicePackFiles\i386\tcpip.sys tcpip.sys.orig 然后将%systemroot%\system32\drivers\tcpip.sys复制到临时目录,在临时目录里 用你熟悉的16进制编辑工具按前述介绍修改tcpip.sys。修改驱动文件时务必重新计 算校验和并修改。本例原版校验和是0x0005F865,修改版校验和应该是0x0005F959, 这个可以用Stud_PE或等价工具完成。 > fc /b tcpip.sys.old tcpip.sys 00000130: 65 59 00000131: F8 F9 0004F5A2: 0A FE 0004F5A3: 00 FF 0004F5A4: 00 FF 将临时目录里修改好的tcpip.sys严格地按如下顺序复制到相应目录: %systemroot%\ServicePackFiles\i386\ %systemroot%\system32\dllcache\ %systemroot%\system32\drivers\ 在资源管理器里确认%systemroot%\system32\drivers\tcpip.sys未因SFC而被自动恢 复成某个早期版本。重启OS使之生效。可用多线程扫描程序结合netstat确认效果。