Unformatierte TCP/IP-Sockets
Ein unformatierter Socket ist ein Sockettyp, der den Zugriff auf den zugrunde liegenden Transportanbieter ermöglicht. Dieses Thema konzentriert sich nur auf unformatierte Sockets und die Protokolle IPv4 und IPv6. Dies liegt daran, dass die meisten anderen Protokolle mit Ausnahme von ATM keine Unformatierten Sockets unterstützen. Um unformatierte Sockets verwenden zu können, muss eine Anwendung über detaillierte Informationen zum zugrunde liegenden Protokoll verfügen, das verwendet wird.
Winsock-Dienstanbieter für das IP-Protokoll unterstützen möglicherweise einen Sockettypvon SOCK_RAW. Der unter Windows enthaltene Windows Sockets 2-Anbieter für TCP/IP unterstützt diesen SOCK_RAW Sockettyp.
Es gibt zwei grundlegende Typen solcher Rohsockets:
- Der erste Typ verwendet einen bekannten Protokolltyp, der in den IP-Header geschrieben wird, der von einem Winsock-Dienstanbieter erkannt wird. Ein Beispiel für den ersten Sockettyp ist ein Socket für das ICMP-Protokoll (IP-Protokolltyp = 1) oder das ICMPv6-Protokoll (IP-Procotol-Typ = 58).
- Mit dem zweiten Typ kann ein beliebiger Protokolltyp angegeben werden. Ein Beispiel für den zweiten Typ wäre ein experimentelles Protokoll, das vom Winsock-Dienstanbieter nicht direkt unterstützt wird, z. B. das Stream Control Transmission Protocol (SCTP).
Ermitteln, ob Unformatierte Sockets unterstützt werden
Wenn ein Winsock-Dienstanbieter SOCK_RAW Sockets für die AF_INET- oder AF_INET6-Adressfamilien unterstützt, sollte der Sockettyp der SOCK_RAW in die WSAPROTOCOL_INFO-Struktur aufgenommen werden, die von der WSAEnumProtocols-Funktion für einen oder mehrere der verfügbaren Transportanbieter zurückgegeben wird.
Der iAddressFamily-Member in der WSAPROTOCOL_INFO-Struktur sollte AF_INET oder AF_INET6 angeben, und das iSocketType-Element der WSAPROTOCOL_INFO-Struktur sollte SOCK_RAW für einen der Transportanbieter angeben.
Der iProtocol-Member der WSAPROTOCOL_INFO-Struktur kann auf IPROTO_IP festgelegt werden. Das iProtocol-Element der WSAPROTOCOL_INFO-Struktur kann auch auf Null festgelegt werden, wenn der Dienstanbieter einer Anwendung die Verwendung eines SOCK_RAW Sockettyps für andere Netzwerkprotokolle als das Internetprotokoll für die Adressfamilie zulässt.
Die anderen Member in der WSAPROTOCOL_INFO-Struktur geben andere Eigenschaften der Protokollunterstützung für SOCK_RAW an und geben an, wie ein Socket mit SOCK_RAW behandelt werden soll. Diese anderen Member der WSAPROTOCOL_INFO für SOCK_RAW geben normalerweise an, dass das Protokoll verbindungslos, nachrichtenorientiert ist, Broadcast/Multicast unterstützt (die XP1_CONNECTIONLESS, XP1_MESSAGE_ORIENTED, XP1_SUPPORT_BROADCAST und XP1_SUPPORT_MULTIPOINT Bits sind im element dwServiceFlags1 festgelegt) und eine maximale Nachrichtengröße von 65.467 Byte aufweisen kann.
Unter Windows XP und höher kann der Befehl NetSh.exe verwendet werden, um zu bestimmen, ob Unformatierte Sockets unterstützt werden. Der folgende Befehl, der über ein CMD-Fenster ausgeführt wird, zeigt Daten aus dem Winsock-Katalog auf der Konsole an:
netsh winsock show catalog
Die Ausgabe enthält eine Liste, die einige der Daten aus den WSAPROTOCOL_INFO Strukturen enthält, die auf dem lokalen Computer unterstützt werden. Suchen Sie im Feld Beschreibung nach dem Begriff RAW/IP oder RAW/IPv6, um die Protokolle zu finden, die Unformatierte Sockets unterstützen.
Erstellen eines Unformatierten Sockets
Um einen Socket vom Typ SOCK_RAW zu erstellen, rufen Sie die Socket- oder WSASocket-Funktion auf, wobei der af-Parameter (Adressfamilie) auf AF_INET oder AF_INET6, der Typparameter auf SOCK_RAW und der Protokollparameter auf die erforderliche Protokollnummer festgelegt ist. Der Protokollparameter wird zum Protokollwert im IP-Header (SCTP ist z. B. 132).
Hinweis
Eine Anwendung darf null (0) nicht als Protokollparameter für die Socket-, WSASocket- und WSPSocket-Funktionen angeben, wenn der Typparameter auf SOCK_RAW festgelegt ist.
Unformatierte Sockets bieten die Möglichkeit, den zugrunde liegenden Transport zu bearbeiten, sodass sie für böswillige Zwecke verwendet werden können, die eine Sicherheitsgefährdung darstellen. Daher können nur Mitglieder der Gruppe Administratoren Sockets vom Typ SOCK_RAW unter Windows 2000 und höher erstellen.
Sende- und Empfangsvorgänge
Sobald eine Anwendung einen Socket vom Typ SOCK_RAW erstellt, kann dieser Socket zum Senden und Empfangen von Daten verwendet werden. Alle Pakete, die auf einem Socket vom Typ SOCK_RAW gesendet oder empfangen werden, werden auf einem nicht verbundenen Socket als Datagramme behandelt.
Die folgenden Regeln gelten für die Vorgänge über SOCK_RAW Sockets:
Die Sendto - oder WSASendTo-Funktion wird normalerweise verwendet, um Daten auf einem Socket vom Typ SOCK_RAW zu senden. Die Zieladresse kann eine beliebige gültige Adresse in der Adressfamilie des Sockets sein, einschließlich einer Broadcast- oder Multicastadresse. Zum Senden an eine Broadcastadresse muss eine Anwendung setockopt mit aktiviertem SO_BROADCAST verwendet haben. Andernfalls schlägt sendto oder WSASendTo mit dem Fehlercode WSAEACCES fehl. Für IP kann eine Anwendung an eine beliebige Multicastadresse senden (ohne Mitglied einer Gruppe zu werden).
Beim Senden von IPv4-Daten hat eine Anwendung die Wahl, ob der IPv4-Header am Anfang des ausgehenden Datagramms für das Paket angegeben werden soll. Wenn die Option IP_HDRINCL Socket für einen IPv4-Socket (Adressfamilie von AF_INET) auf true festgelegt ist, muss die Anwendung den IPv4-Header in den ausgehenden Daten für Sendevorgänge bereitstellen. Wenn diese Socketoption auf false festgelegt ist (die Standardeinstellung), sollte der IPv4-Header nicht in den ausgehenden Daten für Sendevorgänge enthalten sein.
Beim Senden von IPv6-Daten hat eine Anwendung die Wahl, ob der IPv6-Header vor dem ausgehenden Datagramm für das Paket angegeben werden soll. Wenn die Option IPV6_HDRINCL Socket für einen IPv6-Socket (Adressfamilie von AF_INET6) auf true festgelegt ist, muss die Anwendung den IPv6-Header in den ausgehenden Daten für Sendevorgänge bereitstellen. Die Standardeinstellung für diese Option ist false. Wenn diese Socketoption auf false festgelegt ist (die Standardeinstellung), sollte der IPv6-Header nicht in den ausgehenden Daten für Sendevorgänge enthalten sein. Für IPv6 sollte es nicht erforderlich sein, den IPv6-Header einzuschließen. Wenn Informationen mithilfe von Socketfunktionen verfügbar sind, sollte der IPv6-Header nicht eingeschlossen werden, um Kompatibilitätsprobleme in Zukunft zu vermeiden. Diese Probleme werden in RFC 3542 behandelt, der von der IETF veröffentlicht wurde. Die Verwendung der IPV6_HDRINCL Socketoption wird nicht empfohlen und ist möglicherweise in Zukunft veraltet.
Die Recvfrom - oder WSARecvFrom-Funktion wird normalerweise verwendet, um Daten auf einem Socket vom Typ SOCK_RAW zu empfangen. Beide Funktionen haben die Möglichkeit, die Quell-IP-Adresse zurückzugeben, von der das Paket gesendet wurde. Die empfangenen Daten sind ein Datagramm aus einem nicht verbundenen Socket.
Für IPv4 (Adressfamilie von AF_INET) empfängt eine Anwendung den IP-Header an der Vorderseite jedes empfangenen Datagramms, unabhängig von der IP_HDRINCL Socketoption.
Für IPv6 (Adressfamilie von AF_INET6) empfängt eine Anwendung alles nach dem letzten IPv6-Header in jedem empfangenen Datagramm, unabhängig von der IPV6_HDRINCL Socketoption. Die Anwendung empfängt keine IPv6-Header mit einem unformatierten Socket.
Empfangene Datagramme werden in alle SOCK_RAW Sockets kopiert, die die folgenden Bedingungen erfüllen:
- Die Protokollnummer, die beim Erstellen des Sockets im Protokollparameter angegeben wurde, sollte mit der Protokollnummer im IP-Header des empfangenen Datagramms übereinstimmen.
- Wenn eine lokale IP-Adresse für den Socket definiert ist, sollte sie der Zieladresse entsprechen, die im IP-Header des empfangenen Datagramms angegeben ist. Eine Anwendung kann die lokale IP-Adresse angeben, indem sie die bind-Funktion aufruft. Wenn keine lokale IP-Adresse für den Socket angegeben ist, werden die Datagramme unabhängig von der Ziel-IP-Adresse im IP-Header des empfangenen Datagramms in den Socket kopiert.
- Wenn eine Fremdadresse für den Socket definiert ist, sollte sie der Quelladresse entsprechen, die im IP-Header des empfangenen Datagramms angegeben ist. Eine Anwendung kann die fremde IP-Adresse angeben, indem sie die Connect - oder WSAConnect-Funktion aufruft. Wenn für den Socket keine Fremd-IP-Adresse angegeben ist, werden die Datagramme unabhängig von der Quell-IP-Adresse im IP-Header des empfangenen Datagramms in den Socket kopiert.
Es ist wichtig zu verstehen, dass einige Sockets vom Typ SOCK_RAW viele unerwartete Datagramme erhalten können. Beispielsweise kann ein PING-Programm einen Socket vom Typ SOCK_RAW erstellen, um ICMP-Echoanforderungen zu senden und Antworten zu empfangen. Während die Anwendung ICMP-Echoantworten erwartet, werden möglicherweise auch alle anderen ICMP-Nachrichten (z. B. ICMP HOST_UNREACHABLE) an diese Anwendung übermittelt. Wenn außerdem mehrere SOCK_RAW Sockets gleichzeitig auf einem Computer geöffnet sind, können dieselben Datagramme an alle offenen Sockets übermittelt werden. Eine Anwendung muss über einen Mechanismus verfügen, um die relevanten Datagramme zu erkennen und alle anderen zu ignorieren. Für ein PING-Programm kann ein solcher Mechanismus die Überprüfung des empfangenen IP-Headers auf eindeutige Bezeichner im ICMP-Header umfassen (z. B. die Prozess-ID der Anwendung).
Hinweis
Um einen Socket vom Typ SOCK_RAW zu verwenden, sind Administratorrechte erforderlich. Benutzer, die Winsock-Anwendungen ausführen, die unformatierte Sockets verwenden, müssen Mitglied der Gruppe Administratoren auf dem lokalen Computer sein. Andernfalls schlagen unformatierte Socketaufrufe mit dem Fehlercode WSAEACCES fehl. Unter Windows Vista und höher wird der Zugriff für Unformatierte Sockets bei der Socketerstellung erzwungen. In früheren Versionen von Windows wird der Zugriff für Unformatierte Sockets während anderer Socketvorgänge erzwungen.
Häufige Verwendungen von Rohsockets
Eine häufige Verwendung von unformatierten Sockets ist die Problembehandlung von Anwendungen, die IP-Pakete und Header im Detail untersuchen müssen. Beispielsweise kann ein unformatierter Socket mit dem SIO_RCVALL IOCTL verwendet werden, damit ein Socket alle IPv4- oder IPv6-Pakete empfangen kann, die über eine Netzwerkschnittstelle übergeben werden. Weitere Informationen finden Sie in der Referenz zu SIO_RCVALL .
Einschränkungen für Unformatierte Sockets
Unter Windows 7, Windows Vista, Windows XP mit Service Pack 2 (SP2) und Windows XP mit Service Pack 3 (SP3) wurde die Möglichkeit, Datenverkehr über unformatierte Sockets zu senden, auf verschiedene Arten eingeschränkt:
TCP-Daten können nicht über unformatierte Sockets gesendet werden.
UDP-Datagramme mit einer ungültigen Quelladresse können nicht über unformatierte Sockets gesendet werden. Die IP-Quelladresse für ein ausgehendes UDP-Datagramm muss auf einer Netzwerkschnittstelle vorhanden sein, oder das Datagramm wird gelöscht. Diese Änderung wurde vorgenommen, um die Fähigkeit von bösartigem Code zu beschränken, verteilte Denial-of-Service-Angriffe zu erzeugen, und die Möglichkeit zum Senden gefälschter Pakete (TCP/IP-Pakete mit einer gefälschten Quell-IP-Adresse) einzuschränken.
Ein Aufruf der Bindfunktion mit einem Rohsocket für das protokoll IPPROTO_TCP ist nicht zulässig.
Hinweis
Die Bindfunktion mit einem unformatierten Socket ist für andere Protokolle (z. B. IPPROTO_IP, IPPROTO_UDP oder IPPROTO_SCTP) zulässig.
Diese oben genannten Einschränkungen gelten nicht für Windows Server 2008 R2, Windows Server 2008 , Windows Server 2003 oder für Versionen des Betriebssystems vor Windows XP mit SP2.
Hinweis
Die Microsoft-Implementierung von TCP/IP unter Windows kann basierend auf den oben genannten Einschränkungen einen unformatierten UDP- oder TCP-Socket öffnen. Andere Winsock-Anbieter unterstützen die Verwendung von Unformatierten Sockets möglicherweise nicht.
Es gibt weitere Einschränkungen für Anwendungen, die einen Socket vom Typ SOCK_RAW verwenden. Beispielsweise erhalten alle Anwendungen, die auf ein bestimmtes Protokoll lauschen, alle Pakete, die für dieses Protokoll empfangen werden. Dies ist möglicherweise nicht das, was für mehrere Anwendungen mit einem Protokoll gewünscht wird. Dies ist auch für Hochleistungsanwendungen nicht geeignet. Um diese Probleme zu umgehen, muss möglicherweise ein Windows-Netzwerkprotokolltreiber (Gerätetreiber) für das spezifische Netzwerkprotokoll geschrieben werden. Unter Windows Vista und höher, Winsock Kernel (WSK), kann eine neue transportunabhängige Kernelmodus-Netzwerkprogrammierschnittstelle verwendet werden, um einen Netzwerkprotokolltreiber zu schreiben. Unter Windows Server 2003 und früher können ein TDI-Anbieter (Transport Driver Interface) und eine Winsock-Hilfsprogramm-DLL geschrieben werden, um das Netzwerkprotokoll zu unterstützen. Das Netzwerkprotokoll wird dann dem Winsock-Katalog als unterstütztes Protokoll hinzugefügt. Dadurch können mehrere Anwendungen Sockets für dieses spezifische Protokoll öffnen, und der Gerätetreiber kann nachverfolgen, welcher Socket bestimmte Pakete und Fehler empfängt. Informationen zum Schreiben eines Netzwerkprotokollanbieters finden Sie in den Abschnitten zu WSK und TDI im Windows Driver Kit (WDK).
Anwendungen müssen sich auch der Auswirkungen bewusst sein, die Firewalleinstellungen möglicherweise auf das Senden und Empfangen von Paketen mit unformatierten Sockets haben.