
El tema está bastante fuera de escena, lo sé. Por ejemplo, hay un excelente artículo , pero solo se considera allí la parte IP de la lista de bloqueo. También agregaremos dominios.
Debido al hecho de que los tribunales y el ILV bloquean todo a derecha e izquierda, y los proveedores están tratando de no caer bajo las multas emitidas por "Revizorro", las pérdidas asociadas de las cerraduras son bastante grandes. Sí, y entre los sitios bloqueados "legalmente" hay muchos útiles (hola, rutracker)
Vivo fuera de la jurisdicción del ILV, pero mis padres, parientes y amigos se quedaron en casa. Por lo tanto, se decidió idear una forma de evitar bloqueos que sea fácil para aquellos que están lejos de TI, preferiblemente sin su participación.
En este artículo, no describiré las cosas básicas de la red en pasos, pero describiré los principios generales de cómo se puede implementar este esquema. Por lo tanto, es imprescindible conocer cómo funciona la red en general y en Linux en particular.
Tipos de cerraduras
Primero, vamos a actualizar lo que está bloqueado.
Hay varios tipos de bloqueos en XML paginado de ILV:
Para simplificar, los reduciremos a dos: IP y dominio, y simplemente retiraremos el dominio del bloqueo de URL (más precisamente, ya lo hemos hecho por nosotros).
Las buenas personas de Roskomsvoboda han implementado una API maravillosa a través de la cual podemos obtener lo que necesitamos:
Acceder a sitios bloqueados
Para hacer esto, necesitamos algunos VPS extranjeros pequeños, preferiblemente con tráfico ilimitado, hay muchos de esos 3-5 dólares. Debe llevarlo al extranjero para que el ping no sea muy grande, pero tenga en cuenta que Internet y la geografía no siempre coinciden. Y dado que no hay SLA por 5 dólares, es mejor tomar más de 2 piezas de diferentes proveedores para la tolerancia a fallas.
A continuación, necesitamos configurar el túnel encriptado desde el enrutador del cliente al VPS. Utilizo Wireguard como el más rápido y fácil de configurar desde También tengo enrutadores cliente basados en Linux ( APU2 o algo en OpenWRT). En el caso de algunos Mikrotik / Cisco, puede usar protocolos disponibles en ellos como OpenVPN y GRE-over-IPSEC.
Identificación y redireccionamiento del tráfico de interés.
Por supuesto, puede concluir completamente todo el tráfico de Internet a través del extranjero. Pero, muy probablemente, la velocidad de trabajar con contenido local se verá muy afectada por esto. Además, los requisitos de ancho de banda en el VPS serán mucho más altos.
Por lo tanto, necesitaremos de alguna manera asignar tráfico a sitios bloqueados y enviarlo selectivamente al túnel. Incluso si llega una parte del tráfico "extra", sigue siendo mucho mejor que conducir todo a través de un túnel.
Para administrar el tráfico, utilizaremos el protocolo BGP y anunciaremos rutas a las redes necesarias desde nuestro VPS a los clientes. Como demonio BGP, tomemos BIRD, como uno de los más funcionales y convenientes.
IP
Con el bloqueo de IP, todo está claro: solo anunciamos todas las IP bloqueadas con VPS. El problema es que hay alrededor de 600 mil subredes en la lista que ofrece la API, y la gran mayoría de ellas son hosts / 32. Tal cantidad de rutas puede ser confusa para los enrutadores de clientes débiles.
Por lo tanto, se decidió resumir a la red / 24 al procesar la lista si hay 2 o más hosts en ella. Por lo tanto, el número de rutas se redujo a ~ 100 mil. El guión para esto será el siguiente.
Dominios
Es más complicado y hay varias formas. Por ejemplo, puede colocar Squid transparente en cada enrutador de cliente y hacer intercepciones HTTP y espiar en el protocolo de enlace TLS para obtener la URL solicitada en el primer caso y el dominio de SNI en el segundo.
Pero debido a todos los nuevos TLS1.3 + eSNI, el análisis HTTPS se está volviendo cada vez menos real cada día. Y la infraestructura en el lado del cliente se está volviendo más complicada: tendrá que usar al menos OpenWRT.
Por lo tanto, decidí tomar el camino de interceptar respuestas a consultas DNS. Aquí, también, cualquier DNS sobre TLS / HTTPS comienza a elevarse por encima de nuestras cabezas, pero podemos (por ahora) controlar esta parte en el cliente, ya sea deshabilitarlo o usar nuestro propio servidor para DoT / DoH.
¿Cómo interceptar DNS?
También puede haber varios enfoques.
- Intercepción de tráfico DNS a través de PCAP o NFLOG
Ambos métodos de intercepción se implementan en la utilidad sidmat . Pero no se ha admitido durante mucho tiempo y la funcionalidad es muy primitiva, por lo que debe escribir un enlace de todos modos. - Análisis de registro del servidor DNS
Desafortunadamente, los recurrentes que conozco no saben cómo registrar respuestas, sino solo solicitudes. En principio, esto es lógico, porque a diferencia de las solicitudes, las respuestas tienen una estructura compleja y es difícil escribirlas en forma de texto. - DNSTap
Afortunadamente, muchos de ellos ya admiten DNSTap para estos fines.
¿Qué es DNSTap?

