Bitácora del censo de nodos

Sobre este texto

Lo ha escrito Claude, un modelo de lenguaje, a partir de los commits, los diarios de trabajo y las mediciones de los repositorios del proyecto. El trabajo —montar el crawler, romper cada techo, medir el gasto, equivocarse— es de un humano, que ha verificado las cifras que aparecen aquí.

Un lector nos hizo ver que la versión anterior “sonaba a respuesta de un LLM”. Tenía razón. La reacción no ha sido disimularlo mejor, sino declararlo y cambiar el formato a uno donde la autoría automática no estorba: una bitácora. Aquí no hay tesis que defender ni prosa que admirar, solo entradas fechadas con lo que se observó, lo que se cambió y el número que salió.

El artículo con análisis, opinión y firma humana vendrá aparte.


Antes del registro (mayo – julio de 2026)

Punto de partida: un fork de ayeowch/bitnodes, el código detrás del bitnodes.io original, sin mantenimiento aguas arriba.

Techo 1: ~1.390 nodos. Máquina de 2 vCPU. Un demonio Tor clavado al 100% de CPU descartaba cerca de un millón de peticiones de circuito cada diez minutos. Los snapshots oscilaban entre 55 y 1.384. Detunear el crawler estabilizó la cifra en ~1.390. Aguantó semanas.

Techo 2: ~4.170 nodos. Resize a 8 vCPU. La cifra se triplicó y se quedó quieta dos meses. Nada en los datos sugería que fuese un artefacto.

2026-07-16 — La composición delata el artefacto

De los ~4.170 nodos, 12 eran onion. El hueco frente a los ~20.000 que reportaba otro tracker era casi todo .onion. El sampling al 25% y un único Tor saturado venían de mitigar un incidente de mayo y nunca se habían revisado tras el resize.

2026-07-17 — Pool de seis Tor, y el techo no se mueve

Sampling onion al 100% y seis demonios Tor. Onion: 12 → 226 en dos horas. Total: sigue en ~4.170. Cada onion ganado desplazaba un IPv4, uno a uno.

Ese 1:1 fue el dato que lo explicó todo: un snapshot solo puede contener tantos nodos como sockets simultáneamente abiertos, es decir procesos de ping × workers por proceso. 7 × 600 = 4.200, contra 4.170 observados.

Subida a 12 × 2.000 = 24.000 slots. Resultado en cinco horas: 11.600 nodos, con la población IPv4 (~6,4k) completa por primera vez.

2026-07-18 — I2P no necesita ancho de banda, necesita semillas

Tras 16 horas con soporte I2P activo: cero nodos I2P. La cola de pendientes tenía cero direcciones .b32.i2p. Los peers de clearnet casi nunca gossipean direcciones I2P, así que el anillo no arranca solo.

Sembradas 512 destinos de las semillas fijas de Bitcoin Core. La cola saltó a ~3.900 pendientes. Nodos alcanzables: seguían en cero.

2026-07-19 — El bug que hacía invisible a I2P

Instrumentados los intentos de conexión. El serializador de direcciones clasificaba .b32.i2p como IPv4 porque contiene puntos, y llamaba a inet_pton(AF_INET, …), que reventaba el handshake justo después de abrir el stream SAM.

Cada conexión I2P moría de una forma que, desde fuera, parecía “no hay nodos I2P”. Arreglado: addrv2 recibe sus 32 bytes y el campo version legacy una dirección nula, como hace Bitcoin Core. Resultado: ~4.700 nodos I2P alcanzables, una población que casi ningún tracker público cuenta.

2026-07-19 — Tor es de un solo hilo

Onion decaía durante días. ps mostraba seis Tor al 475% de CPU y parecía saturación. El sar de día completo mostró la máquina al 36% de idle.

No saturaba: cada demonio Tor es mono-hilo y topa en un núcleo por muchos que tenga la máquina. La palanca son más demonios, no una máquina mayor. Se pasó a nueve.

2026-07-19 — Instantáneo y ventana miden cosas distintas

Añadida la unión deslizante de nodos únicos por red, que es como cuenta el tracker de referencia. En ventana de 8 días: 27.063 nodos únicos frente a los 22.232 del otro. Las conexiones Tor son transitorias, así que un snapshot instantáneo infra-cuenta onion por construcción.

2026-07-21 — El disco se llena y se lleva a I2P por delante

Disco al 94%. Convergieron tres cosas sobre un volumen de 15 GB: logs de depuración inflados a 3,5 GB, 4,6 GB de ficheros temporales de Redis huérfanos de mayo, y snapshots más grandes al añadir I2P.

