Для будущих студентов курса Сетевой инженер и всех интересующихся подготовили полезную статью.
Также приглашаем на открытый вебинар по теме NAT не Firewall. Участники вебинара вместе с экспертом рассмотрят NAT и его использование, почему NAT != firewall, а также различные виды конфигураций для разных ситуаций.
В данной статье будет проведено исследование сетевой подсистемы ОС Windows и Linux, а также предложен план изучения подсистем операционной системы. Основная задача исследования - понять, из чего состоит сетевая подсистема; какие поддерживает протоколы из коробки; какие дополнительные механизмы использует в своей работе.
Disclamer: Статья описывает данные, которые с точки зрения автора помогут понять, как работают операционные системы с моделью TCP/IP, и не претендует на полноту.
Инструментарий и метод исследования
Для исследования операционной системы будем использовать следующие инструменты:
-
Операционная система Linux:
-
git;
-
Visual Stuio Code;
-
-
Операционная система Windows:
-
strings.exe;
-
radare2;
-
hxD Editor;
-
Python;
-
Process Explorer.
-
Инструменты подобраны таким образом, чтобы можно было охватить максимальное количество форматов файлов, которые можно обнаружить в ОС. Для исходного же кода главный инструмент - редактор, который позволяет удобно переходить от исходника к исходнику для разбора кода.
В нашем исследовании будем руководствоваться двумя правилами:
-
Используем всю информацию из документации операционных систем;
-
Проверяем правдивость описанных данных. Для структур данных:
-
В ОС Windows исследуем соответствующие функционалу dll, sys файлы;
-
В ОС Linux исследуем исходные коды и отдельные ветки ядра;
-
Теперь определимся с проблемами, которые вероятно будут нас преследовать на протяжении всего исследования.
Проблемы при исследовании ОС Linux
Основной функционал подсистемы целиком находится в ядре. К счастью, исходный код доступен в сети. Исследование исходного кода таких больших проектов всегда довольно сложная задача. На её сложность может влиять несколько факторов:
-
Субъективные:
-
у каждого исследователя разный уровень экспертизы в области языка программирования, который используется в исходном коде;
-
у каждого исследователя есть свой собственных подход на интерпретацию полученной информации.
-
-
Объективные:
-
ограниченности исследования по времени;
-
объем исходного кода;
-
принятые правила кодирования проекта.
-
Как минимизировать количество действий исследователя, чтобы получить как можно больше полезной и интересной информации? Огромную роль играет правильно настроенное рабочее место. В нашем случае верную настройку определяет набор инструментов, который мы описали в разделе "Инструментарий и метод исследования". Также можно применить небольшой лайфхак и не рассматривать каждую строку исходников ядра, а рассматривать только высокоуровневые элементы. Это сэкономит время на изучение языка программирования и даст возможность разобраться, что к чему. Попробуем применить эту тактику на практике.
Сетевая подсистема Linux
Начнем наше исследование с вот такой интересной картинки:
Картинка представляет собой структуру директорий исходного кода
ядра ОС Linux. На ней видно, что сетевая подсистема вовсе не самая
большая часть операционной системы. По правде говоря, можно собрать
ядро и без этой части. Сегодня это вариант только для
embeded
систем, в общем случае без сети представить
Linux сложно.
Код, который относится к сетевой подсистеме, находится в директории "net". Посмотрим, из чего он состоит.
Исходный код собран по выполняемым задачам. За базовыми элементами можно обратиться в директорию core:
На картинке выделены названия файлов, которые описывают основные
структуры для работы с сетью. Это создание сокетов, хранение
пересылаемых данных и работа с фильтрующей подсистемой
bfp
. Именно этот код переиспользуется для остальной
части сетевой подсистемы.
Оставшиеся файлы в директории "net" описывают работу ядра с различными протоколами. Интересным моментом здесь является то, что фильтрующая подсистема имеет какие-то файлы только в некоторых протоколах и подсистемах:
Прямоугольниками выделены те протоколы и подсистемы, которые
содержат файлы netfilter
. Как видно из картинки,
механизм фильтрации трафика работает не со всеми протоколами. Также
интересно то, что он присутствует не только в протоколах, но и в
более высокоуровневой абстракции -
bridge. Теперь понятно, почему bridge от Linux можно настроить
настолько гибко и контролировать пересылаемые данные.
Что в итоге? Всего по 4м картинкам структуры исходных кодов ядра мы уже обладаем информацией о том, какие поддерживаются протоколы в ядре Linux, какие механизмы интегрированы в протоколы для контроля и фильтрации и где найти базовые элементы, которые позволяют использовать сеть. Попробуем найти эту информацию и в ОС Windows.
ОС Windows: сетевая подсистема
Изучить сетевую подсистему этой ОС так же просто, как в ОС Linux, не получится. Самый большой камень преткновения - закрытый исходный код. Однако давайте попытаемся восстановить информацию о том, как работает сетевая подсистема в рамках этой ОС. В качестве целей будем использовать то, что нашли в Linux:
-
Где располагается код для создания и работы с сокетами;
-
Какой механизм используется для фильтрации;
-
Как имплементированы протоколы.
Сетевая подсистема, согласно документации построена по принципу модели OSI. И также приводится описание того, за счет каких технологий и типов файлов реализуется работа отдельных уровней модели.
Имплементация модели OSI в операционной системе начинается со строго определенных уровней. В данном случае всё начинается на уровне "Канальном" и заканчивается на уровне "Транспортном". Имплементация на каждом уровне своя:
-
Канальный уровень - состоит из MAC и LLC, соответственно и частей имплементации должно быть две:
-
MAC - miniportdriver это драйвер, который контролирует сетевой интерфейс;
-
LLC - protocol driver - драйвер, который используется для обработки данных от сетевых устройств;
-
-
Уровень сети - protocol driver - драйвер, который используется для обработки данных от сетевых устройств;
-
Уровень транспорта - protocol (transport) driver;
Вот и выявилось коренное отличие Windows от Linux - вся логика работы сетевой подсистемы разбита на множество элементов. Каждое устройство, каждый протокол и абстракция имплементированы не в ядре, а в модуле ядра - драйвере, который может быть загружен ядром по запросу. Что это значит для нас? У нас нет исходного кода данных драйверов, а значит мы не можем использовать подход, который использовали при изучении ОС Linux.
Как же быть? При разработке эксплойтов исследователи в качестве отправной точки для восстановления структур внутри ядра Windows используют проект с открытым исходным кодом - ReactOS. Попробуем сделать тоже самое. Давайте найдем части подсистемы и затем спроецируем найденную информацию на реальную ОС Windows.
На экране ниже приведен снимок директории с основными драйверами для сетевой подсистемы:
Попробуем найти такие же файлы в реальной ОС. Заглянем в директорию "%Windows%". В качестве исследуемой системы возьмем Windows 7.
Часть файлов действительно имеет названия файлов, которые присутствуют в реальной ОС.
Один из способов проверки функционала уже скомпилированного
приложения - прочитать используемые им строки. Можем для этого
воспользоваться утилитой strings.exe для
tcpip.sys
:
Похоже, что данные по работе с сетевой подсистемой можно обнаружить именно в этом драйвере. Поищем функции, которые позволяют фильтровать трафик. Как их идентифицировать?
В операционной системе Windows за всё время её существования было 2 технических спецификаций на основании которых создавались драйвера для сетевого взаимодействия: TDI и WinSock. И все эти спецификации использовали отдельный драйвер для того чтобы можно было собирать весь функционал - NDIS. Значит большая часть функций сконцентрирована в этих драйверах:
-
netio.sys
-
tcpip.sys
-
tdi.sys
-
ndis.sys
Но в них все равно нет функций, которые бы могли фильтровать трафик. Почему так? Дело в том, что до Windows 7 фильтрация трафика как такового была имплементирована в отдельных драйверах, которые настраивались за счет интерфейса Windows. Начиная с Windows 7 была реализована так называемая Windows Filtering Platform, которая определила часть драйверов в специальную категорию, которая и призвана фильтровать трафик.
Часть этих фильтров можно найти по обычному поиску в директориях ОС:
Get-ChildItem "C:\WINDOWS\System32" FWPKCLNT.SYS -Recurse | Select-Object FullName Get-ChildItem "C:\WINDOWS\System32" wfplwf.sys -Recurse | Select-Object FullName
Используем утилиту strings.exe на файлы
FWPKCLNT.SYS
и wfplwf.sys
:
Выше представлена часть строк, которые обнаружились в файле
FWPKCLNT.sys
, файл wfplwf.sys
содержал
только названия функций. Почему тогда они здесь вместе? Дело в том,
что в импортах wfplwf.sys
есть функция, которая
берется из файла FWPKCLNT.sy
s:
В итоге:
-
Имплементация всех объектов и механизмов в ядре для работы с протоколами - файлы из директории
%Windows%\System32\Drivers
. Основные из них - netio.sys, ndis.sys, tdi.sys. -
Фильтрацией занимаются драйвера WFP:
FWPKCLNT.sys
,wfplwf.sys
. -
Имплементируются через отдельные одноименные файлы, например:
tcpip.sys
В ОС Linux мы не задумывались о том как приложения получают доступ к структурам ядра и работают с сетью. Там более-менее всё очевидно и только один шаг до функций, но для Windows всё работает по принципу Callback`ов. Поэтому скорее всего будет несколько оберток для взаимодействия. Попробуем найти эти файлы.
Для поиска файлов, которые используются в качестве обертки-библиотеки, можно использовать следующий метод. Для этого создадим мини приложение, которое будет работать с сокетами, принимать и отправлять данные. Исходный код приложения:
import socketHOST = '127.0.0.1' PORT = 10000 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(data)
Запускаем файл в ОС, если не возникло никаких ошибок, то необходимо параллельно запустить инструмент Process Explorer. С помощью этого инструмента мы подсмотрим, чем занимается поток, пока ждет соединения. На картинке ниже отображены все описанные действия:
Слева изображен стек вызовов функций, которые задействованы в
процедуре настройки сокета и перевода его в состояние bind. Этот
набор файлов - mswinsock.dll
(Win Sock 2 Service) и
WS2_32.dll
(Windows Socket 2). Данные библиотеки
используются для того, чтобы предоставить приложениям функции по
работе с сокетами в ОС Windows.
Стоит отметить, что последовательность функций, которые вызываются для работы сокета в ОС, не виден в Process Explorer`е. Если нужно восстановить и эти данные, то нужно использовать отладчик ядра.
Таким образом, проводить исследование подсистем любых ОС и их механизмов можно с исходным кодом и без достаточно выбрать необходимый набор инструментов, а также доступные методы, источники знаний.
Узнать подробнее о курсе Сетевой инженер.
Зарегистрироваться на открытый вебинар по теме NAT не Firewall.