0

GitHub - ihciah/clean-dns-bpf: 基于 Rust + eBPF 丢弃 GFW DNS 污染包

 2 years ago
source link: https://github.com/ihciah/clean-dns-bpf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Clean DNS with eBPF

基于 Rust + eBPF 丢弃 GFW DNS 污染包

注:只在 Linux 上能用,且需要内核支持 XDP。

How to Use

  1. 下载 最新的 release
  2. 想要加载到内核时(记得修改 eth0 为你的出口网卡名,以及修改 clean-dns.elf 的路径):
    sudo ip link set dev eth0 xdp obj ./clean-dns.elf
    
    正常使用的话,只需要在网卡 ready 后把 elf 挂上去就行了(重启后需再次挂载)。
  3. 当你想从内核卸载这个 bpf 时(同样,记得修改 eth0 为你的网卡名):
    sudo ip link set dev eth0 xdp off
    
    正常使用无需卸载。

Features

当挂在本 bpf 后,对应网卡上到 8.8.8.8:53 的 DNS 请求对应响应上的 GFW 污染会被过滤掉。

即你可以在没有梯子的情况下得到正确的 8.8.8.8 对任意域名的解析结果。所以,如果你使用本程序,请记得将 dns 修改为 8.8.8.8。

How It Works

本节大致说明工作原理。

GFW 污染 DNS 的方式为抢答,我们只需要丢弃投毒响应即可获得正确的解析结果。通过 eBPF 我们可以在内核中插入代码,相比在用户态启动代理,这样可以获得更好的性能。

要丢弃投毒响应,重点是找到它们的特征。

以 twitter.com 为例,当向 8.8.8.8 请求 twitter.com 的 A 记录时,正常的响应会返回 2 条结果(1Q2A);而 GFW 只会返回 1 条,但是使用了 2 次抢答。2 次抢答包其中一个 IP Identification = 0x0000,另一个 IP Flags = 0x40(Don't fragment);而正常的响应 IPID 不会是 0 并且 IP Flags = 0。

我们只要 Drop 掉符合对应特征的包即可。这时我们可以验证,twitter.com 可以正确解析(fb 等非 google 服务也正常)。

但对于 google.com,这种办法并没有预期的表现。正常的响应 DNS Flags = 0x8180,而抢答包出现了 0x8590(额外标记 Authoritative 和 Answer Authenticated),0x85a0(额外标记 Authoritative 和 Non-authenticated data: Acceptable)和 0x8580(额外标记 Authoritative) 三种;并且,正常的响应 Answer 中使用 c00c(0b11 + offset) 来复用 Query 中的 Name,抢答响应则重复又写了一遍。

为了避免误杀,我们可以先放行多个 Answer 的包(因为观测到抢答包里只有单个 Answer)。

之后如果标记了 Authoritative,但是 Authority RRs = 0(不确定这个字段我是不是理解对了),则 Drop。

c00c 这个特征也可以作为判断依据,但是要做较多解析和计算,暂时不使用。

这些过滤做完就可以正常拿到 google.com 的 A 记录啦~

这时我们可以验证,google 系的域名也可以正确解析。

For Developers

如果你想二次开发或自行编译,可以参考本节内容。普通用户无需操作。

Build

cargo bpf build clean-dns
sudo cargo bpf load -i eth0 target/bpf/programs/clean-dns/clean-dns.elf

Release

To load elf with ip command(ref).

llvm-objcopy \
--remove-section .debug_loc \
--remove-section .debug_info \
--remove-section .debug_ranges \
--remove-section .BTF.ext \
--remove-section .eh_frame \
--remove-section .debug_line \
--remove-section .debug_pubnames \
--remove-section .debug_pubtypes \
--remove-section .debug_abbrev \
--remove-section .debug_str \
--remove-section .text \
--remove-section .BTF \
--remove-section .symtab \
--remove-section .rel.BTF \
--rename-section xdp/clean_dns=prog \
./clean-dns.elf

Inspired by @llcccd


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK