Les serveurs DHCP Microsoft, à partir de Windows 2003 Server, disposent d’une fonctionnalité très intéressante et rarement utilisée : le callout
…
Cette fonctionnalité, très bien documentée (http://msdn.microsoft.com/library/windows/desktop/aa363372.aspx), permet de notifier des librairies externes du traitement de requêtes DHCP.
Une fois n’est pas coutume, Microsoft laisse l’opportunité à ces librairies d’altérer les paquets, requêtes, et même de stopper le traitement d’une requête !
Le besoin
Pour une raison quelconque, j’ai du réfléchir à une problématique : comment ne pas distribuer d’adresses IP à une certaine catégorie de machines pouvant se brancher sur le même réseau physique/logique que des machines légitimes.
Des solutions existent déjà :
- IpSec
- NAC
et même d’autres moins efficaces (*) :
- IP fixe pour tout le réseau
- Blacklistage des adresses MAC sur les équipements frontaux
- Réservations DHCP pour tous les postes
…Inapplicables pour diverses raisons sur l’environnement ciblé.
(*) L’on part ici du principe qu’une personne prenant volontairement une IP du réseau d’entreprise ou changeant son adresse MAC, commet une action malveillante. Cela arrive rarement par hasard.
Un début de solution
Quelques recherches Google mènent obligatoirement vers cette entrée Technet : http://blogs.technet.com/b/teamdhcp/archive/2007/10/03/dhcp-server-callout-dll-for-mac-address-based-filtering.aspx
L’on y apprend que le blacklistage d’adresses MAC au niveau DHCP n’est pas un besoin loufoque et que Microsoft a « développé » une librairie pouvant prendre en charge une liste noire ou blanche d’adresses.
A priori celle-ci est maintenant devenue une fonctionnalité native du service DHCP de Windows Server 2008 r2.
Vu le nombre de commentaires exprimant des problématiques de mise en service, et ce genre d’avertissements Microsoft :
The current callout DLL shall no longer be available after December 15, 2010.
[…]
Known Issue:
- This callout dll may not work on localized builds (non english builds).
… cela n’encourage guère à son utilisation !
Un peu de code
Grâce au MSDN : http://msdn.microsoft.com/library/windows/desktop/aa363373.aspx, l’on peut rapidement coder sa propre librairie (ici sans fichier de log ou de paramétrages … (pas envie, pas besoin…)
/* Benjamin DELPY `gentilkiwi` http://blog.gentilkiwi.com benjamin@gentilkiwi.com Licence : http://creativecommons.org/licenses/by-nc-sa/3.0/fr/ */ #include <windows.h> #include <dhcpssdk.h> #define MAC_ADDRESS_SIZE 6 #define MAC_SOURCE_ADDRESS_OFFSET 28 const BYTE macToBlack[][MAC_ADDRESS_SIZE] = { {0x00, 0x0c, 0x29, 0x00, 0x00, 0x00}, {0x00, 0x50, 0x56, 0x00, 0x00, 0x00} }; HMODULE nextLibrary = NULL; LPDHCP_NEWPKT nextLibraryCalloutNewPkt = NULL; BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if(ul_reason_for_call == DLL_PROCESS_DETACH && nextLibrary) FreeLibrary(nextLibrary); return TRUE; } DWORD CALLBACK DhcpNewPktHook(IN OUT LPBYTE *Packet, IN OUT DWORD *PacketSize, IN DWORD IpAddress, IN LPVOID Reserved, IN OUT LPVOID *PktContext, OUT LPBOOL ProcessIt) { DWORD retour = ERROR_SUCCESS, m; *ProcessIt = TRUE; for(m = 0; m < sizeof(macToBlack) / MAC_ADDRESS_SIZE; m++) { if(RtlEqualMemory(*Packet + MAC_SOURCE_ADDRESS_OFFSET, macToBlack[m], MAC_ADDRESS_SIZE / 2)) { *ProcessIt = FALSE; retour = DHCP_DROP_INVALID; break; } } if(*ProcessIt && nextLibraryCalloutNewPkt) retour = nextLibraryCalloutNewPkt(Packet, PacketSize, IpAddress, Reserved, PktContext, ProcessIt); return retour; } DWORD CALLBACK DhcpServerCalloutEntry(IN LPWSTR ChainDlls, IN DWORD CalloutVersion, IN OUT LPDHCP_CALLOUT_TABLE CalloutTbl) { LPDHCP_ENTRY_POINT_FUNC nextEntry; RtlZeroMemory(CalloutTbl, sizeof(DHCP_CALLOUT_TABLE)); if(nextLibrary = LoadLibrary(ChainDlls)) if(nextEntry = (LPDHCP_ENTRY_POINT_FUNC) GetProcAddress(nextLibrary, DHCP_CALLOUT_ENTRY_POINT)) nextEntry(ChainDlls + wcslen(ChainDlls) + 1, CalloutVersion, CalloutTbl); if(CalloutTbl->DhcpNewPktHook) nextLibraryCalloutNewPkt = CalloutTbl->DhcpNewPktHook; CalloutTbl->DhcpNewPktHook = DhcpNewPktHook; return ERROR_SUCCESS; }
Sans oublier notre export C
d’un __stdcall
LIBRARY EXPORTS DhcpServerCalloutEntry = DhcpServerCalloutEntry
Cette librairie rejette ainsi les demandes émanant d’adresse MAC commençant par 00:0c:29
ou 00:50:56
, soit provenant de machines virtuelles VMware.
Installation
Sous HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\DHCPServer\Parameters
CalloutEnabled
de typeDWORD
, à1
pour activer les Callouts,0
pour les désactiverCalloutDlls
de typeREG_MULTI_SZ
, contenant la liste des librairies de Callouts (séparées par un saut de ligne)
Le service DHCP (DHCPServer
) doit être redémarré pour prendre en charge ces modifications.
Test
C:\Documents and Settings\Administrateur>ipconfig /renew
Configuration IP de Windows
Une erreur s'est produite lors du renouvellement de l'interface Connexion au réseau local : impossible de contacter votre serveur DHC. Le délai d'attente de la demande est dépassé.
Diaboliquement efficace pour quelques lignes :)