xdp-dns-evadeproxy README

The project's README from github.com/Oihalitz/xdp-dns-evadeproxy. As one markdown file: README.md.

xdp.es

evade-proxy

Cuando un operador bloquea IPs de forma indiscriminada, esto se lo salta.

Proxy DNS del resolver público xdp.es

Usar el DNS · Estadísticas · Cómo funciona · IPs bloqueadas

Desarrollado por Oihalitz con mateodd1


Usar el DNS de xdp.es

No hace falta clonar este repo. Guía y copiar-y-pegar en xdp.es.

Adblock

publicidad y malware fuera · DNSSEC · zero-logs

Webhttps://xdp.es
DNS85.208.114.51   2a0e:97c0:c40::51
DoHhttps://dns.xdp.es/dns-query
DoTdns.xdp.es · puerto 853
DoQquic://dns.xdp.es:853
iOS / macOSperfil DoH · perfil DoT

Standard

sin adblock · la misma evasión · DNSSEC · zero-logs

Webhttps://xdp.es
DNS85.208.114.52   2a0e:97c0:c40::52
DoHhttps://lite.xdp.es/dns-query
DoTlite.xdp.es · puerto 853
DoQquic://lite.xdp.es:853
iOS / macOSperfil DoH · perfil DoT

Qué es esto

A veces un operador no bloquea un dominio: bloquea la IP. En Cloudflare anycast esa misma dirección la comparten cientos de sitios, así que el corte es indiscriminado — cae lo que tocaba y lo que no. evade-proxy detecta esas IPs y, en la respuesta DNS, las sustituye por otra del mismo prefijo que no está cortada.

Tres piezas:

evade-proxy Proxy DNS en Rust. Reescribe en el paquete las IPs anycast bloqueadas.
Lista de IPs Cada pocos segundos actualiza qué direcciones están cortadas y se lo pasa al proxy.
Sonda residencial Un equipo en casa confirma IPv6 y CDNs que no son anycast. El servidor en datacenter no ve el bloqueo; la línea del abonado sí.

Cómo se lo salta

cliente → Blocky / DoH / DoT → evade-proxy :5335 → Unbound :5336
                                   │
                                   ├─ blocked_ips.txt       ← lista pública + sonda IPv4
                                   ├─ blocked_ipv6.txt      ← sonda IPv6
                                   ├─ cloudflare_prefixes   ← AS13335
                                   └─ redirects.txt         ← sonda (GitHub / Fastly / Akamai)
  1. Unbound responde con la IP real (DNSSEC).
  2. Si un A, AAAA o hint HTTPS/SVCB está en la blocklist y en un prefijo Cloudflare, el proxy la cambia por un vecino del mismo prefijo que no esté listado, y pone TTL 30 s (EVADE_REWRITE_TTL; 0 restaura el comportamiento anterior, sin caché en el cliente).
  3. Fuera de Cloudflare no se toca nada. En CDNs no-anycast la sonda fija un redirect a una IP verificada desde casa y desde el servidor.

La reescritura es in-place: punteros de compresión, flags y orden de registros se conservan.

Compilar

Rust estable (1.82+):

cargo test --locked
cargo build --release --locked
./target/release/evade-proxy --help

Modo prueba (convive con producción: :15335 / :15337, métricas :15339):

./target/release/evade-proxy --test \
  --redirect example.com=203.0.113.7

--redirect solo se acepta con --test.

Instalar el servidor

Debian/Ubuntu, como root, desde el clone:

sudo ./scripts/install.sh

Instala el binario en /usr/local/bin/evade-proxy, el árbol en /opt/xdp-dns-evadeproxy, escribe /etc/evade-proxy.env y arranca el proxy + el timer de la lista de IPs.

sudo editor /etc/evade-proxy.env    # PROBE_TOKEN=…
sudo systemctl enable --now xdp-probe-server

Exponer el ingest de la sonda con TLS (Caddy):

