You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

FWPM_LAYER_DATAGRAM_DATA_V4层修改环回入站UDP数据包失败的技术求助

FWPM_LAYER_DATAGRAM_DATA_V4层修改环回入站UDP数据包失败的技术求助

我仔细看了你的问题和代码,遇到的STATUS_DATA_NOT_ACCEPTED错误在环回UDP入站注入场景里很常见,主要和数据包头部构造错误或者WFP对环回流量的特殊校验逻辑有关。我来帮你拆解问题和给出解决方案:

一、先修正代码里的明显致命错误

你的代码里有一个关键疏漏:FWP_BYTE_ARRAY16 tep变量完全没有初始化就传给了FwpsConstructIpHeaderForTransportPacket,这会导致构造的IP头部目的地址是随机垃圾数据,内核自然会拒绝接收这个非法数据包,直接返回STATUS_DATA_NOT_ACCEPTED

你需要把原来数据包的本地IP地址(也就是当前入站包的目的IP)赋值给tep,修正后的代码片段如下:

// 初始化目的地址(原数据包的本地IP地址,即入站包的接收端IP)
FWP_BYTE_ARRAY16 tep = {0};
tep.size = 4; // IPv4地址长度固定为4字节
UINT32 LocalAddress = inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_LOCAL_ADDRESS].value.uint32;
RtlCopyMemory(tep.byteArray, &LocalAddress, 4);

// 再调用FwpsConstructIpHeaderForTransportPacket构造IP头部
status = FwpsConstructIpHeaderForTransportPacket(
    NetBufferList,
    IpHeaderSize,
    AF_INET,
    (const UCHAR*)&RedirectAddress, // 新的源IP(127.0.0.1)
    (UINT8*)&tep, // 正确的目的IP(原数据包的本地接收IP)
    IPPROTO_UDP,
    0,
    NULL,
    0,
    0,
    NULL,
    0,
    0
);

二、环回UDP入站注入的特殊限制

即使修正了上述错误,你可能还是会遇到环回流量的注入限制——WFP内核模块对环回入站数据包的校验非常严格,因为环回流量完全在内核内部流转,不需要经过物理网卡,FwpsInjectTransportReceiveAsync对于环回场景的支持本身就有限。

如果修正后依然失败,你可以尝试以下两种替代方案:

方案1:改用发送注入模拟入站

对于环回UDP流量,你可以把修改后的数据包作为出站包注入(调用FwpsInjectTransportSendAsync),内核会自动将环回出站包路由到本地接收端点,效果和入站注入完全一致,还能绕过FwpsInjectTransportReceiveAsync的环回校验限制。

核心步骤:

  1. 克隆数据包并修改源/目的IP和端口
  2. 调用FwpsInjectTransportSendAsync注入,参数使用环回接口索引、原compartment ID等
  3. 原数据包直接block并absorb

方案2:换用更早的处理层

如果入站修改的需求必须在接收路径处理,可以尝试把处理逻辑移到FWPM_LAYER_INBOUND_TRANSPORT_V4层(该层在数据包到达应用层之前,但比DATAGRAM_DATA层更早),这个层对环回流量的校验限制更少,更适合做数据包内容修改。

三、额外注意事项

  1. 环回接口索引:确保你使用的InterfaceIndex是环回接口的索引(通常为1),可以通过GetIfEntry2等API确认系统中环回接口的具体索引。
  2. 校验和处理:你已经把UDP校验和设为0,这是正确的——内核IP栈会自动为修改后的数据包重新计算IP和UDP校验和,无需手动处理。
  3. 微软ddproxy样本的问题:ddproxy样本本身没有针对环回流量做特殊适配,所以你需要手动修改样本中的注入逻辑,比如替换为发送注入方式,或者修正目的地址的构造逻辑。

先试试修正tep变量的初始化问题,这大概率能解决你当前的STATUS_DATA_NOT_ACCEPTED错误。如果还有问题,再尝试改用发送注入的方式。

火山引擎 最新活动