You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用eBPF在TC中修改端口与校验和后无法获取curl响应

问题:eBPF改写TCP目标端口后校验和异常

我想用eBPF将目标端口为80的数据包重定向到5432端口。本地未使用容器,直接部署了nginx(80端口)和postgresql(5432端口),期望执行curl localhost:80时,程序能将数据包的目标端口改为5432,从而得到与curl localhost:5432相同的结果,仅修改端口号,不改变IP地址。

由于本地三次握手通过lo接口完成,我编写了挂载到TC钩子的eBPF程序,挂载在iface=lo上,尝试改写所有目标端口为80的数据包。我尝试了两种方法重写端口后重新计算校验和,但均出现相同问题:

static __always_inline __u16 csum_fold_helper(__u32 csum) {
    __u32 sum;
    sum = (csum>>16) + (csum & 0xffff);
    sum += (sum>>16);
    return ~sum;
}

SEC("tc_cls")
int tc_egress(struct __sk_buff *skb) {
    void *data_end = (void *)(long)skb->data_end;
    void *data = (void *)(long)skb->data;
    struct ethhdr *eth;
    struct iphdr *iph;
    struct tcphdr *tcph;
    eth = data;
    if ((void *)eth + sizeof(*eth) > data_end) {
        return TC_ACT_OK;
    }
    if (eth->h_proto != __bpf_htons(0x0800)) {
        return TC_ACT_OK;
    }
    iph = data + sizeof(*eth);
    if ((void *)iph + sizeof(*iph) > data_end) {
        return TC_ACT_OK;
    }
    if (iph->protocol != IPPROTO_TCP) {
        return TC_ACT_OK;
    }
    tcph = data + sizeof(*eth) + sizeof(*iph);
    if ((void *)tcph + sizeof(*tcph) > data_end) {
        return TC_ACT_OK;
    }
    if (tcph->dest == __bpf_htons(80)) {
        // update checksum method #1
        // __u64 from = tcph->dest;
        // __u16 new_port = __bpf_htons(5432);
        // tcph->dest = new_port;
        // __u64 res = bpf_skb_store_bytes(skb, ETH_HLEN + sizeof(struct iphdr) + 2, &(new_port), 2, BPF_F_RECOMPUTE_CSUM);
        // update checksum method #2
        __u16 new_port = __bpf_htons(5432);
        __u16 old_csum = tcph->check;
        __u32 sum = bpf_csum_diff(&tcph->dest, 2, &new_port, 2, 0);
        __u16 csum = csum_fold_helper(sum);
        tcph->dest = new_port;
        bpf_l4_csum_replace(skb, ETH_HLEN + sizeof(struct iphdr) + 16, old_csum, csum, BPF_F_PSEUDO_HDR);
        }
    return TC_ACT_OK;
}

用tcpdump验证5432端口的活动时,能看到数据包已到达,但所有带S标志的SYN数据包校验和错误,带R标志的RST数据包校验和正确。然而卸载eBPF程序后直接执行curl localhost:5432,虽然tcpdump显示所有数据包校验和错误,但能正常得到响应。

现需帮忙检查校验和是否正确更新,以及程序是否遗漏其他步骤。

内容的提问来源于stack exchange,提问作者Angela

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 03:25:26