Ответ
Все эти технологии объединяет возможность захвата и инжекции сетевых пакетов в обход части или всего сетевого стека операционной системы, что критически важно для задач мониторинга сетевой безопасности (IDS/IPS), анализа производительности, отладки и создания специализированных сетевых приложений.
Ключевые различия:
| Технология | Уровень / Интерфейс | Производительность | Сложность | Кроссплатформенность | Основное применение |
|---|---|---|---|---|---|
RAW Sockets (SOCK_RAW) |
Сетевой уровень (L3) — IP-пакеты. | Низкая/Средняя. Каждое копирование пакета из ядра в пользовательское пространство. | Низкая. Простой API на уровне сокетов. | Условная (есть в Linux, BSD, Windows с отличиями). | Отправка кастомных IP-пакетов (пинги, трассировки), простой захват. |
AF_PACKET (aka PF_PACKET, SOCK_DGRAM/SOCK_RAW) |
Канальный уровень (L2) — Ethernet-фреймы. | Высокая. Позволяет использовать PACKET_MMAP/PACKET_RX_RING для снижения оверхеда. |
Средняя. Требует работы с сетевыми интерфейсами и фильтрацией. | В основном Linux. | Высокопроизводительный захват и отправка сырых фреймов (снифферы, мосты). |
| libpcap (PCAP) | Абстракция над RAW/AF_PACKET и другими механизмами ОС. | Средняя. Оверхед из-за абстракции и дополнительной буферизации. | Низкая. Единый простой API для всех платформ. | Отличная (Linux, Windows, macOS, BSD). | Кроссплатформенные снифферы (tcpdump, Wireshark), быстрая разработка. |
| PF_RING (и его вариант PF_RING ZC — Zero Copy) | Канальный уровень (L2), обход стандартного стека через специальный драйвер. | Очень высокая, особенно ZC режим (минимальные копирования, обработка на уровне ядра). | Высокая. Требует установки модуля ядра и линковки со специальной библиотекой. | В основном Linux. | Обработка трафика на скоростях 10/40/100 Gbps (мониторинг безопасности, анализ в реальном времени). |
Практический выбор:
- Для написания кроссплатформенного сниффера или скрипта использую libpcap.
- Для высокопроизводительного захвата в Linux-приложении использую AF_PACKET с PACKET_MMAP.
- Для задач, требующих обработки трафика на предельной скорости линии (например, для кастомного балансировщика или IDS), рассматриваю PF_RING ZC или DPDK.
- RAW sockets применяю для узких задач работы именно с IP-пакетами, где не нужен доступ к Ethernet-заголовкам.
Пример создания AF_PACKET сокета для захвата всех пакетов:
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("socket");
return 1;
}
// Привязка к интерфейсу
struct sockaddr_ll sll;
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = if_nametoindex("eth0");
sll.sll_protocol = htons(ETH_P_ALL);
bind(sockfd, (struct sockaddr*)&sll, sizeof(sll));