Способы фильтрации сетевого траффика в Windows 9x/2000/Net.2003 Server — Архив WASM.RU
Введение.
В данной статье даются основные сведения по способам фильтрации сетевого траффика в Windows 9x/2000/Net.2003 Server, даётся описание фильтрации IP-траффика в Windows 2000 на основе Windows 2000 Filter-Hook Driver способа.Также указываются особенности реализации других методов фильтрации.
Часть первая, теоретическая.
Способы фильтрации сетевого трафика .
Существует несколько способов фильтрации сетевого траффика .Для начала кратко рассмотрим основы сетевой подсистемы Windows:
1) NDIS. В 1989 году Microsoft и 3Com совместно разработали Network Driver Interface Specification (NDIS), которая позволяет драйверам сетевых протоколов использовать сервисы сетевых интерфейсов (отправка/прием сетевых пакетов) скрывая детали их реализации. Драйвер сетевого адаптера, разработанный в соответствии с этой спецификацией, принято называть NDIS минипортом (miniport).Одно из преимуществ - то, что код свободно переносится из 9x/ME - winNT/2000 . Детальное описание предмета можно найти в документации DDK (раздел NetworkDrivers), вкратце NDIS описывает правила (интерфейсы и структуры), в соответствии, с которыми должны разрабатываться драйвера сетевых адаптеров, а так же предоставляет библиотеку функций, к которой должен обращаться разработчик вместо прямого использования сервисов ядра.
2) Драйвера сетевых протоколов. Вкратце, драйвер сетевого протокола (такого как, например TCP/IP) для работы с сетевыми интерфейсами использует функции уже упомянутой библиотеки NDIS и может предоставлять TDI (Transport Data Interface) вышележащим уровням (TDI-клиентам, одним из типичных представителей которых в ядре NT/2000/XP является afd.sys - kernel-mode часть Windows Sockets).
3) User-Mode DLL's которые формируют интерфейс WindowsSockets. Это ws2_32.dll, msafd.dll, wshtcpip.dll и другие.
Тех, кто хочет более детально рассмотреть сетевую подсистему Windows , отсылаю к David Solomon, Mark Russinovich : Inside Windows 2000, часть 13.
Технологии фильтрации:
Технологии фильтрации в User-mode автор не рассматривает.
Технологии фильтрации сетевого трафика в режиме ядра:
1) Kernel-mode sockets filter. Эта технология применима для WindowsNT/2000. Основана на перехвате всех вызовов из msafd.dll (самая низкоуровневая user-mode DLL из состава Windows Sockets) к модулю ядра afd.sys (kernel-mode часть WindowsSockets). Данная технология требует аккуратного обращения с интерфейсами AFD , т.к. они изменяются в разных версиях NT. AFD является TDI клиентом и реализует приём/отправку данных через драйвер протокола. Msafd.dll сообщает AFD название протокола для каждого сокета.Для более подробного изучения отправляю в Inside Windows 2000, раздел 13, подраздел Networking APIs.Способ бесполезен при маршрутизации, т.к. она осуществляется внутри TCPIP.SYS(иногда и вне его - поиск по DDK: Fast Forwarding Path - происходит внутри NDIS ) и не доходит до сокетов. Хотя данный способ удобен для шифрования потоков данных и QoS - Quality of Service - предоставляется специальное API (смотреть в MSDN - поиск по QOS Reference).
2) TDI-filter driver. Технология применима как в Windows 9x/ME так и в WindowsNT/2000, хотя конкретные реализации сильно отличаются. Что касается Windows NT/2000, то в случае TCP/IP фильтрации необходимо перехватывать все вызовы, направленные устройствам (devices) созданным модулем tcpip.sys (\Device\RawIp, \Device\Udp, \Device\Tcp). Технология достаточно известная и используется в ряде коммерческих продуктов (например, OutpostFirewall).
3) NDIS Intermediate Driver Способ очень неудобен в инсталляции и программировании. Желающие могут изучить DDK. Ниже приведён пример кода, показывающего громоздкость программирования :
Код (Text):
local status: NTSTATUS local PChars: NDIS_PROTOCOL_CHARACTERISTICS local MChars: NDIS_MINIPORT_CHARACTERISTICS local Param: PNDIS_CONFIGURATION_PARAMETER local Name1: NDIS_STRING local WrapperHandle:NDIS_HANDLE local DriverHandler: NDIS_HANDLE local ProtHandler: NDIS_HANDLE mov DriverHandler,NULL mov ProtHandler,NULL invoke NdisInitializeWrapper,addr WrapperHandle,pDriverObject, pusRegistryPath,NULL invoke RtlZeroMemory,addr MChars,sizeof NDIS_MINIPORT_CHARACTERISTICS mov MChars.MajorNdisVersion, 5 mov MChars.MinorNdisVersion, NULL mov MChars.InitializeHandler, offset MPInitialize mov MChars.QueryInformationHandler, offset MPQueryInformation mov MChars.SetInformationHandler, offset MPSetInformation mov MChars.ResetHandler, offset MPReset mov MChars.TransferDataHandler, offset MPTransferData mov MChars.HaltHandler, offset MPHalt mov MChars.CheckForHangHandler, NULL mov MChars.SendHandler, offset MPSend mov MChars.ReturnPacketHandler, offset MPReturnPacket invoke NdisIMRegisterLayeredMiniport,WrapperHandle,addr MChars, sizeof MChars,\ addr DriverHandler .if eax == STATUS_SUCCESS invoke NdisMRegisterUnloadHandler,WrapperHandle,offset Unload invoke RtlZeroMemory,addr PChars, sizeof NDIS_PROTOCOL_CHARACTERISTICS mov PChars.MajorNdisVersion, 5 mov PChars.MinorNdisVersion, 0 invoke RtlInitUnicodeString,addr PChars.Name_,addr stroka mov PChars.OpenAdapterCompleteHandler, offset PtOpenAdapterComplete mov PChars.CloseAdapterCompleteHandler, offset PtCloseAdapterComplete mov PChars.SendCompleteHandler , offset PtSendComplete mov PChars.TransferDataCompleteHandler , offset PtTransferDataComplete mov PChars.ResetCompleteHandler , offset PtResetComplete mov PChars.RequestCompleteHandler, offset PtRequestComplete mov PChars.ReceiveHandler , offset PtReceive mov PChars.ReceiveCompleteHandler , offset PtReceiveComplete mov PChars.StatusHandler, offset PtStatus mov PChars.StatusCompleteHandler, offset PtStatusComplete mov PChars.BindAdapterHandler , offset PtBindAdapter mov PChars.UnbindAdapterHandler , offset PtUnbindAdapter mov PChars.UnloadHandler , NULL mov PChars.ReceivePacketHandler , offset PtReceivePacket mov PChars.PnPEventHandler, offset PtPNPHandler invoke NdisRegisterProtocol,addr status,addr ProtHandler,addr PChars,\ sizeof NDIS_PROTOCOL_CHARACTERISTICS .if eax==STATUS_SUCCESS invoke NdisIMAssociateMiniport,DriverHandler,ProtHandler mov eax,STATUS_SUCCESS ret .endif .endifВкратце способ заключается в создании виртуального адаптера и его установки таким образом,что при каждом вызове реального адаптера сначала шло обращение к виртуальному.Т.е мы как бы накладываем наш виртуальный адаптер на реальный.
Вся обработка поступивших вызовов идёт в MP* и Pt* функциях. Где MP* -относится к Miniport, т.е. к нашему виртуальному адаптеру, а Pt* - к Protocol , протоколу, реализуемуму нашим адаптером.
Т.е если мы хотим фильтровать TCP/IP , Protocol должен уметь обрабатывать IP - пакеты .
4) Windows 2000 Filter-Hook Driver. Метод описан в документации DDK и применим только в Windows 2000 и выше, его мы и будем рассматривать в практической части.
5) NDIS Hooking Filter Driver.Способ сводится к перехвату некоторых функций NDIS библиотеки, которые в дальнейшем позволяют отследить регистрацию всех протоколов установленных в операционной системе и открытие ими сетевых интерфейсов. Используется в небезызвестном ZoneAlarm. Для Windows 2000 достаточно перехватить 4 функции:
- NdisRegisterProtocol
- NdisDeregisterProtocol
- NdisOpenAdapter
- NdisCloseAdapter
6) Packet Filtering API. На данный момент доступно в Windows 2000 Server и Windows .NET Server 2003.
Насчёт пунктов 2,3,5 : автор надеется осветить их в отдельной обширной статье по NDIS и TDI.
Часть вторая, практическая.
Использование Windows 2000 Filter-Hook Driver
Начиная с Windows 2000 Microsoft включила возможность фильтрации IP траффика в контексте IP Filter driver - стандартного сервиса Windows 2000. Как написано в DDK ,драйвера , используемые IP Filter driver сервисом, могут обрабатывать и фильтровать IP траффик, т.е расширять возможности IP Filter driver сервиса.
Правда при этом необходимо учитывать нюанс - только один драйвер может использоваться при фильтрации.
Драйвер для фильтрации траффика представляет собой обычный Kernel Mode Driver, реализующий определённую функцию фильтрации , которую он и регестрирует в IP Filter driver сервисе .Фильтруются как исходящий, так и входящий траффик.
Вот исходный текст простейшего драйвера для IP Filter driver, драйвер просто drop -ает все пакеты :
Код (Text):
.386 .model flat, stdcall ; I N C L U D E F I L E S ;######################################################################### include D:\masm32\include\w2k\ntstatus.inc include D:\masm32\include\w2k\ntddk.inc include D:\masm32\include\w2k\pfhook.inc include D:\masm32\include\w2k\ntoskrnl.inc include D:\masm32\Macros\Strings.mac includelib D:\NTDDK\libfre\i386\ntdll.lib includelib D:\NTDDK\libfre\i386\ntoskrnl.lib ; P R O T O ;########################################################################## set_hook PROTO :PacketFilterExtensionPtr ; D A T A ;########################################################################## .data CCOUNTED_UNICODE_STRING "\\Device\\IPFILTERDRIVER" ,drvsmbl,4 ipfilter_name UNICODE_STRING hook_nfo PF_SET_EXTENSION_HOOK_INFO status NTSTATUS ? devobj PDEVICE_OBJECT ? isb IO_STATUS_BLOCK fileobj PFILE_OBJECT NULL myirp PIRP NULL ; C O D E ;############################################################################ .code ; DriverEntry ;############################################################################ DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING mov eax,offset hookproc invoke set_hook, eax .if eax != STATUS_SUCCESS ret .endif mov eax, pDriverObject assume eax:PTR DRIVER_OBJECT mov [eax].DriverUnload,offset Unload assume eax:nothing mov eax,STATUS_SUCCESS ret DriverEntry endp ; Windows 2000 hook (built in) ;############################################################################### Unload proc p1DriverObject:PDRIVER_OBJECT invoke set_hook,NULL ret Unload endp ;############################################################################### set_hook proc hook_fn:PacketFilterExtensionPtr invoke IoGetDeviceObjectPointer,addr drvsmbl,STANDARD_RIGHTS_ALL,\ addr fileobj,addr devobj mov status,eax .if eax != STATUS_SUCCESS jmp exit .endif mov eax,hook_fn mov hook_nfo.ExtensionPointer,eax invoke IoBuildDeviceIoControlRequest,IOCTL_PF_SET_EXTENSION_POINTER(),\ devobj, addr hook_nfo,\ sizeof hook_nfo, NULL, 0, FALSE, NULL,addr isb mov myirp,eax .if eax == NULL mov status ,STATUS_INSUFFICIENT_RESOURCES jmp exit .endif invoke IoCallDriver,devobj,myirp mov myirp,NULL mov eax,STATUS_SUCCESS ret exit: .if fileobj!=NULL invoke ObDereferenceObject,fileobj .endif mov eax,status ret set_hook endp ;############################################################################### hookproc proc PacketHeader:PTR BYTE, Packet:PTR BYTE, PacketLength:WORD, RecvInterfaceIndex:WORD,SendInterfaceIndex:WORD,RecvLinkNextHop:DWORD, SendLinkNextHop:DWORD mov eax,PF_DROP ret hookproc endp end DriverEntryДля компиляции потребуется masm32 by hutch ,последний KMDKit by Four-F, Update KMDKit by van (пока состоит из pfhook.inc и неполного ndis.inc).
Рассмотрим более подробно данный код.
1) CCOUNTED_UNICODE_STRING "\\Device\\IPFILTERDRIVER" ,drvsmbl,4 - название нашего IP Filter driver сервиса.
2) hook_nfo PF_SET_EXTENSION_HOOK_INFO - структура , содержащая указатель типа PacketFilterExtensionPtr, т.е на нашу функцию фильтрации. Все остальные типы описаны в MSDN и KMD by Four-F.
3)
Код (Text):
mov eax,offset hookproc invoke set_hook, eax .if eax != STATUS_SUCCESS ret .endifВызываем set_hook , в качестве параметра выступает offset нашей функции фильтрации.
Если хук не удалось установить, выходим.
4)
Код (Text):
mov eax, pDriverObject assume eax:PTR DRIVER_OBJECT mov [eax].DriverUnload,offset Unload assume eax:nothing mov eax,STATUS_SUCCESS retСтандартная процедура регистрации функции выхода.
5)
Код (Text):
Unload proc p1DriverObject:PDRIVER_OBJECT invoke set_hook,NULL ret Unload endpУстанавливаем указатель на функцию фильтрации в IP Filter driver сервисе в NULL
6)
Код (Text):
set_hook proc hook_fn:PacketFilterExtensionPtr invoke IoGetDeviceObjectPointer,addr drvsmbl,STANDARD_RIGHTS_ALL,addr fileobj, addr devobjНаша функция установки фильтра.
IoGetDeviceObjectPointer - возвращает указатель в devobj на Device и file object , соответсвующий ему , название которого в drvsmbl . При условии, что доступ к нему разрешён.
7)
Код (Text):
invoke IoBuildDeviceIoControlRequest,IOCTL_PF_SET_EXTENSION_POINTER(),devobj, \ addr hook_nfo ,sizeof hook_nfo, NULL, 0, FALSE, NULL,addr isbДанная функция подробно описана в Walter Oney's Programming the Microsoft Windows Driver Model.
Макрос IOCTL_PF_SET_EXTENSION_POINTER() определён в pfhook.inc
Результат - устанавливаем irp для нашего драйвера.
Все остальные функции в данном разделе описаны в DDK и Programming the Microsoft Windows Driver Model.
8)
Код (Text):
hookproc proc PacketHeader: DWORD , Packet: DWORD, PacketLength:WORD, RecvInterfaceIndex:WORD,SendInterfaceIndex:WORD,RecvLinkNextHop:DWORD, SendLinkNextHop:DWORD mov eax,PF_DROP ret hookproc endp
Наш фильтр. Как видно, перед нами внутренности пакета.Заголовок и содержимое.
Возвращаем PF_DROP.
В pfhook.inc определены следующие константы для работы с IP пакетами:
Код (Text):
PF_FORWARD EQU 0t PF_DROP EQU 1t PF_PASS EQU 2t PF_ICMP_ON_DROP EQU 3tPF_FORWARD - форвардит пакет. Т.е. если destination address != наш адрес и включена маршрутизация, то немедленно посылается forward response в IP стек.
PF_PASS - пропускает пакет на наш компьютер.
PF_ICMP_ON_DROP - дропает пакет и отправляет ICMP - сообщение.
Данная константа недокументирована, хотя и определена.
Как установить наш драйвер ?
Автор использовал утилиту instdrv из NT DDK . К сожалению, в Win2000 DDK она отсутсвует.
Итак, набираем в консоли:
Код (Text):
net start ipfilterdriver instdrv filter D:\projects\asm\filter\filter.sys ping 127.0.0.1 Destination host unreachable. ; host unreachable, Destination host unreachable. ; что и следовало ожидать, Destination host unreachable. ; потому что все пакеты Destination host unreachable. ; уничтожены, ICMP - сообщение Ping statistics for 127.0.0.1: ; не отправлялось. Packets: Sent = 4, Received = 0, Lost = 4 (100% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 0ms, Average = 0ms . instdrv filter removeЗаключение.
Автор не претендует на полноту изложения , он постарался дать лишь общее представление о предмете. Автор также надеется , что данная статья позволит самостоятельно создавать firewall'ы на основе IP Filter driver сервиса и данного сэмпла.
Рекомендуемая литература:
Walter Oney's Programming the Microsoft Windows Driver Model.
David Solomon, Mark Russinovich : Inside Windows 2000Благодарности: Volodya /wasm.ru , за то, что терпел и наставлял меня , и за instdrv.
Four-F/wasm.ru ,за KMDKit и замечательные статьи.
gl00my , за моральную поддержку.
Файлы:
© van
Способы фильтрации сетевого траффика в Windows 9x/2000/Net.2003 Server
Дата публикации 1 ноя 2003