惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
博客园 - Franky
腾讯CDC
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
V
V2EX
N
Netflix TechBlog - Medium
量子位
Jina AI
Jina AI
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
爱范儿
爱范儿
博客园 - 叶小钗
D
Docker
MongoDB | Blog
MongoDB | Blog
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss

卡瓦邦噶!

服务器高性能网络调优 | 卡瓦邦噶! 为何写作 | 卡瓦邦噶! 读《金阁寺》 | 卡瓦邦噶! 雨季又来 | 卡瓦邦噶! MTU Probe 引起的初始延迟 | 卡瓦邦噶! 3.5 秒的固定延迟问题 | 卡瓦邦噶! 学习网络的一点经验 | 卡瓦邦噶! ARP 问题诊断 | 卡瓦邦噶! 网络断断续续…… | 卡瓦邦噶! Piccolo P2P 镜像分发 | 卡瓦邦噶! 一起看电影 | 卡瓦邦噶! 《征服C指针》 | 卡瓦邦噶! 我的姥姥 | 卡瓦邦噶! Python的哲学 Python 3.5的新特性 学校不教的计算机课 垃圾回收(GC)的三种基本方式 在编程中体验纯粹的快乐 从《美丽新世界》谈自由 在快钱实习 迷人的嗓音和迷人的故事——《Sleepyhead》 Python 的十个自然语言处理工具 记一个愚蠢的bug 一年炉石传说的游戏体验 《以撒的结合:重生》网页版图鉴 分清 C++的指针、引用和数组 笑话三则 自由比皇帝更伟大——《悲惨世界》笔记 Git 10 周年访谈:Linus 讲述背后故事 用 0x3f3f3f3f 设定最大int值的优点
XDP 实现所有的 TCP 端口都接受 TCP 建立连接
laixintao · 2025-06-08 · via 卡瓦邦噶!

#include <linux/bpf.h>

#include <bpf/bpf_helpers.h>

#include <bpf/bpf_endian.h>

#include <linux/if_ether.h>

#include <linux/ip.h>

#include <linux/icmp.h>

#include <linux/tcp.h>

#include <linux/in.h>

#define MAX_CHECKING 4

#define MAX_CSUM_WORDS 750

static __always_inline __u32 sum16(const void* data, __u32 size, const void* data_end) {

    __u32 sum = 0;

    const __u16 *ptr = (const __u16 *)data;

    #pragma unroll

    for (int i = 0; i < MAX_CSUM_WORDS; ++i) {

        if ((const void *)(ptr + 1) > (data + size)) {

            break;

        }

        if ((const void *)(ptr + 1) > data_end) {

             return sum;

        }

        sum += *ptr;

        ptr++;

    }

    // Handle the potential odd byte at the end if size is odd

    if (size & 1) {

        const __u8 *byte_ptr = (const __u8 *)ptr; // ptr is now after the last full word

        // BPF Verifier check: Ensure the single byte read is within packet bounds

        if ((const void *)(byte_ptr + 1) <= data_end && (const void *)byte_ptr < data_end) {

            // In checksum calculation, the last odd byte is treated as the

            // high byte of a 16-bit word, padded with a zero low byte.

            // E.g., if the byte is 0xAB, it's treated as 0xAB00.

            sum += (__u16)(*byte_ptr) << 8;

        }

        // If the bounds check fails, we just return the sum calculated so far.

    }

    return sum;

}

SEC("xdp")

int tcp_bounce(struct xdp_md *ctx) {

    void *data = (void *)(long)ctx->data;

    void *data_end = (void *)(long)ctx->data_end;

    struct ethhdr *eth = data;

    if ((void *)eth + sizeof(*eth) > data_end)

        return XDP_PASS;  // not enough data

    if (eth->h_proto != bpf_htons(ETH_P_IP))

        return XDP_PASS;

    struct iphdr *iph = data + sizeof(*eth);

    if ((void *)iph + sizeof(*iph) > data_end)

        return XDP_PASS;

    if (iph->protocol != IPPROTO_TCP)

        return XDP_PASS;

    //check ip len

    int ip_hdr_len = iph->ihl*4;

    if((void *)iph + ip_hdr_len > data_end)

        return XDP_PASS;

    // convert to TCP

    struct tcphdr *tcph = (void *)iph + ip_hdr_len;

    if ((void *)tcph + sizeof(*tcph) > data_end)

        return XDP_PASS;

    if (!(tcph->syn) || tcph->ack)

        return XDP_DROP;

    // swap MAC addresses

    __u8 tmp_mac[ETH_ALEN];

    __builtin_memcpy(tmp_mac, eth->h_source, ETH_ALEN);

    __builtin_memcpy(eth->h_source, eth->h_dest, ETH_ALEN);

    __builtin_memcpy(eth->h_dest, tmp_mac, ETH_ALEN);

    // swap IP addresses

    __be32 tmp_ip = iph->saddr;

    iph->saddr = iph->daddr;

    iph->daddr = tmp_ip;

    // TCP

    // swap port

    __be16 tmpsrcport = tcph->source;

    tcph->source = tcph->dest;

    tcph->dest = tmpsrcport;

    // syn+ack

    tcph->ack = 1;

    __u32 ack_seq = bpf_ntohl(tcph->seq) + 1;

    tcph->ack_seq = bpf_htonl(ack_seq);

    // checksum pseudo header

    __u32 csum = 0;

    tcph->check = (__be16)csum;

    if ((void *)&iph->saddr + 8 > data_end)

        return XDP_PASS;

    csum = bpf_csum_diff(0, 0, (__be32 *)&iph->saddr, 8, csum);

    __u16 tcp_len = bpf_ntohs(iph->tot_len) - ip_hdr_len;

    csum += (__u32)(bpf_htons(IPPROTO_TCP) << 16) | bpf_htons(tcp_len);

    csum += sum16(tcph, tcp_len, data_end);

    while (csum >> 16)

        csum = (csum & 0xFFFF) + (csum >> 16);

    tcph->check = (__be16)~csum;

    return XDP_TX;

}

char _license[] SEC("license") = "GPL";