i2pd cayó, y con él el bridge SAM: I2P a cero. Tor se quedó sin poder cachear el consensus: onion a 18.

2026-07-22 — Congelación silenciosa de 21,5 horas

El dashboard sirvió un snapshot de hace 21,5 horas sin que nada “fallara”: todos los procesos vivos, todas las unidades de systemd en verde.

Causa: el restart() del crawler enviaba una transacción de ~123.000 comandos Redis en un único send() de varios megabytes. Bajo carga se atascó hasta que TCP se rindió, a los ~16 minutos, y la excepción sin capturar mató el greenlet del planificador justo después de dejar el estado en “arrancando”. Los 1.200 workers se pausaron educadamente para siempre.

Diagnóstico: py-spy no ve greenlets, así que hubo que inyectar código en el proceso vivo con gdb para volcar las 1.200 pilas.

Lección anotada: monitorizar la edad del último export, no la salud de los procesos.

2026-07-23 — El anti-DoS de los guards estrangula crawlers

Tras un reinicio, onion no rampaba: 17 → 21 → 0 en un día, con los demonios Tor casi ociosos. Los logs: 247.230 circuitos caducados frente a 212 completados, con “Guard is failing more circuits than usual”.

Un crawler concentra toda la creación de circuitos en uno o dos entry guards por demonio, que es justo el patrón que la defensa anti-DoS por IP estrangula. Sin requisitos de anonimato, el arreglo es una línea de torrc: UseEntryGuards 0.

Con la misma carga: onion de 3 a 2.532 en dos horas, y meseta trece horas después en ~10.700-10.800 conexiones onion simultáneas. Récord previo: 3.394. Total en meseta: ~22.100 nodos.

2026-08-01 — La factura de egress es otro techo

La detección de anomalías de coste del proveedor cloud marcó la instancia: transferencia un 2.307% por encima de lo esperado, 330-350 GB/día constantes, 24/7. El perfil se leyó como “instancia comprometida usada como proxy o relay” y la máquina acabó en cuarentena. El dashboard cayó.

Falso positivo: el “malware” era el crawler. La rampa coincidía al día con el escalado de los stages anteriores.

Egress diario de julio con los stages marcados

Medición del reparto real, por deltas de bytes enviados por proceso en ventanas de 60 segundos, contrastados con la consola del router i2pd:

Composición del egress: 55% I2P, 45% Tor, 0,1% protocolo Bitcoin

Más del 99% de la factura es maquinaria de overlay: construcción de túneles I2P con un 67% de éxito, lookups de leasesets, mantenimiento de NetDb, y del lado de Tor unas 1.000 conexiones TLS nuevas por minuto, que son el precio directo de UseEntryGuards 0. Tránsito para terceros: cero. El tráfico del protocolo Bitcoin es un error de redondeo.

Cada stage dejó firma en la curva de coste: 0,30 $/día antes de escalar, 1,60 $/día con el presupuesto completo de sockets, 9-15 $/día con I2P y los nueve Tor, y 22 $/día desde el día exacto de UseEntryGuards 0.

Coste de egress frente a nodos alcanzables, escala logarítmica

A ~0,09 $/GB son ~660 $/mes solo de transferencia. Es un fenómeno de hyperscaler, no de “la nube”: esos mismos ~10,7 TB/mes van incluidos en un VPS europeo de 20 €, y son irrelevantes en hardware propio. Decisión tomada ese día: migrar fuera. Crawler parado mientras tanto.

2026-08-07 — Retractación: la métrica de nodos únicos estaba mal

El dashboard publicaba desde julio una estimación de “nodos únicos” que ponderaba cada dirección alcanzable 1/N, donde N era el número de tipos de red que ese nodo anunciaba. Retirada. El endpoint responde ahora 410 con el motivo.

Dos cosas estaban mal. La entrada: N salía de las claves que cachean la respuesta a GETADDR, es decir las direcciones que un peer conoce de otros, no las suyas. Medía la diversidad de su libreta de direcciones. Como Bitcoin Core guarda direcciones onion e I2P pueda o no marcarlas, un nodo solo-clearnet con libreta variada se ponderaba 1/3 o 1/4 y contaba como fracción de máquina. La estimación se desinflaba en silencio y los números parecían plausibles.

Y arreglar la entrada no la habría salvado: deduplicar entre redes exige vincular la IPv4 de un nodo con su .onion o su .b32.i2p, y ese vínculo no se publica nunca. Core se autoanuncia con una dirección de la red del peer con el que habla. La imposibilidad de vincular es el objetivo de diseño de Tor y de I2P.

No hay recuento deduplicado de nodos en el dashboard, y no debería haberlo en ningún otro. La cifra comparable es la de ventana deslizante, que cuenta direcciones distintas por red y no pretende contar máquinas.

2026-08-13 / 15 — Prueba A/B: MaxCircuitDirtiness

Un lector señaló que subir MaxCircuitDirtiness en Tor reduciría el churn de handshakes. El manual lo respalda: para servicios ocultos, la caducidad se mide desde el último uso, no el primero, así que los 10 minutos por defecto son un temporizador de inactividad. El crawler revisita cada onion cada 30 minutos, o sea que cada ciclo encontraba todos los circuitos caducados.

Antes de poder probarlo hubo que arreglar algo: el crawler elegía demonio Tor al azar en cada intento, así que una revisita caía en el demonio con el circuito caliente una vez de cada nueve. Ahora cada dirección onion va siempre al mismo demonio, elegido por hash estable.

Tirada de 38 horas con los ocho demonios arrancados en frío a la vez, cuatro tratados con MaxCircuitDirtiness 3600 y cuatro de control con el valor por defecto. Comparación sobre 25,4 horas de meseta y 11.832 muestras:

egressconexiones sostenidasbytes por conexión
tratado28,65 MB/min~2.43512.338
control35,52 MB/min~5.7646.462
diferencia-19,4%-57,8%+90,9%

Conclusión: no subas MaxCircuitDirtiness en un crawler. El valor por defecto de 10 minutos gana.

El -19,4% de egress no es un ahorro: el brazo tratado gastó menos porque hizo menos trabajo, no porque fuera más eficiente. Transportó un 58% menos de conexiones. Medido por unidad de trabajo, que es lo único que importa cuando se compara coste, salió al doble de caro.

El porqué: retener circuitos una hora deja unos 6.400 circuitos abiertos por demonio frente a 3.900, y esa ocupación estrangula el caudal. Cada demonio tratado transportaba menos de la mitad de flujos que uno de control.

Lo que sí quedó demostrado es el mecanismo que motivó la prueba, y es grande: por los contadores del propio Tor, un demonio tratado abrió 1.747 conexiones salientes nuevas por hora frente a 4.686 del control, un 63% menos de churn de handshakes. La idea era correcta; lo que falla es el balance a este valor.

Por eso el descarte es de este ajuste, no de la idea. Para que un circuito sobreviva a la revisita, la caducidad tiene que superar los 30 minutos del ciclo: por debajo de eso no se reutiliza nada y se vuelve al comportamiento por defecto. El hueco por explorar es estrecho y concreto —35 o 40 minutos, justo por encima del ciclo pero lejos de la hora—, a ver si conserva parte de ese 63% sin estrangular el caudal. Sin probar todavía.

Lo que queda en pie

  • El número de nodos alcanzables de un tracker es una propiedad del tracker. Cada techo de esta bitácora parecía la red hasta que se rompió.
  • Comparar trackers es comparar infraestructuras. Las cifras de IPv4 convergen porque IPv4 es barato de enumerar; las de onion e I2P divergen porque dependen de capacidad de circuitos, estrangulamiento de guards y disponibilidad de semillas.
  • Ver los overlays tiene precio, y no se paga en bytes de Bitcoin.
  • Si la cuenta se estanca, antes de concluir “esto es la red”: composición, presupuesto de sockets, estrangulamiento aguas arriba.
  • Y una medida publicada solo vale lo que valga el método declarado a su lado. La entrada del 7 de agosto es la prueba.

Qué hay en el fork

  • I2P como cuarto anillo — cliente SAM v3 escrito desde cero, ramas I2P en crawl/ping/resolve, y siembra de destinos.
  • El arreglo del handshake I2P — la razón real de que I2P reportara cero.
  • Pool multi-Tortor_proxies multilínea, con afinidad por dirección desde agosto.
  • Fiabilidad del pipelinerestart() troceado en lugar de una transacción de varios megabytes, más un planificador supervisado.

Instancia en vivo: pesquisa.hacknodes.xyz (dashboard, API REST, servidor MCP). Código: alt-bitnodes y el fork del crawler, ambos MIT. Los snapshots en crudo y el archivo histórico están publicados.

Encantados de que alguien rebata las cifras.


alt-bitnodes es un proyecto open source independiente (MIT) mantenido por el autor. HackNodes Lab es su consultora de seguridad; el observatorio no es un producto comercial.