【转载】 在windows系统中关闭全局socket连接,可跨进程实现“断网”

原文链接: how-do-i-close-a-socket-ipv4-and-ipv6-connection-on-windows-from-any-process

c# 代码
`using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

// add 2.0.0 version as nuget package
using DigitalRuby.IPBanCore;

namespace YourNamespace;

///


/// Socket closer interface
///

public interface ISocketCloser
{
///
/// Close a socket using low level windows API. Handles ipv4 and ipv6.
///

/// Local end point
/// Remote end point
/// True if closed, false if not
bool CloseSocket(IPEndPoint local, IPEndPoint remote);
}

///


/// Close sockets on Windows or Linux
///

public partial class SocketCloser : ISocketCloser
{
private const int MIB_TCP_STATE_DELETE_TCB = 12;

private static readonly byte[] moduleId = [0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x4A, 0x00, 0xEB, 0x1A, 0x9B, 0xD4, 0x11, 0x91, 0x23, 0x00, 0x50, 0x04, 0x77, 0x59, 0xBC];
private static readonly IntPtr moduleIdPtr;

[LibraryImport("iphlpapi.dll", SetLastError = true)]
private static partial uint SetTcpEntry(ref MIB_TCPROW pTcpRow);

[LibraryImport("nsi.dll", SetLastError = true)]
private static partial uint NsiSetAllParameters(uint action, uint flags, IntPtr moduleId, uint operation, IntPtr buffer, uint bufferLength, IntPtr metric, uint metricLength);

[StructLayout(LayoutKind.Sequential)]
private struct MIB_TCPROW
{
    public uint dwState;
    public uint dwLocalAddr;
    public uint dwLocalPort;
    public uint dwRemoteAddr;
    public uint dwRemotePort;
}

[StructLayout(LayoutKind.Sequential)]
private struct KillTcpSocketData_V6
{
    public ushort wLocalAddressFamily;
    public ushort wLocalPort;
    public uint bReserved1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] bLocal;
    public uint dwLocalScopeID;

    public ushort wRemoteAddressFamily;
    public ushort wRemotePort;
    public uint bReserved2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] bRemote;
    public uint dwRemoteScopeID;
};

static SocketCloser()
{
    moduleIdPtr = Marshal.AllocHGlobal(moduleId.Length);
    Marshal.Copy(moduleId, 0, moduleIdPtr, moduleId.Length);
}

/// <inheritdoc />
public bool CloseSocket(IPEndPoint local, IPEndPoint remote)
{
    if (OSUtility.IsLinux)
    {
        return CloseSocketLinux(local, remote);
    }
    else if (OSUtility.IsWindows)
    {
        return CloseSocketWindows(local, remote);
    }

    return false;
}

private static bool CloseSocketLinux(IPEndPoint local, IPEndPoint remote)
{
    // sudo ss --kill state all src IP_ADDRESS:PORT dst IP_ADDRESS:PORT
    string command = $"ss --kill state all src \"{local.Address}:{local.Port}\" dst \"{remote.Address}:{remote.Port}\"";
    OSUtility.StartProcessAndWait("sudo", command, 0);
    return true;
}
private static bool CloseSocketWindows(IPEndPoint local, IPEndPoint remote)
{
    var localPortFixed = (ushort)IPAddress.HostToNetworkOrder((short)local.Port);
    var remotePortFixed = (ushort)IPAddress.HostToNetworkOrder((short)remote.Port);

    if (local.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
    {
        MIB_TCPROW row = new()
        {
            dwState = MIB_TCP_STATE_DELETE_TCB,
            dwLocalAddr = local.Address.ToUInt32(false),
            dwLocalPort = (uint)localPortFixed,
            dwRemoteAddr = remote.Address.ToUInt32(false),
            dwRemotePort = (uint)remotePortFixed
        };
        var result = SetTcpEntry(ref row);
        return result == 0 || result == 317;
    }
    else if (local.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
    {
        KillTcpSocketData_V6 row6 = new()
        {
            wLocalAddressFamily = (ushort)AddressFamily.InterNetworkV6,
            wLocalPort = localPortFixed,
            bLocal = local.Address.GetAddressBytes(),
            bRemote = remote.Address.GetAddressBytes(),
            bReserved1 = 0,
            bReserved2 = 0,
            dwLocalScopeID = (uint)IPAddress.HostToNetworkOrder(local.Address.ScopeId),
            dwRemoteScopeID = (uint)IPAddress.HostToNetworkOrder(remote.Address.ScopeId),
            wRemoteAddressFamily = (ushort)AddressFamily.InterNetworkV6,
            wRemotePort = remotePortFixed
        };

        // Assume global module ID and other parameters are correctly set
        var ptrSize = Marshal.SizeOf<KillTcpSocketData_V6>();
        var ptr = Marshal.AllocHGlobal(ptrSize);
        try
        {
            // Call the undocumented API (the values for module ID, etc., must be correct)
            Marshal.StructureToPtr(row6, ptr, false);
            var result = NsiSetAllParameters(1, 2, moduleIdPtr, 16, ptr, (uint)ptrSize, IntPtr.Zero, 0);
            return result == 0 || result == 317;
        }
        finally
        {
            // Cleanup
            Marshal.FreeHGlobal(ptr);
        }
    }

    return false;
}

}`

posted @ 2025-12-17 22:03  manreborn  阅读(3)  评论(0)    收藏  举报