开发 IPsec 兼容的标注驱动程序

与 IPsec 兼容的层

若要与以 Windows Vista 和 Windows Server 2008 开头的 IPsec 的 Windows 实现完全兼容,应在以下运行时筛选层之一注册标注驱动程序:

TCP 数据包筛选
流层:

  • FWPS_LAYER_STREAM_V4

  • FWPS_LAYER_STREAM_V6

非 TCP 和非错误 ICMP 数据包筛选
Datagram-Data层:

  • FWPS_LAYER_DATAGRAM_DATA_V4

  • FWPS_LAYER_DATAGRAM_DATA_V6

  • FWPS_LAYER_DATAGRAM_DATA_V4_DISCARD

  • FWPS_LAYER_DATAGRAM_DATA_V6_DISCARD

除了必须在从数据报数据层接收注入的传入数据包之前重新生成这些数据包的情况外,在这些数据层上注册的标注驱动程序与 IPsec 兼容。

与 IPsec 不兼容的层

网络和转发层与 IPsec 不兼容,因为在这些层上,IPsec 流量尚未解密或验证。 IPsec 策略在传输层强制执行,这在网络层分类操作之后发生。

以下运行时筛选层与 IPsec 不兼容,因为 Windows 中的 IPsec 处理发生在以下层以下:

FWPS_LAYER_INBOUND_IPPACKET_V4

FWPS_LAYER_INBOUND_IPPACKET_V6

FWPS_LAYER_INBOUND_IPPACKET_V4_DISCARD

FWPS_LAYER_INBOUND_IPPACKET_V6_DISCARD

FWPS_LAYER_OUTBOUND_IPPACKET_V4

FWPS_LAYER_OUTBOUND_IPPACKET_V6

FWPS_LAYER_OUTBOUND_IPPACKET_V4_DISCARD

FWPS_LAYER_OUTBOUND_IPPACKET_V6_DISCARD

传输层的特殊注意事项

若要使注册到传输层 (FWPS_LAYER_XXX_TRANSPORT_V4 或_V6) 与 IPsec 兼容的标注驱动程序,请遵循以下准则:

  1. 在 ALE 中注册标注,授权接收/接受层 (FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6) ,以及传输层 (FWPS_LAYER_XXX_TRANSPORT_V4 或 _V6) 。

  2. 若要防止干扰内部 Windows IPsec 处理,请在权重低于 FWPM_SUBLAYER_UNIVERSAL 的子层上注册标注。 使用 FwpmSubLayerEnum0 函数查找子层的权重。 有关此函数的信息,请参阅Microsoft Windows SDK中的 Windows 筛选平台文档。

  3. 必须在 ALE 授权接收/接受层 (FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4或FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6) 检查需要 ALE 分类的传入传输数据包。 必须允许此类数据包来自传入传输层。 从 Windows Vista Service Pack 1 (SP1) 和 Windows Server 2008 开始,使用 FWPS_METADATA_FIELD_ALE_CLASSIFY_REQUIRED 元数据标志来确定传入数据包是否将指示给 FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 筛选层。 此元数据标志替换在 Windows Vista 中使用的 FWP_CONDITION_FLAG_REQUIRES_ALE_CLASSIFY 条件标志。

  4. 为防止干扰内部 Windows IPsec 处理,如果 IPsec 流量尚未解除隧道,请不要在传输层截获 IPsec 隧道模式流量。 下面的代码示例演示如何绕过此类数据包。

    FWPS_PACKET_LIST_INFORMATION0 packetInfo = {0};
    FwpsGetPacketListSecurityInformation0(
     layerData,
        FWPS_PACKET_LIST_INFORMATION_QUERY_IPSEC |
        FWPS_PACKET_LIST_INFORMATION_QUERY_INBOUND,
        &packetInfo
        );
    
    if (packetInfo.ipsecInformation.inbound.isTunnelMode &&
        !packetInfo.ipsecInformation.inbound.isDeTunneled)
    {
     classifyOut->actionType = FWP_ACTION_PERMIT;
     goto Exit;
    }
    
  5. 在传输层解密并验证受 IPsec 保护的数据包后,AH/ESP 标头将保留在 IP 标头中。 如果此类数据包必须重新插入 TCP/IP 堆栈,则必须重新生成 IP 标头以删除 AH/ESP 标头。 从 Windows Vista SP1 和 Windows Server 2008 开始,可以通过克隆数据包并调用 FwpsConstructIpHeaderForTransportPacket0 函数来执行此操作,该函数将 headerIncludeHeaderSize 参数设置为克隆数据包的 IP 标头大小。

  6. 在 ALE 接收/接受层,标注可以通过检查是否设置了FWP_CONDITION_FLAG_IS_IPSEC_SECURED标志来检测受 IPsec 保护 流量。 在传输层,标注可以通过调用 FwpsGetPacketListSecurityInformation0 函数并检查是否在 queryFlags 参数中设置了 FWPS_PACKET_LIST_INFORMATION0 标志来检测受 IPsec 保护的流量。

使用 IPsec ESP 数据包

当引擎指示已解密封装安全有效负载 (ESP) 数据包时,它会将其截断以排除尾随 ESP 数据。 由于引擎处理此类数据包的方式, NET_BUFFER 结构中的 MDL 数据不会反映正确的数据包长度。 通过使用 NET_BUFFER_DATA_LENGTH 宏检索 NET_BUFFER 结构的数据长度,可以获得正确的长度。