Este es un protocolo cliente-servidor basado en Protocol Buffers y Frame Streams para transferir desde un servidor DNS a un recopilador de consultas y respuestas DNS estructuradas. De hecho, el servidor DNS transmite metadatos de solicitudes y respuestas (tipo de mensaje, IP cliente / servidor, etc.) más mensajes DNS completos en la forma (binaria) en la que trabaja con ellos a través de la red.
Es importante comprender que en el paradigma DNSTap, el servidor DNS actúa como un cliente y el recopilador como un servidor. Es decir, el servidor DNS se conecta al recopilador, y no al revés.
Hoy DNSTap es compatible con todos los servidores DNS populares. Pero, por ejemplo, BIND en muchas distribuciones (como Ubuntu LTS) a menudo se construye por alguna razón sin su soporte. Por lo tanto, no nos molestaremos en reconstruir, sino que tomaremos un recursor más ligero y rápido: Sin consolidar.
¿Cómo atrapar DNSTap?
Existen varias utilidades de CLI para trabajar con una secuencia de eventos DNSTap, pero no funcionan bien para nuestra tarea. Así que decidí inventar mi propia bicicleta que haga lo que sea necesario: dnstap-bgp
Algoritmo de Operación:
- Cuando se inicia, carga una lista de dominios de un archivo de texto, los invierte (habr.com -> com.habr), excluye líneas discontinuas, duplicados y subdominios (es decir, si habr.com y www.habr.com están en la lista, se cargará solo el primero) y crea un árbol de prefijos para una búsqueda rápida en esta lista
- Actuando como un servidor DNSTap, espera una conexión desde el servidor DNS. En principio, es compatible con sockets UNIX y TCP, pero los servidores DNS que conozco solo pueden usar sockets UNIX
- Los paquetes DNSTap entrantes se deserializan primero en la estructura Protobuf, y luego el mensaje DNS binario en sí, ubicado en uno de los campos Protobuf, se analiza al nivel de los registros RR de DNS
- Comprueba si el host solicitado (o su dominio principal) está en la lista cargada; de lo contrario, la respuesta se ignora
- Solo se selecciona A / AAAA / CNAME RR de la respuesta y se extraen las direcciones IPv4 / IPv6 correspondientes.
- Las direcciones IP se almacenan en caché con TTL personalizados y se anuncian a todos los pares BGP configurados
- Al recibir una respuesta que indica una IP ya almacenada en caché, su TTL se actualiza
- Después de la expiración de TTL, el registro se elimina del caché y de los anuncios BGP
Funcionalidad adicional:
- Releyendo la lista de dominios por SIGHUP
- Sincronización de caché con otras instancias dnstap-bgp a través de HTTP / JSON
- Duplicación de la caché en el disco (en la base de datos BoltDB) para restaurar su contenido después de un reinicio
- Soporte para cambiar a un espacio de nombres de red diferente (por qué esto se describirá a continuación)
- Soporte IPv6
Limitaciones:
- Dominios IDN aún no admitidos
- Pocas configuraciones de BGP
He compilado paquetes RPM y DEB para una fácil instalación. Debería funcionar en todos los sistemas operativos relativamente recientes con systemd, como No tienen dependencias.
Esquema
Entonces, comencemos a ensamblar todos los componentes juntos. Como resultado, deberíamos obtener algo como esta topología de red:

