В этом руководстве я собираюсь объяснить основные концепции перехвата пакетов и почему перехват пакетов является таким мощным инструментом, когда речь идет как о наступательной, так и о оборонительной кибербезопасности. В этом руководстве предполагается, что вы уже знакомы с моделью OSI и структурой пакета.

Если вам нужна дополнительная информация о модели OSI и структуре пакетов, вот несколько полезных ресурсов:





Как работает перехват пакетов

Перехват пакетов является обычным явлением во многих организациях для мониторинга сетевого трафика и защиты своей ИТ-инфраструктуры. Мы часто слышим о таких программах, как Wireshark и Splunk, которые позволяют ИТ-специалистам получать доступ и копаться в перехваченных пакетах в поисках любой вредоносной или опасной сетевой активности. Давайте посмотрим на полуглубокое описание перехвата пакетов и того, как он работает внутри компьютера, чтобы мы могли понять, как писать и читать код перехвата пакетов.

Он начинается с двоичных единиц и нулей. Когда данные передаются по кабелю Ethernet и попадают на компьютер, им предстоит долгий путь к прикладному уровню. Данные сначала вступают в контакт с канальным уровнем, где находится карта NIC, а затем перемещаются вверх по модели OSI, пока приложение не получит полезную нагрузку данных. Данные, о которых идет речь, называются пакетом, и этот пакет восходит по модели OSI во многом подобно эстафетной гонке.

Когда пакет впервые вступает в контакт с сетевой картой, он быстро проходит через ядро ​​и в приложение. Приложение привязывается к сокету, чтобы передавать данные в коммуникационном туннеле с клиентом.

Разработчики ОС поняли, что в некоторых случаях владелец сети может захотеть видеть все сообщения, поступающие через сокет, поэтому они встроили новый тип сокета, называемый необработанным сокетом. При использовании необработанного сокета сетевая карта будет отправлять копию входящих пакетов в необработанный сокет. Вот тут-то и появляется приложение для анализа пакетов. Приложение для анализа пакетов может связываться с необработанным сокетом и обрабатывать входящие пакеты, что позволяет выполнять индивидуальную интеграцию. В следующем разделе я покажу, как написать сниффер пакетов на языке программирования Go.

Go поставляется с предустановленными замечательными сетевыми функциями. Пакет «net» в Go позволяет программистам настраивать серверы, отслеживать трафик и многое другое, но сегодня мы будем использовать его для написания анализатора пакетов.

Написание анализатора пакетов в GO

Шаг 1: импорт зависимостей

Для этого проекта мы будем использовать несколько встроенных пакетов. Нам понадобятся пакеты fmt, log и net для создания сниффера с нуля.

package main

import (
 "fmt"
 "log"
 "net"
)

Шаг 2. Определите сетевой интерфейс, который вы хотите прослушивать

Затем нам нужно дать нашему приложению интерфейс, который мы хотим прослушивать, в моем случае это «eth0». Поскольку это важный элемент, рекомендуется добавить экран ошибок, если интерфейс не может быть найден. iface — это переменная, определяющая сетевой интерфейс.

Затем используется функция net.InterfaceByName(), передавая лицо, определенное для разрешения выбранного сетевого интерфейса. Проверка ошибок размещена в этом блоке кода и может быть следствием некорректного интерфейса или ошибки при разрешении интерфейса.

func main() {
 // Define the network interface to sniff on
 iface := "eth0"

 // Resolve the network interface
 netInterface, err := net.InterfaceByName(iface)
 if err != nil {
  log.Fatal(err)
 }

Шаг 3. Захват пакетов

Далее нам нужно встроить в наш код секцию прослушивания, которая будет подключаться к необработанному сокету и перехватывать входящие сетевые пакеты. С этим блоком кода мы начинаем с использования conn, чтобы открыть соединение с сокетом на интерфейсе. Затем мы используем встроенную функцию для прослушивания сокета net.ListenPacket(). Затем мы устанавливаем фильтр, передавая тип трафика, который мы хотели бы прослушивать. Вы можете найти больше информации об определении сетевого трафика в Go здесь. Мы также определяем интерфейс, который мы обнюхиваем, используя переменную net.Interface.Name, определенную ранее в коде. Затем мы фильтруем ошибки, заявляя, что если err › nil: зарегистрируйте ошибку в нашей системе.

// Open a raw socket and filter the port traffic
 conn, err := net.ListenPacket("ip4:tcp", netInterface.Name)
 if err != nil {
  log.Fatal(err)
 }
 defer conn.Close()

Шаг 4. Сохранение и чтение пакетов

 // Buffer for storing packet data
 buffer := make([]byte, 65536)

 // Start capturing packets
 for {
  // Read packet data into the buffer
  n, _, err := conn.ReadFrom(buffer)
  if err != nil {
   log.Fatal(err)
  }

  // Process the packet
  fmt.Println(buffer[:n])
 }
}

В последнем блоке кода мы сохраняем пакеты в буфере, определяя переменную буфера и массив байтов. Затем мы создаем цикл for по захваченным пакетам в буфере и выводим их на терминал. Имейте в виду, что этот код можно расширить, чтобы отформатировать пакеты и сохранить их отдельным способом, но для этого простого руководства я решил не расширять его, а показать шаблон. Если у вас есть какие-либо рекомендации или вы хотите, чтобы код был расширен, или просто есть вопросы, не стесняйтесь обращаться к нам!

Спасибо, что прочитали!