下列组件可处理 IP 数据包:

IP 转发 为发送或转发的数据包确定下一跃点接口和地址。

TCP/IP 筛选 允许按 IP 协议、TCP 端口或 UDP 端口,指定可为传入的本地主机流量(发往主机的数据包)所接受的流量类型。可以在“网络连接”文件夹中,从 Internet 协议 (TCP/IP) 组件高级属性的“选项”选项卡,配置 TCP/IP 筛选。

筛选器挂钩驱动程序 该 Windows 组件可使用筛选器挂钩 API,筛选传入和传出的 IP 数据包。在运行 Windows Server 2003 的计算机上,筛选器挂钩驱动程序为 Ipfltdrv.sys ,属于“路由和远程访问”的一个组件。启用后,“路由和远程访问”允许用户使用路由和远程访问管理单元,对每个接口配置单独的入站和出站 IP 数据包筛选器。Ipfltdrv.sys 会同时检查本地主机和中转 IP 流量(不发往主机的数据包)。

防火墙挂钩驱动程序 该 Windows 组件可使用防火墙挂钩 API,检查传入和传出的数据包。在运行 Windows XP 的计算机上,防火墙挂钩驱动程序为 Ipnat.sys ,由 Internet 连接共享和 Windows 防火墙双方共享。Internet 连接共享是一种基础网络地址转换器 (NAT)。Windows 防火墙是一种基于主机的状态防火墙。Ipnat.sys 可同时检查本地主机和中转 IP 流量。

IPsec组件(Ipsec.sys) 是 IPsec 在 Windows 中的实现,可对 IP 流量提供加密保护。Ipsec.sys 可同时检查本地主机和中转 IP 流量,并可允许、阻止或保护流量。

数据包处理路径

下面几节介绍了针对以下流量的具体的数据包处理路径:

源流量 由基于 Windows 的发送主机发起。

目标流量 达到最终的基于 Windows 的目标主机。

中转流量 由基于 Windows 的 IP 路由器转发。

这里只讨论 Windows Server 2003 或 Windows XP 所附带的组件,不涉及 Windows 套接字分层服务提供程序或 NDIS 中间微型端口驱动程序。

源流量的数据包处理路径如下图所示。

1.

IP 数据包形成后,Tcpip.sys 就会将其传递给防火墙挂钩驱动程序 (lpnat.sys) 进行处理。

Windows 防火墙检查该流量是否属于所要阻止的特定的 Internet 控制消息协议 (ICMP) 消息类型。如果 ICMP 消息被阻止,Windows 防火墙就将丢弃该数据包。

Windows 防火墙检查该流量是否属于点对点隧道协议 (PPTP) 隧道维护流量。如果属于的话,Windows 防火墙将分析该流量,确定用于识别特定 PPTP 隧道的通用路由封装 (GRE) 调用 ID,从而允许 PPTP 隧道的基于 GRE 的传入流量。

如果需要,Windows 防火墙会在例外列表中添加一个动态项目,来允许响应流量。

处理完后,lpnat.sys 会将该 IP 数据包传回给 Tcpip.sys,而后者会使用 IP 转发组件,确定下一跃点 IP 地址和接口。

2.

Tcpip.sys 将数据包传递给筛选器挂钩驱动程序 (Ipfltdrv.sys) 进行处理。

Ipfltdrv.sys 根据下一跃点接口,将该数据包与已配置的出站 IP 数据包筛选器进行对比。

若出站 IP 数据包筛选器不允许该数据包,Ipfltdrv.sys 就会在不给出提示的情况下,丢弃该数据包。若出站 IP 数据包筛选器允许该数据包,Ipfltdrv.sys 就会将该数据包传回给 Tcpip.sys。

3.

Tcpip.sys 将该数据包传递给 Ipsec.sys 进行处理。

Ipsec.sys 根据 IPsec 筛选器组,决定是否允许、阻止或保护该数据包。若允许的话,Ipsec.sys 会在不修改该数据包的情况下,将其发回给 Tcpip.sys。若阻止的话,Ipsec.sys 会在不发出任何提示的情况下,丢弃该数据包。若要进行保护的话,Ipsec.sys 会在将数据包传回给 Tcpip.sys 之前,对其添加适当的 IPsec保护。Tcpip.sys 随后会通过下一跃点接口,将该数据包发送到下一跃点 IP 地址。

目标流量的数据包处理路径如下图所示。

1.

接收到 IP 数据包后,Tcpip.sys 会将其传递给 Ipsec.sys 进行处理。

若数据包带有 IPsec 保护(指示验证头 [AH] 或封装式安全措施负载 [ESP] 的 IP 协议字段值),将对其进行处理并加以移除。若对计算机应用了“Windows 防火墙:允许已验证的 IPSec 跳过”组策略设置,Ipsec.sys 将设置一个与该数据包相关联的 IPsec Bypass 标记。Ipsec.sys 将结果数据包传回给 Tcpip.sys。