La lógica del trabajo, creo, está clara en el diagrama:
- El cliente tiene nuestro servidor configurado como DNS, y las consultas DNS también deben pasar por la VPN. Esto es necesario para que el proveedor no pueda usar la intercepción de DNS para bloquear.
- Cuando se abre el sitio, el cliente envía una consulta DNS del formulario "¿qué IP tiene xxx.org?"
- Unbound resuelve xxx.org (o lo toma de la caché) y envía una respuesta al cliente "xxx.org tiene tal y tal IP", duplicándolo en paralelo a través de DNSTap
- dnstap-bgp anuncia estas direcciones en BIRD por BGP si el dominio está en la lista de bloqueados
- BIRD anuncia la ruta a estas IP con el enrutador
next-hop self
client del next-hop self
- Los paquetes posteriores del cliente a estas IP pasan por el túnel
En el servidor, para rutas a sitios bloqueados, tengo una tabla separada dentro de BIRD y no se cruza con el sistema operativo.
Hay un inconveniente en este esquema: el primer paquete SYN del cliente probablemente tendrá tiempo de salir a través del proveedor nacional desde La ruta no se anuncia al instante. Y aquí las opciones son posibles dependiendo de cómo el proveedor hace el bloqueo. Si solo deja caer el tráfico, entonces no hay problemas. Y si lo redirige a algunos DPI, entonces (teóricamente) son posibles los efectos especiales.
Los milagros también son posibles con clientes que no observan DNS TTL, lo que puede hacer que el cliente use algunas entradas desactualizadas de su caché podrido en lugar de preguntar Unbound.
En la práctica, ni el primero ni el segundo me causaron problemas, pero su kilometraje puede variar.
Configuración del servidor
Para facilitar el rodaje, escribí un papel para Ansible . Puede configurar tanto servidores como clientes basados en Linux (diseñados para distribuciones basadas en deb). Todas las configuraciones son bastante obvias y están configuradas en Inventory.yml . Este rol se ha eliminado de mi gran libro de jugadas, por lo que puede contener errores.
Veamos los componentes principales.
BGP
Al iniciar dos demonios BGP en el mismo host, surge un problema fundamental: BIRD no quiere aumentar el emparejamiento BGP con un host local (o con cualquier interfaz local). De la palabra en absoluto. Buscar en Google y leer listas de correo no ayudó, afirman que es por diseño. Quizás haya alguna forma, pero no la encontré.
Puedes probar otro demonio BGP, pero me gusta BIRD y se usa conmigo en todas partes, no quiero producir entidades.
Por lo tanto, escondí dnstap-bgp dentro del espacio de nombres de la red, que está conectado a la raíz a través de la interfaz veth: es como una tubería cuyos extremos sobresalen en un espacio de nombres diferente. En cada uno de estos extremos colgamos las direcciones IP privadas p2p que no salen del host, por lo que pueden ser cualquiera. Este es el mismo mecanismo que se utiliza para acceder a los procesos dentro del amado Docker y otros contenedores.
Para esto, se escribió un script y en dnstap-bgp se agregó la funcionalidad descrita anteriormente para arrastrarse por el cabello a otro espacio de nombres. Debido a esto, debe ejecutarse como root o devolverse al binario CAP_SYS_ADMIN a través del comando setcap.
Script de ejemplo para crear espacio de nombres dnstap-bgp.conf namespace = "dtap" domains = "/var/cache/rkn_domains.txt" ttl = "168h" [dnstap] listen = "/tmp/dnstap.sock" perm = "0666" [bgp] as = 65000 routerid = "192.168.149.2" peers = [ "192.168.149.1", ]
bird.conf router id 192.168.1.1; table rkn; # Clients protocol bgp bgp_client1 { table rkn; local as 65000; neighbor 192.168.1.2 as 65000; direct; bfd on; next hop self; graceful restart; graceful restart time 60; export all; import none; } # DNSTap-BGP protocol bgp bgp_dnstap { table rkn; local as 65000; neighbor 192.168.149.2 as 65000; direct; passive on; rr client; import all; export none; } # Static routes list protocol static static_rkn { table rkn; include "rkn_routes.list"; import all; export none; }
rkn_routes.list route 3.226.79.85/32 via "ens3"; route 18.236.189.0/24 via "ens3"; route 3.224.21.0/24 via "ens3"; ...
DNS
De forma predeterminada, en Ubuntu, el binario Unbound está sujeto por el perfil de AppArmor, lo que evita que se conecte a los sockets DNSTap allí. Puede eliminar este perfil o deshabilitarlo:
# cd /etc/apparmor.d/disable && ln -s ../usr.sbin.unbound . # apparmor_parser -R /etc/apparmor.d/usr.sbin.unbound
Esto probablemente debería agregarse al libro de jugadas. Es ideal, por supuesto, corregir el perfil y emitir los derechos necesarios, pero era demasiado vago.
unbound.conf server: chroot: "" port: 53 interface: 0.0.0.0 root-hints: "/var/lib/unbound/named.root" auto-trust-anchor-file: "/var/lib/unbound/root.key" access-control: 192.168.0.0/16 allow remote-control: control-enable: yes control-use-cert: no dnstap: dnstap-enable: yes dnstap-socket-path: "/tmp/dnstap.sock" dnstap-send-identity: no dnstap-send-version: no dnstap-log-client-response-messages: yes
Descarga y procesamiento de listas
Script para descargar y procesar una lista de direcciones IP
Descarga la lista, resume antes del prefijo pfx . En dont_add y dont_summarize, puede indicarle a IP y redes que omitan o no resuman. Lo necesitaba porque mi subred VPS estaba en la lista de bloqueo :)
Lo curioso es que la API RosKomSvoboda bloquea las solicitudes con el agente de usuario predeterminado de Python. Parece un guión que Kiddy lo entendió. Por lo tanto, lo cambiamos a Firelis.
Hasta ahora, solo funciona con IPv4 porque IPv6 es pequeño, pero será fácil de solucionar. A menos que sea necesario usar también bird6.
Script para actualizar
Comienza en mi corona una vez al día, tal vez vale la pena tirar de ella cada 4 horas, porque En mi opinión, este es el período de actualización que ILV requiere de los proveedores. Además, hay otras cerraduras urgentes adicionales que pueden volar más rápido.
Hace lo siguiente:
- Ejecuta el primer script y actualiza la lista de rutas (
rkn_routes.list
) para BIRD - Recargar PÁJARO
- Actualiza y limpia la lista de dominios para dnstap-bgp
- Reubicar dnstap-bgp
Fueron escritos sin pensarlo mucho, así que si ves lo que se puede mejorar, anímate.
Configuración del cliente
Aquí daré ejemplos de enrutadores Linux, pero en el caso de Mikrotik / Cisco esto debería ser aún más simple.
Primero, configure BIRD:
bird.conf router id 192.168.1.2; table rkn; protocol device { scan time 10; }; # Servers protocol bgp bgp_server1 { table rkn; local as 65000; neighbor 192.168.1.1 as 65000; direct; bfd on; next hop self; graceful restart; graceful restart time 60; rr client; export none; import all; } protocol kernel { table rkn; kernel table 222; scan time 10; export all; import none; }
Por lo tanto, sincronizaremos las rutas recibidas de BGP con la tabla de enrutamiento del núcleo número 222.
Después de eso, es suficiente pedirle al núcleo que mire esta placa antes de mirar el valor predeterminado:
# ip rule add from all pref 256 lookup 222 # ip rule 0: from all lookup local 256: from all lookup 222 32766: from all lookup main 32767: from all lookup default
Todo lo que queda es configurar DHCP en el enrutador para distribuir la dirección IP del túnel del servidor como DNS y el esquema está listo.
Desventajas
Con el algoritmo actual para crear y procesar una lista de dominios, youtube.com
y sus CDN entran en él.
Y esto lleva al hecho de que todos los videos pasarán por la VPN, que puede obstruir todo el canal. Quizás valga la pena compilar una lista de dominios de excepción populares que están bloqueados en el ILV por el momento. Y omítalos mientras analizas.
Conclusión
El método descrito le permite omitir casi todos los bloqueos que los proveedores implementan actualmente.
En principio, dnstap-bgp puede usarse para cualquier otro propósito donde se requiere un cierto nivel de control de tráfico basado en un nombre de dominio. Solo tenga en cuenta que hoy en día miles de sitios pueden colgar en la misma dirección IP (para algunos Cloudflare, por ejemplo), por lo que este método tiene una precisión bastante baja.
Pero para las necesidades de evitar las cerraduras, esto es suficiente.
¡Adiciones, ediciones, misiones de extracción son bienvenidas!