我正在通过IP过滤器拦截,修改和重新注入传出的IPv4 TCP数据包。 问题是,在我改变数据包并设置IP和TCP校验和后,当我用Wireshark分析结果数据包时,IP校验和等于0(我正在计算的校验和似乎是正确的,因为它等于Wireshark的建议一个)。macOS NKE ipf_filter - IP校验和为0
这里是我下面的步骤,我希望有一个人谁可以当场错误或提出处理事情有更好的方式:
static int handle_packet(mbuf_t* data, int ip_len, int dir, ipf_pktopts_t options)
{
errno_t result = 0;
unsigned char packet[1500];
struct tcphdr *tcp;
struct ip *ip;
mbuf_t old_packet = *data, new_packet;
uint32_t mbufs = 0, packet_bytes = 0;
// zero packet
bzero(packet, sizeof(packet));
// "finalize" the packet so that it is safe to modify it
mbuf_outbound_finalize(*data, AF_INET, 0);
// get length of mbuf chain
do
{
mbufs++;
packet_bytes += mbuf_len(old_packet);
old_packet = mbuf_next(old_packet);
} while (old_packet != NULL);
// copy data to local buffer
if (0 != (result = mbuf_copydata(*data, 0, packet_bytes, packet))) {
printf("mbuf_copydata returned %d", result);
return 0;
}
// pointer to start IP header
ip = (struct ip*)packet;
tcp = (struct tcphdr*)((u_int32_t*)ip + ip->ip_hl);
// only consider SYN packet
if (!(tcp->th_flags & TH_SYN))
return KERN_SUCCESS;
if (0 != (result = mbuf_dup(*data, MBUF_DONTWAIT, &new_packet)))
{
printf("ERROR - mbuf_dup: unable to duplicate mbuf, %d", result);
return 0;
}
/**
… I’m modifying the packet and recalculating ip and tcp’s checksums here
(by previously setting them to 0, so to avoid that the previous values
are considered in the calculation) …
*/
/*
* Copy buffer back to mbuf
*/
if (0 != (result = mbuf_copyback(new_packet, 0, ntohs(ip->ip_len), packet, MBUF_DONTWAIT)))
{
mbuf_freem(new_packet);
switch (result) {
case EINVAL:
printf("ERROR - handle_packet: mbuf_copyback returned EINVAL");
return 0;
break;
case ENOBUFS:
printf("ERROR - handle_packet: mbuf_copyback returned ENOBUFS");
return 0;
break;
default:
break;
}
}
// recompute any checksums invalidated by data changes
// mbuf_outbound_finalize(new_packet, AF_INET, 0); // -> PANIC(m->m_flags & M_PKTHDR)
// is this necessary?
mbuf_set_csum_performed(new_packet, MBUF_CSUM_DID_IP | MBUF_CSUM_IP_GOOD | MBUF_CSUM_DID_DATA | MBUF_CSUM_PSEUDO_HDR, checksum_ip(ip));
result = ipf_inject_output(new_packet, ip_filter_ref, options);
return result == 0 ? EJUSTRETURN : result;
}
static errno_t ip_filter_output(void* cookie, mbuf_t *data, ipf_pktopts_t options)
{
struct ip *ip;
char src[32], dst[32];
int ip_len;
// pointer to start IP header
ip = (struct ip*)mbuf_data(*data);
ip_len = ntohs(ip->ip_len);
bzero(src, sizeof(src));
bzero(dst, sizeof(dst));
// converts the network address structure into a character string
inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src));
inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst));
// avoid congestion and filter only packets from/to tcpcrypt website
if (ip->ip_p == IPPROTO_TCP
&& mbuf_flags(*data) == MBUF_PKTHDR) {
return handle_packet(data, ip_len, DIRECTION_OUT /* 1 */, options);
}
// continue with normal processing of the packet
return KERN_SUCCESS;
}
我怀疑越来越零是重新计算的预期后果整个头部的校验和,即它导致计算出的总和自行消失。
无论如何,我真的不明白为什么会发生这种情况。
有没有人知道答案或可以帮助?
非常感谢你提前,
罗密欧
他正在调用'mbuf_outbound_finalize()',请参阅该方法的文档。不管你的硬件是否卸载,都调用这个函数来保证正确的校验和。从文档:“*有许多操作是在硬件中执行的,例如计算校验和。这个函数将在软件中执行计划在硬件中完成的各种操作。*”所以你的回答没有意义,我不明白为什么这是被接受的答案。 – Mecki