handle /probe/* {
    reverse_proxy 127.0.0.1:8090
}

No ejecutar a la vez que un evade_proxy en Python: mismos puertos.

Docker

Alternativa a install.sh para quien prefiera contenedores. El stack de ejemplo levanta evade-proxy, un unbound recursivo con validación DNSSEC (su upstream en 127.0.0.1:5336/:5338) y el bucle que sincroniza blocklist + prefijos Cloudflare:

cp evade-proxy.env.example evade-proxy.env   # PROBE_TOKEN=… si usas la sonda
docker compose up -d --build

unbound y blocklist-updater se unen al network namespace de evade-proxy (network_mode: "service:evade-proxy") porque el proxy siempre resuelve su upstream en 127.0.0.1 (ver tabla de puertos más abajo) — no hay forma de apuntarlo a otro contenedor por nombre de servicio.

Para ponerlo delante de un servidor DNS que ya use network_mode: host en el mismo host (p. ej. AdGuard Home), añade network_mode: host al servicio evade-proxy, quita su bloque ports:, y apunta el DNS upstream de ese servidor a 127.0.0.1:5335.

Lista de IPs bloqueadas

scripts/update-blocked-ips.sh, timer cada 15 s:

  1. Descarga el listado público IPv4 (BLOCKLIST_URL)
  2. Se queda solo con direcciones IPv4
  3. Une las IPs que confirmó la sonda
  4. Escribe /etc/unbound/blocked_ips.txt — evade-proxy lo recarga cada 5 s
  5. Une IPv6 de la sonda en /etc/unbound/blocked_ipv6.txt
  6. Actualiza prefijos Cloudflare AS13335 (una vez al día)

No hace falta vaciar la caché del resolver: el proxy reescribe a la salida, también las respuestas ya cacheadas.

Sonda residencial

Cubre IPv6 y CDNs no-anycast. Pide objetivos, sondea TCP:443 + TLS(SNI) + HTTP HEAD y reporta. El servidor solo marca bloqueo si sirve en el datacenter y no en casa, con histéresis (3 rondas para añadir, 2 para quitar).

En probe/domains.json:

En casa (Raspberry Pi / mini-PC):

sudo ./probe/agent/install-agent.sh https://dns.xdp.es/probe <TOKEN> mi-casa

Solo conexiones salientes (funciona detrás del NAT). Detalle: probe/README.md.

Puertos

Escucha Upstream Uso
127.0.0.1:5335 UDP/TCP :5336 camino principal
127.0.0.1:5337 UDP/TCP :5338 segundo camino (Lite)
127.0.0.1:5339 HTTP — /metrics y stats JSON
127.0.0.1:8090 HTTP — ingest de la sonda

Variables: evade-proxy.env.example (EVADE_REWRITE_TTL incluido). Redirects temporales de producción (/run/evade-proxy/redirects.txt):

ejemplo.es=104.18.13.102 1787609000

Layout

src/main.rs                              evade-proxy
scripts/update-blocked-ips.sh            lista de IPs + sonda
scripts/update-cloudflare-prefixes.py    AS13335
probe/probe-server.py                    ingest + diferencial
probe/domains.json                       objetivos
probe/agent/                             sonda de casa
systemd/                                 unidades

Oihalitz con mateodd1 · xdp.es · MIT

xdp-dns-evadeproxy (Oihalitz/xdp-dns-evadeproxy)

Searching Database…

Что это такое?DNS-прокси на Rust, который обходит сплошные IP-блокировки провайдеров: когда оператор отрезает anycast-адрес, на котором живут сотни сайтов Cloudflare, прокси подменяет этот IP в DNS-ответе на незаблокированного соседа из того же префикса.
Это что-то, что я ставлю на свой сервер, или хостинговый сервис, на который можно просто направить свои устройства?И то, и другое. Авторы держат публичные резолверы — dns.xdp.es и lite.xdp.es — доступные по обычному IP, а также через DoH, DoT и DoQ на порту 853, так что можно просто пользоваться ими; этот репозиторий — серверная часть на случай, если хотите разместить всё у себя.
Что нужно, чтобы запустить свой экземпляр?Собрать проект на Rust 1.82+, а на сервере с Debian/Ubuntu запустить установочный скрипт от root: он положит бинарник в /usr/local/bin/evade-proxy, дерево файлов — в /opt/xdp-dns-evadeproxy и запустит прокси вместе с таймером обновления блоклиста. Альтернатива — Docker compose-стек.
Кроме самого прокси, что ещё нужно для полного комплекта?Пример стека дополняет его рекурсивным резолвером unbound с проверкой DNSSEC и циклом обновления блоклиста. Для полного покрытия IPv6 и CDN без anycast понадобится ещё residential-проба, которая отчитывается с домашнего подключения.
Переписывание адресов спасает любой заблокированный сайт?Нет — подменяются только anycast-IP Cloudflare, всё вне этих префиксов остаётся как есть. CDN без anycast вроде GitHub, Fastly или Akamai идут через проверенные пробами перенаправления, а вместе со старым Python-вариантом evadeproxy это запустить нельзя — они делят одни и те же порты.
Где всё это вообще работает?Серверная часть рассчитана на Debian/Ubuntu (работает и Docker) и слушает только localhost: 5335 и 5337 для DNS, 5339 для метрик, 8090 для приёма данных проб. Residential-проба задумана для Raspberry Pi или мини-компьютера за домашним NAT и делает только исходящие соединения.
Что происходит с моими запросами на хостинговых резолверах?Резолверы xdp.es заявляют проверку DNSSEC, нулевое логирование и встроенную фильтрацию рекламы и вредоносных сайтов. При самостоятельном размещении всё остаётся на вашей машине, а прокси слушает только localhost.
Что именно меняется в DNS-ответе?Если запись A, AAAA или подсказка HTTPS/SVCB одновременно есть в блоклисте и лежит в префиксе Cloudflare, прокси меняет IP на незаблокированного соседа из того же префикса и ставит TTL 30 с — это настраивается через EVADEREWRITETTL, где 0 возвращает старое поведение. Замена делается на месте, с сохранением compression-указателей, флагов и порядка записей.
Зачем кроме блоклиста ещё residential-проба?Потому что сервер в дата-центре не видит того, что видит абонентская линия. Небольшая коробка дома проверяет цели по TCP:443, TLS(SNI) и HTTP HEAD и отчитывается серверу; блокировку сервер помечает, только если сайт нормально открывается из дата-центра, но не открывается из дома, с гистерезисом: 3 раунда, чтобы добавить IP, и 2, чтобы убрать.
Почему переписывать IP, а не просто указать другой резолвер?Потому что блокировка бьёт по адресу, а не по домену: любой резолвер вернёт тот же заблокированный anycast-IP, на котором сидят сотни сайтов. Замена его на живого соседа из того же префикса Cloudflare возвращает доступ всему, что работает на этом адресе.
Как это поспевает за операторами, когда они вводят или снимают блокировки?Скрипт запускается по таймеру каждые 15 секунд: скачивает публичный список заблокированных IP, оставляет IPv4-записи, добавляет то, что подтвердила домашняя проба, и пишет /etc/unbound/blockedips.txt, который прокси перечитывает каждые 5 с. Данные о префиксах Cloudflare обновляются раз в день.
Creator
Oihalitz
Size
0.2 MB
Stars
131
Updated
CommitOct 15
Age
1mo
Commits · 90 Days