【问题标题】:How do I close a socket (ipv4 and ipv6) connection on Windows from any process?如何从任何进程关闭 Windows 上的套接字(ipv4 和 ipv6)连接?
【发布时间】:2019-09-01 09:20:06
【问题描述】:

如何在 Windows 上关闭 tcp v4 和 tcp v6 连接?我不想杀死具有开放连接的整个进程,因为这显然会使其他所有人退出该进程。我需要从一个单独的进程中执行此操作,因此无法访问套接字句柄等。我正在使用 Windows API 来获取 tcp 表等,所以我知道哪些连接处于活动状态。

【问题讨论】:

  • 根据thisSetTcpEntry6 不存在(还没有?)...
  • 嘿,是的,这是我找到的唯一信息。听起来微软只是懒惰。我希望这不会涉及到注入一个非常痛苦的 RST 数据包,必须有一种更简单的方法......

标签: windows sockets winapi


【解决方案1】:

一种方法可能是枚举系统上所有打开的句柄,或者至少是给定目标进程的打开句柄,直到找到您感兴趣的SOCKET 句柄(参见HOWTO: Enumerate handlesSocket Handles、和C++ Get Handle of Open Sockets of a Program - 虽然我不确定您如何能够检索SOCKET 的IP/端口对以与您感兴趣的活动连接进行比较,而无需注入远程getsockname()/getpeername() 调用进入SOCKET的拥有过程。

找到所需的SOCKET 句柄后,您可以使用DuplicateHandle()DUPLICATE_CLOSE_SOURCE 标志1 将其关闭。

1:这就是 Process Explorer 中“关闭句柄”功能的工作原理。

【讨论】:

  • getsockname 和 getpeername 是否适用于重复的句柄?
  • 可能,但这在这种情况下无济于事,因为您必须在没有DUPLICATE_CLOSE_SOURCE 的情况下进行复制,这违背了复制的目的。除非您复制一次,否则在结束比赛时进行测试,然后再次复制。但是你真的不希望复制每个打开的套接字只是为了测试它们的开销,你只想复制你打算关闭的套接字。
  • 可惜SetTcpEntry6不存在
  • 不幸的是,我无法让这个工作,很多奇怪的错误和垃圾数据。很可能我在某处犯了错误,但由于这是一个私有且大部分未记录的 API,我对在生产中使用它感觉不好。
【解决方案2】:

由于我使用的是 C#,因此我无法 PInvoke SetTcpEntry,即使作为具有 app.manifest 文件的管理员,它也总是会发送 317 错误。因此,我创建了一个 C++ .exe 以使用 SetTcpEntry 在命令行上关闭逗号分隔的 ipv4 地址列表,即使没有 app.manifest 文件也可以正常工作。这解决了踢 ipv4 连接的问题。

我尝试使用带有 NtQuerySystemInformation 的获取句柄方法,但始终无法使其正常工作,而且它是一个私有的且大部分未记录的 API,使用起来似乎不安全。

所以,对于 ipv6,我使用 windivert 并将 RST 标志注入到具有特定 IP 地址的 ipv6 数据包中。这就像在使用 windivert 发送数据包之前设置传入数据包的 RST 标志一样简单。缺点是,如果客户端从不发送另一个数据包,ipv6 套接字仍然会无限期地保持打开状态。

也许有一天微软会添加一个 SetTcpEntry6 函数,但在那之前这似乎是唯一现实的方法。

【讨论】:

    猜你喜欢
    • 2014-01-06
    • 1970-01-01
    • 2010-12-09
    • 2015-03-05
    • 2011-07-03
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    相关资源
    最近更新 更多