Sockets bruts TCP/IP
Un socket brut est un type de socket qui permet d’accéder au fournisseur de transport sous-jacent. Cette rubrique se concentre uniquement sur les sockets bruts et les protocoles IPv4 et IPv6. En effet, la plupart des autres protocoles, à l’exception de ATM, ne prennent pas en charge les sockets bruts. Pour utiliser des sockets bruts, une application doit disposer d’informations détaillées sur le protocole sous-jacent utilisé.
Les fournisseurs de services Winsock pour le protocole IP peuvent prendre en charge un type de socket de SOCK_RAW. Le fournisseur Windows Sockets 2 pour TCP/IP inclus sur Windows prend en charge ce type de socket SOCK_RAW .
Il existe deux types de base de ces sockets bruts :
- Le premier type utilise un type de protocole connu écrit dans l’en-tête IP reconnu par un fournisseur de services Winsock. Un exemple de premier type de socket est un socket pour le protocole ICMP (type de protocole IP = 1) ou le protocole ICMPv6 (type de procotol IP = 58).
- Le deuxième type permet de spécifier n’importe quel type de protocole. Un exemple de deuxième type serait un protocole expérimental qui n’est pas directement pris en charge par le fournisseur de services Winsock, tel que le protocole SCTP (Stream Control Transmission Protocol).
Déterminer si les sockets bruts sont pris en charge
Si un fournisseur de services Winsock prend en charge les sockets SOCK_RAW pour les familles d’adresses AF_INET ou AF_INET6, le type de socket de SOCK_RAW doit être inclus dans la structure WSAPROTOCOL_INFO retournée par la fonction WSAEnumProtocols pour un ou plusieurs des fournisseurs de transport disponibles.
Le membre iAddressFamily dans la structure WSAPROTOCOL_INFO doit spécifier AF_INET ou AF_INET6 et le membre iSocketType de la structure WSAPROTOCOL_INFO doit spécifier SOCK_RAW pour l’un des fournisseurs de transport.
Le membre iProtocol de la structure WSAPROTOCOL_INFO peut être défini sur IPROTO_IP. Le membre iProtocol de la structure WSAPROTOCOL_INFO peut également être défini sur zéro si le fournisseur de services autorise une application à utiliser un type de socket SOCK_RAW pour d’autres protocoles réseau autres que le protocole Internet pour la famille d’adresses.
Les autres membres de la structure WSAPROTOCOL_INFO indiquent d’autres propriétés de la prise en charge du protocole pour SOCK_RAW et indiquent comment un socket de SOCK_RAW doit être traité. Ces autres membres du WSAPROTOCOL_INFO pour SOCK_RAW spécifient normalement que le protocole est sans connexion, orienté message, prend en charge la diffusion/multidiffusion (les XP1_CONNECTIONLESS, XP1_MESSAGE_ORIENTED, XP1_SUPPORT_BROADCAST et XP1_SUPPORT_MULTIPOINT bits sont définis dans le membre dwServiceFlags1) et peuvent avoir une taille de message maximale de 65 467 octets.
Sur Windows XP et versions ultérieures , la commandeNetSh.exepeut être utilisée pour déterminer si les sockets bruts sont pris en charge. La commande suivante exécutée à partir d’une fenêtre CMD affiche les données du catalogue Winsock sur la console :
netsh winsock show catalog
La sortie inclut une liste qui contient certaines des données des structures WSAPROTOCOL_INFO prises en charge sur l’ordinateur local. Recherchez le terme RAW/IP ou RAW/IPv6 dans le champ Description pour trouver les protocoles qui prennent en charge les sockets bruts.
Création d’un socket brut
Pour créer un socket de type SOCK_RAW, appelez la fonction socket ou WSASocket avec le paramètre af (famille d’adresses) défini sur AF_INET ou AF_INET6, le paramètre de type défini sur SOCK_RAW et le paramètre de protocole défini sur le numéro de protocole requis. Le paramètre de protocole devient la valeur de protocole dans l’en-tête IP (SCTP est 132, par exemple).
Notes
Une application ne peut pas spécifier zéro (0) comme paramètre de protocole pour les fonctions socket, WSASocket et WSPSocket si le paramètre de type est défini sur SOCK_RAW.
Les sockets bruts offrent la possibilité de manipuler le transport sous-jacent, de sorte qu’ils peuvent être utilisés à des fins malveillantes qui posent une menace de sécurité. Par conséquent, seuls les membres du groupe Administrateurs peuvent créer des sockets de type SOCK_RAW sur Windows 2000 et versions ultérieures.
Opérations d’envoi et de réception
Une fois qu’une application a créé un socket de type SOCK_RAW, ce socket peut être utilisé pour envoyer et recevoir des données. Tous les paquets envoyés ou reçus sur un socket de type SOCK_RAW sont traités comme des datagrammes sur un socket non connecté.
Les règles suivantes s’appliquent aux opérations sur SOCK_RAW sockets :
La fonction sendto ou WSASendTo est normalement utilisée pour envoyer des données sur un socket de type SOCK_RAW. L’adresse de destination peut être n’importe quelle adresse valide dans la famille d’adresses du socket, y compris une adresse de diffusion ou de multidiffusion. Pour envoyer à une adresse de diffusion, une application doit avoir utilisé setsockopt avec SO_BROADCAST activé. Sinon, sendto ou WSASendTo échoue avec le code d’erreur WSAEACCES. Pour l’adresse IP, une application peut envoyer à n’importe quelle adresse de multidiffusion (sans devenir membre du groupe).
Lors de l’envoi de données IPv4, une application a le choix de spécifier ou non l’en-tête IPv4 à l’avant du datagramme sortant pour le paquet. Si l’option de socket IP_HDRINCL est définie sur true pour un socket IPv4 (famille d’adresses de AF_INET), l’application doit fournir l’en-tête IPv4 dans les données sortantes pour les opérations d’envoi. Si cette option de socket a la valeur false (paramètre par défaut), l’en-tête IPv4 ne doit pas être inclus dans les données sortantes pour les opérations d’envoi.
Lors de l’envoi de données IPv6, une application a le choix de spécifier l’en-tête IPv6 à l’avant du datagramme sortant pour le paquet. Si l’option de socket IPV6_HDRINCL est définie sur true pour un socket IPv6 (famille d’adresses de AF_INET6), l’application doit fournir l’en-tête IPv6 dans les données sortantes pour les opérations d’envoi. Le paramètre par défaut de cette option est false. Si cette option de socket a la valeur false (paramètre par défaut), l’en-tête IPv6 ne doit pas être inclus dans les données sortantes pour les opérations d’envoi. Pour IPv6, il ne doit pas être nécessaire d’inclure l’en-tête IPv6. Si des informations sont disponibles à l’aide de fonctions de socket, l’en-tête IPv6 ne doit pas être inclus pour éviter des problèmes de compatibilité à l’avenir. Ces problèmes sont abordés dans la RFC 3542 publiée par l’IETF. L’utilisation de l’option de socket IPV6_HDRINCL n’est pas recommandée et peut être déconseillée à l’avenir.
La fonction recvfrom ou WSARecvFrom est normalement utilisée pour recevoir des données sur un socket de type SOCK_RAW. Ces deux fonctions ont la possibilité de retourner l’adresse IP source à partir de laquelle le paquet a été envoyé. Les données reçues sont un datagramme provenant d’un socket non connecté.
Pour IPv4 (famille d’adresses de AF_INET), une application reçoit l’en-tête IP à l’avant de chaque datagramme reçu, quelle que soit l’option de socket IP_HDRINCL .
Pour IPv6 (famille d’adresses de AF_INET6), une application reçoit tout ce qui suit le dernier en-tête IPv6 dans chaque datagramme reçu, quelle que soit l’option de socket IPV6_HDRINCL . L’application ne reçoit aucun en-tête IPv6 à l’aide d’un socket brut.
Les datagrammes reçus sont copiés dans tous les sockets SOCK_RAW qui remplissent les conditions suivantes :
- Le numéro de protocole spécifié dans le paramètre de protocole lors de la création du socket doit correspondre au numéro de protocole dans l’en-tête IP du datagramme reçu.
- Si une adresse IP locale est définie pour le socket, elle doit correspondre à l’adresse de destination spécifiée dans l’en-tête IP du datagramme reçu. Une application peut spécifier l’adresse IP locale en appelant la fonction bind . Si aucune adresse IP locale n’est spécifiée pour le socket, les datagrammes sont copiés dans le socket, quelle que soit l’adresse IP de destination dans l’en-tête IP du datagramme reçu.
- Si une adresse étrangère est définie pour le socket, elle doit correspondre à l’adresse source spécifiée dans l’en-tête IP du datagramme reçu. Une application peut spécifier l’adresse IP étrangère en appelant la fonction connect ou WSAConnect . Si aucune adresse IP étrangère n’est spécifiée pour le socket, les datagrammes sont copiés dans le socket, quelle que soit l’adresse IP source dans l’en-tête IP du datagramme reçu.
Il est important de comprendre que certains sockets de type SOCK_RAW peuvent recevoir de nombreux datagrammes inattendus. Par exemple, un programme PING peut créer un socket de type SOCK_RAW pour envoyer des demandes d’écho ICMP et recevoir des réponses. Bien que l’application attende des réponses d’écho ICMP, tous les autres messages ICMP (tels que icmp HOST_UNREACHABLE) peuvent également être remis à cette application. De plus, si plusieurs sockets SOCK_RAW sont ouverts sur un ordinateur en même temps, les mêmes datagrammes peuvent être remis à tous les sockets ouverts. Une application doit disposer d’un mécanisme permettant de reconnaître les datagrammes intéressants et d’ignorer tous les autres. Pour un programme PING, un tel mécanisme peut inclure l’inspection de l’en-tête IP reçue à la recherche d’identificateurs uniques dans l’en-tête ICMP (ID de processus de l’application, par exemple).
Notes
Pour utiliser un socket de type SOCK_RAW nécessite des privilèges d’administration. Les utilisateurs exécutant des applications Winsock qui utilisent des sockets bruts doivent être membres du groupe Administrateurs sur l’ordinateur local. Sinon, les appels de socket bruts échouent avec un code d’erreur WSAEACCES. Sur Windows Vista et versions ultérieures, l’accès aux sockets bruts est appliqué lors de la création du socket. Dans les versions antérieures de Windows, l’accès aux sockets bruts est appliqué lors d’autres opérations de socket.
Utilisations courantes des sockets bruts
L’une des utilisations courantes des sockets bruts est la résolution des problèmes d’applications qui doivent examiner en détail les paquets et les en-têtes IP. Par exemple, un socket brut peut être utilisé avec le SIO_RCVALL IOCTL pour permettre à un socket de recevoir tous les paquets IPv4 ou IPv6 passant via une interface réseau. Pour plus d’informations, consultez la référence SIO_RCVALL .
Limitations sur les sockets bruts
Sur Windows 7, Windows Vista, Windows XP avec Service Pack 2 (SP2) et Windows XP avec Service Pack 3 (SP3), la possibilité d’envoyer du trafic sur des sockets bruts a été limitée de plusieurs façons :
Les données TCP ne peuvent pas être envoyées sur des sockets bruts.
Les datagrammes UDP avec une adresse source non valide ne peuvent pas être envoyés sur des sockets bruts. L’adresse IP source de tout datagramme UDP sortant doit exister sur une interface réseau ou le datagramme est supprimé. Cette modification a été apportée pour limiter la capacité du code malveillant à créer des attaques par déni de service distribuées et limiter la possibilité d’envoyer des paquets usurpés (paquets TCP/IP avec une adresse IP source falsifiée).
Un appel à la fonction de liaison avec un socket brut pour le protocole IPPROTO_TCP n’est pas autorisé.
Notes
La fonction de liaison avec un socket brut est autorisée pour d’autres protocoles (IPPROTO_IP, IPPROTO_UDP ou IPPROTO_SCTP, par exemple).
Ces restrictions ci-dessus ne s’appliquent pas à Windows Server 2008 R2, Windows Server 2008 , Windows Server 2003 ou aux versions du système d’exploitation antérieures à Windows XP avec SP2.
Notes
L’implémentation Microsoft de TCP/IP sur Windows est capable d’ouvrir un socket UDP ou TCP brut en fonction des restrictions ci-dessus. D’autres fournisseurs Winsock peuvent ne pas prendre en charge l’utilisation de sockets bruts.
Il existe d’autres limitations pour les applications qui utilisent un socket de type SOCK_RAW. Par exemple, toutes les applications qui écoutent un protocole spécifique reçoivent tous les paquets reçus pour ce protocole. Ce n’est peut-être pas ce qui est souhaité pour plusieurs applications utilisant un protocole. Cela ne convient pas non plus aux applications hautes performances. Pour contourner ces problèmes, il peut être nécessaire d’écrire un pilote de protocole réseau Windows (pilote de périphérique) pour le protocole réseau spécifique. Sur Windows Vista et versions ultérieures, le noyau Winsock (WSK), une nouvelle interface de programmation réseau en mode noyau indépendant du transport peut être utilisée pour écrire un pilote de protocole réseau. Sur Windows Server 2003 et versions antérieures, un fournisseur TDI (Transport Driver Interface) et une DLL d’assistance Winsock peuvent être écrits pour prendre en charge le protocole réseau. Le protocole réseau est ensuite ajouté au catalogue Winsock en tant que protocole pris en charge. Cela permet à plusieurs applications d’ouvrir des sockets pour ce protocole spécifique et le pilote de périphérique peut suivre le socket qui reçoit des paquets et des erreurs spécifiques. Pour plus d’informations sur l’écriture d’un fournisseur de protocole réseau, consultez les sections sur WSK et TDI dans le Kit de pilotes Windows (WDK).
Les applications doivent également être conscientes de l’impact que les paramètres de pare-feu peuvent avoir sur l’envoi et la réception de paquets à l’aide de sockets bruts.