Redes Yggdrasil en Go
Resumen
Usa este skill para construir programas Go que se conecten y sirvan en la malla cifrada de extremo a extremo IPv6 de Yggdrasil: clientes, servidores HTTP/TCP/UDP, proxies SOCKS5, reenviadores de puertos y nodos que publiquen metadatos de descubrimiento. El nodo se ejecuta en espacio de usuario sobre una pila de red gVisor — sin dispositivo TUN, sin root, sin demonio yggdrasil externo y sin binario yggstack. Te conectas y escuchas sobre Yggdrasil con interfaces Go estándar (net.Conn, net.Listener, net.PacketConn, http.Transport).
La librería de embebido es github.com/voluminor/ratatoskr: crea el nodo con ratatoskr.New y maneja todo a través de su API Go. El alcance y la estabilidad de sus paquetes se resumen a continuación.
Diseño para una malla restringida
Yggdrasil es una malla superpuesta cifrada de extremo a extremo, no un tejido de centro de datos. Los enlaces tienen alta latencia, bajo ancho de banda, pérdidas y son intermitentes; un par alcanzable ahora puede desaparecer un segundo después, y el tráfico puede cruzar muchos saltos. Construye cada solución Yggdrasil como si fuera para una conexión débil e inestable. Esto no es un pulido opcional — es la forma predeterminada del código correcto aquí.
- Nunca sin límite. Un plazo límite en cada llamada y solicitud (
context.WithTimeout); reintentos acotados; colas acotadas. Sin esperas infinitas. - Limita la concurrencia. Restringe el trabajo en vuelo: SOCKS
MaxConnections, reenvíoSetMaxUDPSessions,http.Transport.MaxConnsPerHost/MaxIdleConnsPerHost, tus propios pools de workers. Ambos valores por defecto son ilimitados — establece límites reales. - Fragmenta transferencias grandes, verifica, reanuda. Nunca muevas un archivo grande de una sola vez. Divídelo en trozos pequeños (p. ej., HTTP
Range), verifica cada uno (tamaño/checksum) y hazlo reanudable para que un enlace caído cueste un trozo, no toda la transferencia. - Reintenta con retroceso + jitter, de forma idempotente. Espera desconexiones durante la operación. Haz las operaciones reanudables/idempotentes; retroceso exponencial con jitter; limita los intentos.
- Mantén las cargas pequeñas. Evita protocolos charlatanes y sondeos; comprime; usa codificaciones compactas. Mantén NodeInfo/sigilos muy por debajo del límite de 16 KB.
- Ajusta los buffers al enlace. Usa
node.MTU()para buffers de paquetes (la MTU en espacio de usuario es dinámica, con mínimo en 1280). - Degrada, no golpees. Ante fallos, retrocede y devuelve resultados parciales; nunca reintentes agresivamente a un par ni inundes la malla.
Un enfoque ingenuo de "servir un archivo grande sobre net/http" o "una solicitud/respuesta gigante" es la forma incorrecta. La forma correcta es acotada, fragmentada, reanudable y tolerante a fallos por defecto. Consulta el patrón de transferencia en malla restringida en references/integrations.md.
Fuente de la verdad
El módulo activo es la autoridad — no la memoria, ni texto README desactualizado, ni este skill. Antes de escribir orientación específica de una versión, inspecciona de qué depende realmente el proyecto:
go list -m github.com/voluminor/ratatoskr # versión seleccionada
go doc github.com/voluminor/ratatoskr # API raíz compilada
go doc github.com/voluminor/ratatoskr/mod/peermgr ConfigObj
Para leer el código fuente real de la versión seleccionada, resuélvelo desde la caché del módulo en lugar de adivinar una ruta:
go list -m -f '{{.Dir}}' github.com/voluminor/ratatoskr
No congeles la versión mínima de Go del texto README — puede ir por detrás de la directiva go.mod. Lee el go.mod activo de la versión Ratatoskr seleccionada.
Flujo de trabajo predeterminado
- Identifica la forma de la aplicación: nodo embebido, cliente/servidor HTTP, TCP/UDP puro, SOCKS5, reenvío de puertos, gestión de pares, o NodeInfo/sigilos.
- Usa el paquete raíz
github.com/voluminor/ratatoskrpara aplicaciones. Accede amod/coresolo a través del contratocore.Interface; evita*core.Obj/UnsafeCore()a menos que un paquete de bajo nivel lo requiera genuinamente. - Posee un
context.Context, pásalo comoratatoskr.ConfigObj.Ctx, y aún así hazdefer node.Close()después de un inicio exitoso. Ambos son necesarios. - Configura pares en exactamente un lugar:
- Pares Yggdrasil estáticos:
cfg.Config.Peers - Gestor de pares Ratatoskr:
ratatoskr.ConfigObj.Peers(entonces dejacfg.Config.Peersvacío, oNewdevuelveErrPeersConflict).
- Pares Yggdrasil estáticos:
- Usa
node.DialContextpara TCP/UDP saliente ynode.Listen/node.ListenPacketpara servicios dentro de Yggdrasil. - Encierra direcciones IPv6 entre corchetes en URLs y cadenas host-puerto:
http://[200:abcd::1]:8080, nuncahttp://200:abcd::1:8080. - Trata el enlace como débil: pon un plazo límite en cada llamada, limita la concurrencia y fragmenta/verifica/reanuda transferencias grandes (consulta Diseño para una malla restringida).
- Cuando generes código en un proyecto real, añade una verificación de compilación o una prueba enfocada en lugar de asumir que compila.
Alcance del módulo y estabilidad
Las direcciones Yggdrasil se derivan de la clave del nodo, por lo que la superficie de red es pequeña y estable. Prefiere las partes que la librería considera terminadas; marca explícitamente el resto en lugar de construir sobre ello.
| Paquete | Estado | Úsalo a través de |
|---|---|---|
raíz ratatoskr | Estable, API principal | New, EnableSOCKS, Ask/AskAddr, Snapshot, Close |
mod/core | Contrato estable | los métodos core.Interface embebidos en el nodo |
mod/peermgr | Estable | ratatoskr.ConfigObj.Peers |
mod/socks | Estable | node.EnableSOCKS (no instancies directamente) |
mod/resolver | Estable | creado automáticamente por EnableSOCKS; el uso directo es avanzado |
mod/forward | Estable | forward.New → Add* → Start |
mod/sigils (+ info, services, public, inet) | Estable | ratatoskr.ConfigObj.Sigils |
mod/ninfo | Estable | node.Ask / node.AskAddr |
mod/probe | Avanzado / inestable — requiere UnsafeCore(), la API puede cambiar | solo cuando se requiera explícitamente trazado de topología/ruta |
mod/settings | Trabajo en curso — esquema no finalizado | evita; usa yggdrasil-go/src/config directamente |
cmd/* | Aplicaciones de ejemplo, no API de librería importable | léelas como patrones, nunca las importes |
Raíz vs submódulos: por defecto usa ratatoskr.New (core + SOCKS + gestor de pares + ninfo + sigilos detrás de un solo Close). Baja a mod/core mediante core.New solo para la superficie más pequeña (llamada/escucha raw), o compón submódulos alrededor de core.Interface para transportes personalizados y pruebas. Cada submódulo (peermgr/socks/forward/resolver/ninfo) recibe un core.Interface. Consulta references/overview.md.
Sigilos del sistema — publica aquí primero
NodeInfo es cómo un nodo se describe a sí mismo en la red. Cuatro sigilos integrados ("del sistema") son analizados automáticamente por cada nodo, por lo que los datos que pongas en ellos serán reconocidos por otros participantes. Recurre a estos antes de inventar un sigilo personalizado; pásalos a través de ratatoskr.ConfigObj.Sigils. Mantén cada uno pequeño — comparten un presupuesto de NodeInfo de 16 KB.
| Sigilo | Qué pertenece aquí | Por qué usarlo |
|---|---|---|
info | Identidad del nodo: nombre, tipo, ubicación, contactos, descripción | Permite que otros sepan quién/qué es tu nodo. |
services | Puertos que expones dentro de Yggdrasil, como nombre → puerto | Descubrimiento de servicios sin escaneo de puertos. |
public | Tus URIs de peering público agrupadas por red | Permite que otros se conecten directamente contigo. |
inet | Tus direcciones del mundo real (dominios/IPs) | Mapa tu nodo Yggdrasil a identidad en Internet claro. |
Pon datos estándar y detectables en estos para que toda la red pueda leerlos. Solo define un sigilo personalizado para datos que ninguno de los cuatro cubra — y recuerda que solo los pares que ejecuten tu código lo analizarán. Los constructores validan y devuelven errores; manéjalos antes de ratatoskr.New. Detalles, límites exactos, acceso tipado y creación de sigilos personalizados: references/nodeinfo-sigils.md y references/custom-sigils.md.
Mapa de referencias
Lee solo los archivos necesarios para la tarea actual:
- Conceptos básicos de nodo embebido, Ratatoskr vs yggstack, arquitectura, alcance: references/overview.md
ratatoskr.New,ConfigObj, ciclo de vida, seguridad en hilos, métodos raíz, errores, snapshot: references/root-api.md- TCP, UDP,
DialContext,Listen,ListenPacket, cliente/servidor HTTP, multidifusión/admin, puntos de prueba: references/networking.md - Pares estáticos, gestor de pares, SOCKS5, resolvedor, reenvío de puertos: references/peers-socks-forwarding.md
- NodeInfo,
Ask/AskAddr, sigilos integrados con límites exactos: references/nodeinfo-sigils.md - Acceso tipado y creación/conexión de tus propios sigilos (sin
map[string]anyraw): references/custom-sigils.md - Plantillas de cliente/servidor e integraciones con frameworks (net/http, fasthttp, gRPC, puente gnet): references/integrations.md
- Áreas avanzadas/en desarrollo (probe, settings) y patrones de CLI/aplicaciones de ejemplo: references/advanced-and-examples.md
- Recetas de aplicación listas para adaptar: references/recipes.md
Errores comunes
| Error | Corrección |
|---|---|
| Iniciar un demonio Yggdrasil externo para una aplicación embebida | Usa ratatoskr.New; ejecuta una pila de red gVisor en espacio de usuario. |
Recomendar yggstack para integración de librería | yggstack es un binario para usuario final. Usa Ratatoskr para control de API Go. |
Establecer tanto cfg.Config.Peers como ConfigObj.Peers | Elige pares estáticos o el gestor de pares; nunca ambos → ErrPeersConflict. |
Pasar Ctx pero omitir Close (o viceversa) | Haz ambos: la cancelación desencadena el apagado, Close libera recursos. |
| Construir URLs sin corchetes IPv6 | Usa fmt.Sprintf("http://[%s]:%d", ip, port). |
Crear ninfo.New para consultas básicas | Usa node.Ask / node.AskAddr; el objeto raíz ya construye ninfo. |
| Ensamblar o registrar sigilos dinámicamente en tiempo de ejecución | Los sigilos se ensamblan estrictamente en código; las claves duplicadas o sobrescritas son errores graves por diseño, no fusiones silenciosas. Publica mediante ConfigObj.Sigils; lee tus propias claves de res.Node.Extra. |
Recurrir a UnsafeCore() / mod/probe / mod/settings por defecto | Mantente en la API raíz; estos son avanzados o trabajo en curso. |
| Hardcodear una versión de Go desde README | Lee el go.mod activo de la versión del módulo seleccionado. |
Validación
Mantén SKILL.md como capa de navegación y pon los detalles pesados de la API en references/. Prueba los cambios contra los escenarios en evals/evals.json antes de publicar.