Cuando un operador bloquea IPs de forma indiscriminada, esto se lo salta.
Proxy DNS del resolver público xdp.es
No hace falta clonar este repo. Guía y copiar-y-pegar en xdp.es.
publicidad y malware fuera · DNSSEC · zero-logs
| Web | https://xdp.es |
| DNS | 85.208.114.51 2a0e:97c0:c40::51 |
| DoH | https://dns.xdp.es/dns-query |
| DoT | dns.xdp.es · puerto 853 |
| DoQ | quic://dns.xdp.es:853 |
| iOS / macOS | perfil DoH · perfil DoT |
sin adblock · la misma evasión · DNSSEC · zero-logs
| Web | https://xdp.es |
| DNS | 85.208.114.52 2a0e:97c0:c40::52 |
| DoH | https://lite.xdp.es/dns-query |
| DoT | lite.xdp.es · puerto 853 |
| DoQ | quic://lite.xdp.es:853 |
| iOS / macOS | perfil DoH · perfil DoT |
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í. |
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)
- Unbound responde con la IP real (DNSSEC).
- 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;0restaura el comportamiento anterior, sin caché en el cliente). - Fuera de Cloudflare no se toca nada. En CDNs no-anycast la sonda fija un
redirecta 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.
Rust estable (1.82+):
cargo test --locked
cargo build --release --locked
./target/release/evade-proxy --helpModo 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.
Debian/Ubuntu, como root, desde el clone:
sudo ./scripts/install.shInstala 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-serverExponer 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.
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 --buildunbound 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.
scripts/update-blocked-ips.sh, timer cada 15 s:
- Descarga el listado público IPv4 (
BLOCKLIST_URL) - Se queda solo con direcciones IPv4
- Une las IPs que confirmó la sonda
- Escribe
/etc/unbound/blocked_ips.txt— evade-proxy lo recarga cada 5 s - Une IPv6 de la sonda en
/etc/unbound/blocked_ipv6.txt - 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.
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:
cf-blocklist— Cloudflare. La IP entra en la blocklist; el proxy salta al vecino.verified-pool— GitHub / Fastly / Akamai. Se fijadominio=IP_sanaenredirects.txt.
En casa (Raspberry Pi / mini-PC):
sudo ./probe/agent/install-agent.sh https://dns.xdp.es/probe <TOKEN> mi-casaSolo conexiones salientes (funciona detrás del NAT). Detalle: probe/README.md.
| 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
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