【发布时间】:2021-01-18 01:21:22
【问题描述】:
我正在尝试修改从客户端接收到的 UDP 有效负载,以克隆和重定向数据包以响应它。交换 MAC 和 IP 地址以及克隆已经完成,但我不知道如何修改 UDP 有效负载。
我想通过创建一个新的有效负载(更好)并在数据包中替换它或通过替换将具有以下 3 个字节的有效负载发送回客户端:0x1a 0x31 0x0f。我该怎么做?
到目前为止,这是我的代码:
根据评论更新(现在只需要重新计算校验和):
int pingpong(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
void *data_end = (void *)(long)skb->data_end;
struct ethhdr *eth = data;
struct iphdr *ip;
struct udphdr *udpdata;
if ((void *)eth + sizeof(*eth) > data_end) {
return TC_ACT_UNSPEC;
}
ip = data + sizeof(*eth);
if ((void *)ip + sizeof(*ip) > data_end) {
return TC_ACT_UNSPEC;
}
udpdata = (void *)ip + sizeof(*ip);
if ((void *)udpdata + sizeof(*udpdata) > data_end) {
return TC_ACT_UNSPEC;
}
if (eth->h_proto != htons(ETH_P_IP)) {
return TC_ACT_UNSPEC;
}
if (ip->protocol != IPPROTO_UDP) {
return TC_ACT_UNSPEC;
}
unsigned int payload_size;
unsigned char *payload;
payload_size = ntohs(udpdata->len) - sizeof(*udpdata);
payload = (unsigned char *)udpdata + sizeof(*udpdata);
if ((void *)payload + payload_size > data_end) {
return TC_ACT_UNSPEC;
}
// 1. Swap the MACs
__u8 tmp_mac[ETH_ALEN];
memcpy(tmp_mac, eth->h_dest, ETH_ALEN);
memcpy(eth->h_dest, eth->h_source, ETH_ALEN);
memcpy(eth->h_source, tmp_mac, ETH_ALEN);
// 2. Swap the IPs
if (eth->h_proto == htons(ETH_P_IP)) {
__u32 tmp_ip = ip->saddr;
ip->saddr = ip->daddr;
ip->daddr = tmp_ip;
}
// 3. Swap the ports
udpdata->source = port;
udpdata->dest = srcport;
// 4. Change the payload to be 0x1a 0x31 0x0f
bpf_skb_adjust_room(skb, -1, BPF_ADJ_ROOM_NET, 0);
uint8_t byte1 = 0x1a;
uint8_t byte2 = 0x31;
uint8_t byte3 = 0x0f;
int ret = bpf_skb_store_bytes(skb, payload_offset, &byte1, sizeof(byte1), 0);
ret = bpf_skb_store_bytes(skb, payload_offset+1, &byte2, sizeof(byte2), 0);
ret = bpf_skb_store_bytes(skb, payload_offset+2, &byte3, sizeof(byte3), 0);
// Re-calculate the checksum
bpf_l4_csum_replace(skb, L4_CSUM_OFF, datap[0], byte1, 0);
bpf_l4_csum_replace(skb, L4_CSUM_OFF, datap[1], byte2, 0);
bpf_l4_csum_replace(skb, L4_CSUM_OFF, datap[2], byte3, 0);
// Not working!
// Final: Redirect to be sent
bpf_clone_redirect(skb, skb->ifindex, 0);
}
如果我只是更改有效负载而不使用 adjust_room 函数删除 1 字节,则会发送它,但最后一个字节是 00。我想删除它。
请问有什么建议吗?谢谢!
【问题讨论】:
-
您是否提前知道现有 UDP 有效负载的大小?
-
@pchaigno 不幸的是没有。但有可能算不出来吗? (payload_length)
-
@pchaigno 实际上它应该是 4 个字节(我的答案应该是 3 个字节),但是最好有一个不需要知道的更通用的解决方案。
-
你看过
bpf_skb_adjust_room()助手吗?您应该能够将有效负载大小缩小payload_size - <sizeof(new_payload)>? (注意:另请参阅bpf_l3_csum_replace()/bpf_l4_csum_replace()以重新计算您的校验和) -
@Qeole 谢谢,对于“bpf_skb_adjust_room”,我收到“警告:函数 'bpf_skb_adjust_room' 的隐式声明在 C99 中无效”
标签: c linux-kernel kernel bpf ebpf