Dropping GFW DNS contaminated packets based on Rust + eBPF

Overview

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 服务也正常)。

screen shot:non-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 系的域名也可以正确解析。 screen shot:google

For Developers

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

Install cargo-bpf

cargo install cargo-bpf --git https://github.com/redsift/redbpf

Build

cargo bpf build clean-dns

Run

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

Note

Inspired by @llcccd

You might also like...
Minimal DNS server built in Rust with rule system and logging.

MinDNS MinDNS is a minimal DNS server written in Rust. It is intended to be used as a firewall, black-hole or proxy DNS server. ⚡ Features Fully async

A Lightning-Fast DNS Resolver written in Rust 🦀
A Lightning-Fast DNS Resolver written in Rust 🦀

dnsresolver A Lightning-Fast DNS Resolver Table of Contents Installation Usage Basic Usage Resolving Hosts with Ports Virtual Host Enumeration Using U

Library + CLI-Tool to measure the TTFB (time to first byte) of HTTP requests. Additionally, this crate measures the times of DNS lookup, TCP connect and TLS handshake.

TTFB: CLI + Lib to Measure the TTFB of HTTP/1.1 Requests Similar to the network tab in Google Chrome or Mozilla Firefox, this crate helps you find the

Utility for working with reverse DNS

RDNS RDNS is a small Rust CLI utility for performing single and bulk reverse DNS (PTR) lookups. Usage RDNS 0.1.0 Joe Banks [email protected] Utilities for

Implementation of algorithms for Domain Name System (DNS) Cookies construction

DNS Cookie RFC7873 left the construction of Server Cookies to the discretion of the DNS Server (implementer) which has resulted in a gallimaufry of di

A wrapper for the Google Cloud DNS API

cloud-dns is a crate providing a client to interact with Google Cloud DNS v1

Automatically updates your Cloudflare DNS records for specific zones. Especially useful if you have dynamic IP address

Cloudflare DNS updater What does it do? Cloudflare DNS updater updates specified dns records for specified zones effortlessly and automatically. It wa

Resolved - a simple DNS server for home networks

resolved resolved (pronounced "resolved", not "resolved") is a simple DNS server for home networks. To that end, it supports: Recursive and non-recurs

DNS resolver for split-horizon scenarios

polyresolver is a resolver for split-horizon scenarios polyresolver is used to root domain names to different nameservers for the purposes of resolvin

Comments
  • 在kali linux上使用release文件的问题

    在kali linux上使用release文件的问题

    └─# ip link set dev eth0 xdp obj ./clean-dns.elf libbpf: elf: couldn't find symbol table in ./clean-dns.elf, stripped object file? ERROR: opening BPF object file failed

    opened by Black-Kamous 0
  • CentOS   No ELF library support compiled in.

    CentOS No ELF library support compiled in.

    [root@localhost rust]# sudo ip link set dev eth0 xdp obj ./clean-dns.elf No ELF library support compiled in. [root@localhost rust]# uname -r 5.14.13-1.el7.elrepo.x86_64 [root@localhost rust]#

    尝试过很多种方法。

    opened by cloudmisst 0
  • Segmentation fault

    Segmentation fault

    系统:

    uname -a
    Linux Debian-VM-x64 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
    

    运行:

    ip link set dev ens33 xdp obj ./clean-dns.elf
    Segmentation fault
    

    日志:

    Oct  9 14:34:11 Debian-VM-x64 kernel: [  212.184511] ip[2211] segfault at 10 ip 00007fcf5f36e582 sp 00007fff796b4de0 error 4 in libbpf.so.0.3.0[7fcf5f358000+23000]
    Oct  9 14:34:11 Debian-VM-x64 kernel: [  212.184517] Code: 49 63 47 60 48 8d 58 01 48 69 c0 d8 00 00 00 48 89 5c 24 18 48 89 44 24 50 49 8b 9f 00 01 00 00 48 b8 ab aa aa aa aa aa aa aa <48> 8b 73 10 48 f7 e6 48 c1 ea 04 48 89 54 24 10 48 83 fe 170f 86
    
    opened by rampageX 1
Owner
ihc童鞋@提不起劲
ihc童鞋@提不起劲
Obtain (wildcard) certificates from let's encrypt using dns-01 without the need for API access to your DNS provider.

Agnos Presentation Agnos is a single-binary program allowing you to easily obtain certificates (including wildcards) from Let's Encrypt using DNS-01 c

Arthur Carcano 246 Dec 20, 2022
A minimalistic encryption protocol for rust async streams/packets, based on noise protocol and snow.

Snowstorm A minimalistic encryption protocol for rust async streams / packets, based on noise protocol and snow. Quickstart Snowstorm allows you to se

Black Binary 19 Nov 22, 2022
Replay packets from pcap -file to network interface

pktreplay can be used to read packets from pcap file or interface and write them into interface. By default packets are written with the same rate they have been saved into the pcap file, or, when reading from interface, as fast as they are received.

Jukka Taimisto 3 Nov 23, 2022
A multi-targets ping tool and library, which supports 10,000 packets/second, accurate latency

mping-rs a multi-targets ping tool, which supports 10,000 packets/second, accurate latency. 一个高频ping工具,支持多个目标。 正常的ping一般用来做探测工具,mping还可以用来做压测工具。 Go版本:

smallnest 25 Oct 29, 2023
A Rust based DNS client, server, and resolver

Trust-DNS A Rust based DNS client, server, and Resolver, built to be safe and secure from the ground up. This repo consists of multiple crates: Librar

Benjamin Fry 2.7k Dec 30, 2022
Userspace libpcap-based tool to mirror your dns traffic

DNS traffic mirroring tool (dns-mirror) Description Userspace libpcap-based tool. dns-mirror sniffs dns packets on the given interface and proxies it

Timofey 1 Mar 15, 2022
Dns subdomain finding tool, based off of the c application of the same name

dnsmap-rs Tool for brute-forcing/scanning for existing subdomains in a domain. Based on dnsmap c application that is packaged in kali linux. Can query

Tomás Alvarez 3 Oct 19, 2022
Third party Google DNS client for rust.

google-dns-rs Documentation Install Add the following line to your Cargo.toml file: google-dns-rs = "0.3.0" Usage use google_dns_rs::api::{Dns, DoH, R

Eduardo Stuart 2 Nov 13, 2021
A primitive DNS server written in Rust for fun.

vòdo A primitive DNS server written in Rust for fun. @lucavallin ➜ /workspaces/vodo (main) $ ./target/debug/vodo -h A primitive DNS server written in

Luca Cavallin 3 Jul 27, 2023
RDE1 (Rusty Data Exfiltrator) is client and server tool allowing auditor to extract files from DNS and HTTPS protocols written in Rust. 🦀

Information: RDE1 is an old personal project (end 2022) that I didn't continue development on. It's part of a list of projects that helped me to learn

Quentin Texier (g0h4n) 32 Oct 6, 2023