编辑
2025-02-06
C# 应用
00
请注意,本文编写于 89 天前,最后修改于 89 天前,其中某些信息可能已经过时。

目录

主要特性
应用示例
1. 列出可用的网络设备
2. 捕获实时数据包
3. 截获http的数据包
4. 写入捕获文件
5. HTTP流量分析
6. 实时网络流量统计
结论

SharpPcap是一个功能强大的.NET库,用于跨平台(Windows、Mac、Linux)的数据包捕获。本文将介绍SharpPcap的主要特性,并提供几个详细的应用示例。

主要特性

  1. 跨平台支持:
    • Linux: 支持libpcap
    • Windows: 支持Npcap和WinDivert
    • 所有平台: 支持实时设备列表、统计信息、从实时设备和离线设备读取数据包
  2. 数据包处理:
    • 支持Berkeley数据包过滤器
    • 可以将数据包转储到Pcap文件
    • 支持Pcap和pcap-ng格式(使用libpcap >=1.1.0或npcap时)
  3. 性能优化:
    • 使用ReadOnlySpan<>避免内存分配和复制
    • 提供辅助方法将捕获的数据包转换为对象实例
  4. 其他特性:

应用示例

1. 列出可用的网络设备

C#
using SharpPcap; class Program { static void Main(string[] args) { // 获取所有可用的捕获设备 var devices = CaptureDeviceList.Instance; // 打印每个设备的信息 foreach (var dev in devices) { Console.WriteLine($"设备: {dev.Name}"); Console.WriteLine($"描述: {dev.Description}"); Console.WriteLine(); } } }

image.png

2. 捕获实时数据包

C#
using SharpPcap; using SharpPcap.LibPcap; class Program { static void Main(string[] args) { // 选择第一个可用的设备 using var device = LibPcapLiveDeviceList.Instance[6]; // 打开设备 device.Open(DeviceModes.Promiscuous); // 设置过滤器(可选) device.Filter = "tcp"; // 注册数据包到达事件处理程序 device.OnPacketArrival += Device_OnPacketArrival; // 开始捕获 device.StartCapture(); Console.WriteLine("开始捕获数据包。按任意键停止..."); Console.ReadKey(); // 停止捕获 device.StopCapture(); } static void Device_OnPacketArrival(object sender, PacketCapture e) { var packet = e.GetPacket(); Console.WriteLine($"捕获到数据包: 长度 = {packet.Data.Length} 字节"); Console.WriteLine($"时间戳: {packet.Timeval.Date}"); Console.WriteLine($"数据: {BitConverter.ToString(packet.Data)}"); Console.WriteLine(); } }

image.png

3. 截获http的数据包

C#
using System; using System.Text; using SharpPcap; using PacketDotNet; class Program { static void Main(string[] args) { // 获取所有可用的捕获设备 var devices = CaptureDeviceList.Instance; if (devices.Count < 1) { Console.WriteLine("No devices found. Make sure WinPcap or Npcap is installed."); return; } // 选择第一个设备 var device = devices[6]; Console.WriteLine($"Capturing on {device.Description}"); // 打开设备 device.Open(DeviceModes.Promiscuous); // 设置过滤器,只捕获HTTP流量 device.Filter = "tcp port 80 or tcp port 443"; // 注册数据包到达事件处理程序 device.OnPacketArrival += Device_OnPacketArrival; // 开始捕获 device.StartCapture(); Console.WriteLine("Capturing HTTP traffic. Press any key to stop..."); Console.ReadKey(); // 停止捕获 device.StopCapture(); device.Close(); } static void Device_OnPacketArrival(object sender, PacketCapture e) { var rawPacket = e.GetPacket(); var packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data); var tcpPacket = packet.Extract<TcpPacket>(); if (tcpPacket != null) { var ipPacket = (IPPacket)tcpPacket.ParentPacket; Console.WriteLine($"TCP Packet: {ipPacket.SourceAddress}:{tcpPacket.SourcePort} -> " + $"{ipPacket.DestinationAddress}:{tcpPacket.DestinationPort}"); if (tcpPacket.PayloadData != null && tcpPacket.PayloadData.Length > 0) { string payload = Encoding.ASCII.GetString(tcpPacket.PayloadData); if (payload.StartsWith("GET") || payload.StartsWith("POST") || payload.StartsWith("HTTP/1.1") || payload.StartsWith("HTTP/1.0")) { Console.WriteLine("HTTP Content:"); Console.WriteLine(payload); Console.WriteLine(); } } } } }

image.png

4. 写入捕获文件

C#
using System; using SharpPcap; using PacketDotNet; class Program { static void Main(string[] args) { // 获取第一个网络接口 using var device = CaptureDeviceList.Instance[0]; // 打开设备 device.Open(mode: DeviceModes.Promiscuous, read_timeout: 1000); // 创建捕获文件写入器 using var writer = new CaptureFileWriterDevice("capture.pcap"); writer.Open(device); // 设置数据包到达事件处理 device.OnPacketArrival += (sender, e) => { writer.Write(e.GetPacket()); Console.WriteLine("已写入一个数据包"); }; // 开始捕获 device.StartCapture(); Console.WriteLine("正在捕获数据包,按任意键停止..."); Console.ReadKey(); // 停止捕获 device.StopCapture(); } }

image.png

5. HTTP流量分析

C#
using System; using System.Text; using PacketDotNet; using SharpPcap; class Program { static void Main(string[] args) { // 获取第一个网络接口 using var device = CaptureDeviceList.Instance[6]; device.Open(mode: DeviceModes.Promiscuous, read_timeout: 1000); // 设置过滤器捕获HTTP和HTTPS流量 device.Filter = "tcp port 80 or tcp port 443"; device.OnPacketArrival += (sender, e) => { var rawPacket = e.GetPacket(); var packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data); if (packet is EthernetPacket ethernetPacket) { var ipPacket = ethernetPacket.PayloadPacket as IPPacket; var tcpPacket = ipPacket?.PayloadPacket as TcpPacket; if (tcpPacket != null && tcpPacket.PayloadData != null && tcpPacket.PayloadData.Length > 0) { if (tcpPacket.DestinationPort == 80) { AnalyzeHttpTraffic(tcpPacket); } else if (tcpPacket.DestinationPort == 443) { AnalyzeHttpsTraffic(tcpPacket); } } } }; device.StartCapture(); Console.WriteLine("正在捕获HTTP和HTTPS流量,按任意键停止..."); Console.ReadKey(); device.StopCapture(); } static void AnalyzeHttpTraffic(TcpPacket tcpPacket) { string payload = Encoding.ASCII.GetString(tcpPacket.PayloadData); if (payload.StartsWith("GET") || payload.StartsWith("POST") || payload.StartsWith("PUT") || payload.StartsWith("DELETE")) { string[] lines = payload.Split('\n'); string requestLine = lines[0].Trim(); string[] parts = requestLine.Split(' '); if (parts.Length >= 2) { string method = parts[0]; string url = parts[1]; Console.WriteLine($"HTTP请求: {method} {url}"); } } } static void AnalyzeHttpsTraffic(TcpPacket tcpPacket) { // 获取 IP 包 var ipPacket = (IPPacket)tcpPacket.ParentPacket; if (ipPacket != null) { // 从 IP 包获取源和目标地址 var sourceAddress = ipPacket.SourceAddress; var destinationAddress = ipPacket.DestinationAddress; // 从 TCP 包获取源和目标端口 var sourcePort = tcpPacket.SourcePort; var destinationPort = tcpPacket.DestinationPort; Console.WriteLine($"HTTPS连接: {sourceAddress}:{sourcePort} -> {destinationAddress}:{destinationPort}"); // 检查 TLS 握手包 if (tcpPacket.PayloadData != null && tcpPacket.PayloadData.Length > 0 && tcpPacket.PayloadData[0] == 0x16) { Console.WriteLine("检测到TLS握手包"); } } else { Console.WriteLine("无法获取 IP 包信息"); } } }

image.png

6. 实时网络流量统计

C#
using System; using System.Threading; using SharpPcap; class Program { static long packetCount = 0; static long byteCount = 0; static void Main(string[] args) { // 获取第一个网络接口 using var device = CaptureDeviceList.Instance[6]; device.Open(mode: DeviceModes.Promiscuous, read_timeout: 1000); device.OnPacketArrival += (sender, e) => { Interlocked.Increment(ref packetCount); Interlocked.Add(ref byteCount, e.GetPacket().Data.Length); }; // 启动统计线程 var statsThread = new Thread(PrintStats); statsThread.Start(); device.StartCapture(); Console.WriteLine("正在统计网络流量,按任意键停止..."); Console.ReadKey(); device.StopCapture(); statsThread.Join(); } static void PrintStats() { long lastPacketCount = 0; long lastByteCount = 0; while (true) { Thread.Sleep(1000); long currentPacketCount = Interlocked.Read(ref packetCount); long currentByteCount = Interlocked.Read(ref byteCount); long packetsPerSecond = currentPacketCount - lastPacketCount; long bytesPerSecond = currentByteCount - lastByteCount; Console.WriteLine($"数据包/秒: {packetsPerSecond}, 字节/秒: {bytesPerSecond}"); lastPacketCount = currentPacketCount; lastByteCount = currentByteCount; } } }

image.png

结论

SharpPcap提供了强大而灵活的数据包捕获和处理功能。通过上述示例,我们展示了如何使用SharpPcap来列出网络设备、捕获实时数据包、读写捕获文件以及收集网络统计信息。这些功能使SharpPcap成为网络分析、安全审计和协议开发等领域的有力工具。

在使用SharpPcap时,请注意以下几点:

  1. 确保使用最新版本的SharpPcap,以获得最新的功能和性能改进。
  2. 在Windows平台上,推荐使用Npcap代替已废弃的WinPcap。
  3. 利用ReadOnlySpan<>和其他性能优化特性,以获得最佳的捕获性能。
  4. 对于复杂的数据包解析和创建任务,可以考虑结合使用Packet.Net库。

通过掌握SharpPcap,您将能够开发出功能强大的网络分析和监控工具,为您的.NET项目增添网络捕获的能力。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!