若数据包不带有 IPsec 保护,Ipsec.sys 就会根据 IPsec 筛选器组,决定是否允许、阻止或保护该数据包。若允许的话,Ipsec.sys 会在不修改该数据包的情况下,将其发回给 Tcpip.sys。若数据包被阻止或需要保护,Ipsec.sys 就会在不发出任何提示的情况下,丢弃该数据包。

2.

Tcpip.sys 将该数据包传递给 Ipfltdrv.sys 进行处理。

Ipfltdrv.sys 根据接收数据包的接口,将该数据包与已配置的入站 IP 数据包筛选器进行对比。

若入站 IP 数据包筛选器不允许该数据包,Ipfltdrv.sys 就会在不给出提示的情况下,丢弃该数据包。 若入站 IP 数据包筛选器允许该数据包,Ipfltdrv.sys 就会将该数据包传回给 Tcpip.sys。

3.

Tcpip.sys 将该数据包传递给 lpnat.sys 进行处理。

若启用了 Internet 连接共享或 NAT/基本防火墙,并且接收数据包的接口是连接到 Internet 的公共接口,lpnat.sys 就会将该数据包与其 NAT 转换表进行对比。若找到了匹配项,就将转换该 IP 数据包,并将结果数据包视为源流量。

Windows 防火墙检查与该数据包相关联的 IPsec Bypass 标记。若设置了 IPsec Bypass 标记,Windows 防火墙就会将该数据包传回给 Tcpip.sys。

若未设置 IPsec Bypass 标记,Windows 防火墙就会将该数据包与其例外列表进行对比。若数据包与某个例外匹配,lpnat.sys 就会将该 IP 数据包传回给 Tcpip.sys。若不匹配,lpnat.sys 会在不发出提示的情况下,丢弃该 IP 数据包。

4.

Tcpip.sys 将 IP 数据包与已配置的 TCP/IP 筛选允许的那组数据包进行对比。

若 TCP/IP 筛选不允许该数据包,Tcpip.sys 将在不发出提示的情况下,丢弃该数据包。若 TCP/IP 筛选允许该数据包,Tcpip.sys 将继续对其进行处理,并最终将该数据包有效负载传递给 TCP、UDP 或其它上层协议。

中转流量的前半部分路径如下图所示。

1.

接收到 IP 数据包后,Tcpip.sys 会将其传递给 Ipfltdrv.sys 进行处理。

Ipfltdrv.sys 根据接收 IP 数据包的接口,将该数据包与已配置的入站 IP 数据包筛选器进行对比。

若入站 IP 数据包筛选器不允许该数据包,Ipfltdrv.sys 就会在不给出提示的情况下,丢弃该 IP 数据包。若入站 IP 数据包筛选器允许该数据包,Ipfltdrv.sys 就会将该 IP 数据包传回给 Tcpip.sys。

Tcpip.sys 将数据包传递给 IP 转发组件,由后者确定用于转发该数据包的下一跃点接口和地址。

中转流量的后半部分路径如下图所示。

2.

Tcpip.sys 将该数据包传递给 lpnat.sys。

若启用了 Internet 连接共享或 NAT/基本防火墙,并且接收数据包的接口是连接到 Intranet 的专用接口,lpnat.sys就会将该数据包与其 NAT 转换表进行对比。若 Internet 连接共享或 NAT/基本防火墙找到了匹配项,将转换该 IP 数据包,并将结果数据包当作源流量。若 Internet 连接共享或 NAT/基本防火墙未找到匹配项,将创建一个新的 NAT 转换表项,转换 IP 数据包,并将结果数据包当作源流量。

若未启用 Internet 连接共享,lpnat.sys就会将 IP 数据包传回给 Tcpip.sys。

3.

Tcpip.sys 将该数据包传递给 Ipfltdrv.sys。

Ipfltdrv.sys 根据下一跃点接口,将该数据包与已配置的出站 IP 数据包筛选器进行对比。

若出站 IP 数据包筛选器不允许该数据包,Ipfltdrv.sys 就会在不给出提示的情况下,丢弃该 IP 数据包。若出站 IP 数据包筛选器允许该数据包,Ipfltdrv.sys 就会将该 IP 数据包传回给 Tcpip.sys。

4.

Tcpip.sys 将该数据包传递给 Ipsec.sys 进行处理。

Ipsec.sys 根据 IPsec 筛选器组,决定是否允许、阻止或保护该数据包。若允许的话,Ipsec.sys 会在不修改该数据包的情况下,将其发回给 Tcpip.sys。 若阻止的话,Ipsec.sys 会在不发出任何提示的情况下,丢弃该数据包。若要进行保护的话,Ipsec.sys 会在将数据包传回给 Tcpip.sys 之前,对其添加适当的 IPsec保护。

