You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux平台下实现C#网络抓包工具遇阻及解决方案咨询

解决Linux下C# Raw Socket捕获IP包的兼容性问题

一、Linux不支持ProtocolType.IP的原因

Linux和Windows的Raw Socket实现机制存在本质差异:

  • Windows允许直接通过ProtocolType.IP创建Raw Socket来接收所有IP包,同时提供IOControlCode.ReceiveAll这类专属命令开启全量捕获。
  • Linux的Raw Socket权限管控和规则更严格:不能直接用ProtocolType.IP创建此类Socket,它要求Raw Socket必须绑定到具体传输层协议(如ICMP/TCP/UDP);同时IOControlCode.ReceiveAll是Windows专属的IO控制指令,Linux内核没有对应实现,这就是你遇到Protocol not supported错误的核心原因。

二、Linux平台的替代方案

方案1:原生Linux Raw Socket实现(无需第三方库)

通过Linux专属的AddressFamily.Packet创建链路层Socket,配合平台判断逻辑实现跨平台兼容:

using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Runtime.InteropServices;

namespace Watchdog.IPListener
{
    class IPListener
    {
        static Socket socket;
        static byte[] Buffer = new byte[24576];
        static int PackagesReceived = 0;

        static public void StartCapturing(string ipaddress)
        {
            try
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    // Windows原有逻辑保留
                    socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
                    socket.Bind(new IPEndPoint(IPAddress.Parse(ipaddress), 0));
                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AcceptConnection, true);
                    byte[] inBytes = new byte[4] { 1, 0, 0, 0 };
                    byte[] outBytes = new byte[4];
                    socket.IOControl(IOControlCode.ReceiveAll, inBytes, outBytes);
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    // Linux下创建链路层Raw Socket
                    socket = new Socket(AddressFamily.Packet, SocketType.Raw, ProtocolType.IP);
                    // 绑定到目标IP对应的网卡
                    socket.Bind(new IPEndPoint(IPAddress.Parse(ipaddress), 0));
                    // 增大接收缓冲区避免丢包
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 1024 * 1024);
                }

                StartReceiving();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex);
            }
        }

        public static void StartReceiving()
        {
            while (true)
            {
                try
                {
                    EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
                    int bytesReceived = socket.ReceiveFrom(Buffer, 0, Buffer.Length, SocketFlags.None, ref remoteEP);
                    if (bytesReceived > 0)
                    {
                        PackagesReceived++;
                        ConvertReceivedData(Buffer, bytesReceived);
                    }
                    Array.Clear(Buffer, 0, Buffer.Length);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Receive Exception: " + ex);
                    break;
                }
            }
        }

        // 保留你原有的数据解析逻辑
        static void ConvertReceivedData(byte[] buffer, int length)
        {
            Console.WriteLine($"Received {length} bytes, total packages: {PackagesReceived}");
            // 此处添加你的IP包解析代码
        }
    }
}

Linux下运行注意事项

  • 必须以root权限运行(sudo执行程序),Raw Socket需要系统级权限。
  • 捕获的数据包包含以太网帧头,需要手动解析掉帧头才能获取IP包内容。

方案2:使用跨平台捕获库(推荐)

用SharpPcap(基于libpcap/WinPcap的C#封装),它已经封装了Windows和Linux的底层差异,无需手动处理平台兼容:

using SharpPcap;
using PacketDotNet;

namespace Watchdog.IPListener
{
    class IPListener
    {
        static public void StartCapturing(string ipaddress)
        {
            // 找到目标IP对应的网卡设备
            ICaptureDevice targetDevice = null;
            foreach (var dev in CaptureDeviceList.Instance)
            {
                if (dev.Addresses.Any(a => a.Addr?.ToString() == ipaddress))
                {
                    targetDevice = dev;
                    break;
                }
            }

            if (targetDevice == null)
            {
                Console.WriteLine("No matching network device found for the specified IP");
                return;
            }

            // 设置包捕获回调
            targetDevice.OnPacketArrival += (sender, e) =>
            {
                var packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
                var ipPacket = packet.Extract<IpPacket>();
                if (ipPacket != null)
                {
                    Console.WriteLine($"IP Packet: {ipPacket.SourceAddress} -> {ipPacket.DestinationAddress}");
                    // 此处添加你的包解析逻辑
                }
            };

            // 启动捕获
            targetDevice.Open(DeviceMode.Promiscuous, 1000);
            targetDevice.StartCapture();
            Console.WriteLine("Capturing started... Press any key to stop");
            Console.ReadKey();
            targetDevice.StopCapture();
            targetDevice.Close();
        }
    }
}

优势

  • 自动适配Windows/Linux平台,无需手动判断。
  • 提供封装好的数据包解析类(如IpPacket/TcpPacket),省去手动解析协议头的工作量。
  • 支持混杂模式、BPF过滤规则等高级功能。

内容的提问来源于stack exchange,提问作者Funkhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:47:28