Технологии AF_PACKET, PCAP, RAW socket, PF_RING. Что их объединяет и в чем различия?

«Технологии AF_PACKET, PCAP, RAW socket, PF_RING. Что их объединяет и в чем различия?» — вопрос из категории Сети, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Все эти технологии объединяет возможность захвата и инжекции сетевых пакетов в обход части или всего сетевого стека операционной системы, что критически важно для задач мониторинга сетевой безопасности (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));