Tcpip.sys 随后会通过下一跃点接口,将该 IP 数据包发送到下一跃点地址。

对于运行 Windows XP SP2 或 Windows Server 2003 SP1 并采取常规配置的客户端或服务器计算机(不充当路由器或 NAT,并禁用了 TCP/IP 筛选),源流量的数据包处理路径涉及以下组件:

1.

Windows 防火墙

2.

IPsec

对于上述采用常规配置的基于 Windows 的计算机来说,目标流量的数据包处理路径涉及以下组件:

1.

IPsec

2.

Windows 防火墙

若使用了 IPsec,并启用了 Windows 防火墙,那么可能需要配置这两个组件,以允许想要的流量。譬如,要是您正在配置一台 Web 服务器,并使用 IPsec 保护发往该服务器的 Web 流量,就必须配置以下项目:

1.

一个 IPsec 规则(要求发往和发自该服务器的 IP 地址和 TCP 端口 80 的安全性)。

2.

一个 TCP 端口 80 的 Windows 防火墙例外。

该 IPsec 规则可确保发往 Web 服务器服务的流量受到保护。该 Windows 防火墙例外可确保 Windows 防火墙不会丢弃未经请求的传入请求,来通过 TCP 端口 80 创建到 Web 服务器的连接。由于 IPsec 和 Windows 防火墙都作为单独的组件处理 IP 数据包,因此必须同时配置这两个组件。要是不想让 Windows 防火墙处理受 IPsec 保护的数据包,请配置“Windows 防火墙:允许已验证的 IPSec 跳过”组策略设置。

下图为 TCP/IP 协议驱动程序 (Tcpip.sys) 及其用于在 Windows XP Service Pack 2 和 Windows Server 2003 Service Pack 1 转自TCP/IP 数据包处理路径 下图为 TCP/IP 协议驱动程序 (Tcpip.sys) 及其用于在 Windows XP Service Pack 2 和 Windows Server 2003 Service Pack 1 中处理 IP 数据包的相关组件的简要示意图。下列组件可处理 IP 数据包:IP 转发 为发送或转发的数据包确定下一跃 打开注册表 。运行窗口输入regedit进入注册表。 删除HKEY_LOCAL_MACHINE\ SYS TEM\CurrentControlSet\ Service s\WinSock、HKEY_LOCAL_MACHINE\ SYS TEM\CurrentControlSet\ Service s\WinSock2这两项。 打开C:\ WINDOWS \inf\net tcpip .inf文件,找到[MS_ TCPIP .PrimaryInstall]这一行,将下方的Characteristics = 0xA 受影响系统: Microsoft Windows Server 20H2 ( Server Core Insta Microsoft Windows Server 2019 ( Server Core Insta Microsoft Windows Server 2019 Microsoft Windows Server 2016 ( Server Core Insta Microsoft Windows Server 2016 Microsoft Windows Server SOCKET sock = socket(AF_INET, SOCK_STREAM, IP PROTO_ TCP ); if (sock == INVALID_SOCKET) { // 套接字创建失败 WSACleanup(); return STATUS_UNSUCCESSFUL; 然后可以将套接字绑定到一个地址和端口: struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(12345); // 绑定到端口号 12345 addr.sin_addr.s_addr = INADDR_ANY; iResult = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); if (iResult == SOCKET_ERROR) { // 套接字绑定失败 closesocket(sock); WSACleanup(); return STATUS_UNSUCCESSFUL; 接下来可以开始监听连接: iResult = listen(sock, SOMAXCONN); if (iResult == SOCKET_ERROR) { // 监听失败 closesocket(sock); WSACleanup(); return STATUS_UNSUCCESSFUL; 然后可以接受连接请求: SOCKET clientSock = accept(sock, NULL, NULL); if (clientSock == INVALID_SOCKET) { // 接受连接请求失败 closesocket(sock); WSACleanup(); return STATUS_UNSUCCESSFUL; 现在可以使用 `recv` 和 `send` 函数从套接字中读取和写入数据了: char recvBuf[1024]; iResult = recv(clientSock, recvBuf, sizeof(recvBuf), 0); if (iResult > 0) { // 成功接收到数据 // 可以在这里处理接收到的数据 // ... // 发送响应数据 char sendBuf[] = "Hello, client!"; iResult = send(clientSock, sendBuf, sizeof(sendBuf), 0); if (iResult == SOCKET_ERROR) { // 发送数据失败 } else if (iResult == 0) { // 连接已关闭 } else { // 接收数据失败 最后在 驱动程序 退出时记得关闭套接字和释放套接字库: closesocket(clientSock); closesocket(sock); WSACleanup(); 请注意,在 Windows 驱动程序 中使用套接字通信需要谨慎,因为套接字 I/O 操作可能会阻塞 驱动程序 ,导致系统响应延迟或死锁。建议仅在必要时使用套接字通信。