你可以可以直接nuget使用 linker.tun
去 https://www.wintun.net/ 下载wintun,使用适合你系统的wintun.dll
1、P/Invoke wintun api和一些windows api
C#
internal static class WinTun{ [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 80)] internal struct MIB_UNICASTIPADDRESS_ROW { [FieldOffset(0)] public ushort sin_family; [FieldOffset(4)] public uint sin_addr; [FieldOffset(32)] public ulong InterfaceLuid; [FieldOffset(60)] public byte OnLinkPrefixLength; [FieldOffset(64)] public int DadState; } [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 104)] internal struct MIB_IPFORWARD_ROW2 { [FieldOffset(0)] public ulong InterfaceLuid; [FieldOffset(12)] public ushort si_family; [FieldOffset(16)] public uint sin_addr; [FieldOffset(40)] public byte PrefixLength; [FieldOffset(48)] public uint NextHop_sin_addr; [FieldOffset(44)] public ushort NextHop_si_family; } [DllImport("iphlpapi.dll", SetLastError = true)] internal static extern void InitializeUnicastIpAddressEntry(ref MIB_UNICASTIPADDRESS_ROW Row); [DllImport("iphlpapi.dll", SetLastError = true)] internal static extern uint CreateUnicastIpAddressEntry(ref MIB_UNICASTIPADDRESS_ROW Row); [DllImport("iphlpapi.dll", SetLastError = true)] internal static extern void InitializeIpForwardEntry(ref MIB_IPFORWARD_ROW2 Row); [DllImport("iphlpapi.dll", SetLastError = true)] internal static extern uint CreateIpForwardEntry2(ref MIB_IPFORWARD_ROW2 Row); [DllImport("kernel32.dll")] internal static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); [DllImport("kernel32.dll")] internal static extern bool SetEvent(IntPtr hEvent); [DllImport("wintun.dll", SetLastError = true)] internal static extern IntPtr WintunCreateAdapter( [MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] string tunnelType, ref Guid guid); [DllImport("wintun.dll", SetLastError = true)] internal static extern uint WintunGetRunningDriverVersion(); [DllImport("wintun.dll", SetLastError = true)] internal static extern void WintunGetAdapterLUID(IntPtr adapter, out ulong luid); [DllImport("wintun.dll", SetLastError = true)] internal static extern IntPtr WintunStartSession(IntPtr adapter, uint capacity); [DllImport("wintun.dll", SetLastError = true)] internal static extern IntPtr WintunGetReadWaitEvent(IntPtr session); [DllImport("wintun.dll", SetLastError = true)] internal static extern IntPtr WintunReceivePacket(IntPtr session, out uint packetSize); [DllImport("wintun.dll", SetLastError = true)] internal static extern void WintunSendPacket(IntPtr session, IntPtr packet); [DllImport("wintun.dll", SetLastError = true)] internal static extern void WintunEndSession(IntPtr session); [DllImport("wintun.dll", SetLastError = true)] internal static extern void WintunCloseAdapter(IntPtr adapter); [DllImport("wintun.dll", SetLastError = true)] internal static extern IntPtr WintunAllocateSendPacket(IntPtr session, uint packetSize); [DllImport("wintun.dll", SetLastError = true)] internal static extern IntPtr WintunOpenAdapter( [MarshalAs(UnmanagedType.LPWStr)] string name); [DllImport("wintun.dll", SetLastError = true)] internal static extern bool WintunDeleteDriver(); [DllImport("wintun.dll", SetLastError = true)] internal static extern void WintunReleaseReceivePacket(IntPtr session, IntPtr packet); [DllImport("wintun.dll", SetLastError = true)] internal static extern void WintunSetLogger(WINTUN_LOGGER_CALLBACK newLogger); internal delegate void WINTUN_LOGGER_CALLBACK( WINTUN_LOGGER_LEVEL level, ulong timestamp, [MarshalAs(UnmanagedType.LPWStr)] string message); internal enum WINTUN_LOGGER_LEVEL { WINTUN_LOG_INFO, /**< Informational */ WINTUN_LOG_WARN, /**< Warning */ WINTUN_LOG_ERR /**< Error */ }}2、创建tun网卡
C#
Guid guid = Guid.NewGuid();//创建网卡IntPtr adapter = WinTun.WintunCreateAdapter("linker", "linker", ref guid);//创建一个会话IntPtr session = WinTun.WintunStartSession(adapter, 0x400000);//获取一个等待对象IntPtr waitHandle = WinTun.WintunGetReadWaitEvent(session);//你的IP和掩码IPAddress address = IPAddress.Parse("10.18.18.2");int prefixLength = 24//设置IP和掩码WinTun.WintunGetAdapterLUID(adapter, out ulong luid);{ WinTun.MIB_UNICASTIPADDRESS_ROW AddressRow = default; WinTun.InitializeUnicastIpAddressEntry(ref AddressRow); AddressRow.sin_family = 2; AddressRow.sin_addr = BinaryPrimitives.ReadUInt32LittleEndian(address.GetAddressBytes()); AddressRow.OnLinkPrefixLength = prefixLength; AddressRow.DadState = 4; AddressRow.InterfaceLuid = luid; uint LastError = WinTun.CreateUnicastIpAddressEntry(ref AddressRow); if (LastError != 0) throw new InvalidOperationException();}//设置MTUnetsh interface ipv4 set subinterface 网卡编号 mtu=1400 store=persistent3、从网卡读取数据
C#
byte[] buffer = new byte[2 * 1024];for (;;){ IntPtr packet = WinTun.WintunReceivePacket(session, out var packetSize); if (packet != 0) { new Span<byte>((byte*)packet, (int)packetSize).CopyTo(buffer.AsSpan(4, (int)packetSize)); ((int)packetSize).ToBytes(buffer); WinTun.WintunReleaseReceivePacket(session, packet); return buffer.AsMemory(0, (int)packetSize + 4); } else { if (Marshal.GetLastWin32Error() == 259L) { WinTun.WaitForSingleObject(waitHandle, 0xFFFFFFFF); } else { return new byte[0]; } }}4、将数据写入网卡
C#
ReadOnlyMemory<byte> buffer; //你的数据IntPtr packet = WinTun.WintunAllocateSendPacket(session, (uint)buffer.Length);if (packet != 0){ buffer.Span.CopyTo(new Span<byte>((byte*)packet, buffer.Length)); WinTun.WintunSendPacket(session, packet); return true;}return false;5、网卡被禁用后如何重新启用
网卡被禁用后,网卡IP消失,重新启用网卡后会是“网线被拔出”状态,所以重新启用后需要重新设置IP和创建新会话
netsh interface set interface linker enable //启用网卡IntPtr oldSession = session;IntPtr oldWaitHandle = waitHandle;session = WinTun.WintunStartSession(adapter, 0x400000); //重新创建会话waitHandle = WinTun.WintunGetReadWaitEvent(session); //重新获取等待句柄//重新给网卡设置IPWinTun.WintunGetAdapterLUID(adapter, out ulong luid);{ WinTun.MIB_UNICASTIPADDRESS_ROW AddressRow = default; WinTun.InitializeUnicastIpAddressEntry(ref AddressRow); AddressRow.sin_family = 2; AddressRow.sin_addr = BinaryPrimitives.ReadUInt32LittleEndian(address.GetAddressBytes()); AddressRow.OnLinkPrefixLength = prefixLength; AddressRow.DadState = 4; AddressRow.InterfaceLuid = luid; uint LastError = WinTun.CreateUnicastIpAddressEntry(ref AddressRow); if (LastError != 0) throw new InvalidOperationException();}WinTun.SetEvent(oldWaitHandle); //取消等待WinTun.WintunEndSession(oldSession); //注销之前的会话
支付宝微信扫一扫,打赏作者吧~
