Überlegungen zur Programmierung von Legendentreibern
Berücksichtigen Sie die folgenden Themen, wenn Sie einen Windows-Filterplattform-Beschriftungstreiber programmieren.
Benutzermodus im Vergleich zu Kernelmodus
Wenn die gewünschte Filterung mithilfe der Standardfilterfunktion erfolgen kann, die in die Windows-Filterplattform integriert ist, sollten unabhängige Softwareanbieter (Independent Software Vendors, ISVs) Verwaltungsanwendungen im Benutzermodus schreiben, um die Filter-Engine zu konfigurieren, anstatt Kernelmodus-Legendentreiber zu schreiben. Ein Kernelmodus-Legendentreiber sollte nur geschrieben werden, wenn Sie die Netzwerkdaten auf eine Weise verarbeiten müssen, die von der standardmäßigen integrierten Filterfunktion nicht verarbeitet werden kann. Informationen zum Schreiben einer Windows-Filterplattform-Verwaltungsanwendung im Benutzermodus finden Sie in der Dokumentation zur Windows-Filterplattform im Microsoft Windows SDK.
Auswahl der Filterebene
Ein Legendentreiber sollte die Netzwerkdaten auf der höchstmöglichen Filterebene im Netzwerkstapel filtern. Wenn beispielsweise die gewünschte Filteraufgabe auf der Streamebene verarbeitet werden kann, sollte sie nicht auf der Netzwerkebene implementiert werden. Weitere Informationen zu Empfehlungen der Filterebenen, die Ihr Treiber verwenden sollte, um die Kompatibilität mit IPsec in Windows zu gewährleisten, finden Sie unter Entwickeln IPsec-Compatible Callout-Treiber.
Blockieren im ALE-Flow (Application Layer Enforcement) Etablierte Ebenen
Wenn der Filter-Engine in einer der vom ALE-Flow eingerichteten Filterebenen (FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4 oder FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6) eine Legende hinzugefügt wurde, sollte die KlassifizierungFn-Legendenfunktion in der Regel nie FWP_ACTION_BLOCK für die Aktion zurückgeben. Eine Entscheidung zum Autorisieren oder Ablehnen einer Verbindung sollte nicht in einer der ALE-Flow-Filterebenen getroffen werden. Eine solche Entscheidung sollte immer auf einer der anderen ALE-Filterebenen getroffen werden.
Der einzige gültige Grund dafür, dass eine solche klassifizierungFn-Calloutfunktion FWP_ACTION_BLOCK für die Aktion zurückgibt, ist, wenn ein Fehler auftritt, der ein potenzielles Sicherheitsrisiko darstellen könnte, wenn die hergestellte Verbindung nicht beendet wird. In diesem Fall wird durch zurückgeben FWP_ACTION_BLOCK für die Aktion die Verbindung geschlossen, um zu verhindern, dass das potenzielle Sicherheitsrisiko ausgenutzt wird.
Ausführungszeit der Legendenfunktion
Da die Filter-Engine in der Regel die Legendenfunktionen einer Legende unter IRQL = DISPATCH_LEVEL aufruft, stellen Sie sicher, dass diese Funktionen ihre Ausführung so schnell wie möglich abschließen, damit das System effizient ausgeführt wird. Erweiterte Ausführung bei IRQL = DISPATCH_LEVEL kann sich negativ auf die Gesamtleistung des Systems auswirken.
Einfügen in den Empfangsdatenpfad
Legenden sollten IP-Prüfsummen neu berechnen, bevor sie Paketeinschleusungsfunktionen aufrufen, die in den Empfangsdatenpfad eingefügt werden, da die Prüfsumme im ursprünglichen Paket möglicherweise nicht korrekt ist, wenn das Paket aus IP-Paketfragmenten neu zusammengesetzt wird. Es gibt keinen zuverlässigen Mechanismus, der angibt, ob eine Nettopufferliste aus Fragmenten neu zusammengesetzt wird.
Inlineinjektion von TCP-Paketen aus Transportebenen
Aufgrund des Sperrverhaltens des TCP-Stapels kann eine Legende auf der Transportschicht kein neues oder geklontes TCP-Paket aus der Legendenfunktion klassifizierenFn einfügen. Wenn eine Inlineeinschleusung gewünscht ist, muss die Legende einen DPC in die Warteschlange stellen, um die Einschleusung durchzuführen.
Ausrichtung ausgehender IP-Header
Die MDL, die den IP-Header in einer Netzwerkpufferliste (NET_BUFFER_CURRENT_MDL(NET_BUFFER_LIST_FIRST_NB(netBufferList))) beschreibt, muss zeigerbündig sein, wenn eine der Paketeinschleusungsfunktionen verwendet wird, um Paketdaten in einen ausgehenden Pfad einzufügen. Da die IP-Header-MDL eines eingehenden Pakets möglicherweise zeigerbündig ist, muss eine Legende den IP-Header (falls nicht bereits ausgerichtet) neu erstellen, wenn ein eingehendes Paket in einen ausgehenden Pfad eingefügt wird.