×

# c#在windows 使用wintun虚拟网卡

hqy hqy 发表于2026-04-08 16:35:07 浏览5 评论0

抢沙发发表评论

# c#在windows 使用wintun虚拟网卡

你可以可以直接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=persistent

3、从网卡读取数据

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); //注销之前的会话


打赏

本文链接:https://www.kinber.cn/post/6389.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客