Resumen

  • SOCKS5 creaba UDP ASSOCIATE dentro de una conexión TCP que ya había negociado un método y extinguía esa asociación cuando se cerraba el control; el flujo daba un límite de estado, no fiabilidad a los datagramas.
  • La dirección BND, la IP origen admitida, el destino declarado en cada envío, el método de protección y el reensamblado eran afirmaciones distintas. Ninguna certificaba por sí sola usuario, receptor ni efecto.

El tráfico reciente no renovaba una decisión antigua

Un cliente puede estar enviando voz, consultas o datos de juego a un puerto UDP del relé cuando el socket TCP de control se corta. Quizá cayó un NAT, cambió la red móvil o terminó el proceso que lo abrió. Un paquete más llega al punto conocido y contiene una dirección remota perfectamente válida. Reenviarlo parece práctico.

La regla de RFC 1928, de marzo de 1996, era más rigurosa: la asociación UDP termina cuando termina la conexión TCP por la que llegó la petición UDP ASSOCIATE. La actividad demuestra que alguien conoce el puerto; no demuestra que siga vigente el contexto que evaluó autenticación y política.

TCP no transportaba esos datagramas. Su función era sostener la negociación de método y el acto que había creado estado en el relé. UDP mantenía sus propiedades: mensajes independientes, posible pérdida, repetición y desorden. El final del flujo revocaba una relación local sin convertirlo en testigo de la entrega remota.

La solución dio a un servicio sin cierre propio una frontera ejecutable. En vez de dejar que una heurística de inactividad decidiera todo, el protocolo conservó una señal explícita y obligó a crear un contexto nuevo después de perderla.

Una petición podía omitir el origen, no la política

Antes de cualquier UDP, cliente y servidor intercambiaban los métodos disponibles sobre TCP y completaban el elegido. Solo entonces aparecían CONNECT, BIND o UDP ASSOCIATE.

La petición UDP podía incluir la dirección y el puerto que el cliente esperaba utilizar como origen. El servidor podía limitar la asociación con esos datos. Si el cliente aún no los conocía, enviaba ceros en ambos campos. Esa ausencia no concedía acceso universal: trasladaba al servidor la responsabilidad de obtener y aplicar una fuente efectiva.

La respuesta entregaba BND.ADDR y BND.PORT, es decir, el punto UDP donde el cliente debía depositar las solicitudes para el relé. En un servidor con varias interfaces, podía ser diferente de la dirección de la conexión TCP.

El objetivo final tampoco era BND.ADDR. Se encontraba dentro de cada envoltura UDP. Por ello, una captura correcta conserva tres coordenadas: servidor TCP, ingreso UDP del relé y destino remoto. Confundirlas hace que un cambio de interfaz parezca un cambio de destino o que un fallo de alcance al relé parezca rechazo del servicio remoto.

La asociación admitía más de un destino

Cada datagrama de cliente llevaba un encabezado SOCKS con reserva, FRAG, tipo de dirección, dirección, puerto y datos. La relación no era una tubería fijada a un host. Era la autorización para presentar decisiones de reenvío una por una.

Cuando un sistema remoto contestaba, el relé envolvía la respuesta con la misma gramática. De ese modo el cliente recibía el origen que el relé había observado. La dirección servía para correlación; no constituía una prueba criptográfica del actor ni de la intención.

El relé podía registrar aceptación, política aplicada y emisión. Solo el siguiente sistema podía confirmar recepción, y solo la aplicación conocía el resultado útil. Incluso una respuesta mostraba una nueva observación, no la certeza de que un acto anterior se hubiese ejecutado exactamente una vez.

La misma modestia gobernaba la vida del punto ligado. Después de cerrar TCP, conocer todavía BND.ADDR y formar bien el encabezado no devolvía el permiso. El dato de encaminamiento sobrevivía en memoria; la asociación no.

La IP de origen era una defensa de borde

RFC 1928 exigía que el relé obtuviera del servidor SOCKS la IP esperada del cliente y descartara en silencio los datagramas procedentes de otra IP. Así, un tercero con otro origen no podía aprovechar fácilmente una asociación ajena.

La comprobación no identificaba a una persona. Una dirección puede representar muchos procesos o equipos detrás de NAT y puede cambiar con la movilidad. El filtro comparaba un atributo de llegada; no demostraba que el mismo programa controlara TCP y UDP, ni que el destino autorizara la operación.

La autenticación residía en el método seleccionado. RFC 1929 describió usuario y contraseña, pero transmitía ambos en claro dentro de su subnegociación y desaconsejaba el método donde hubiera escucha. RFC 1961 añadió una opción GSS-API capaz de negociar integridad por mensaje y confidencialidad opcional además de autenticar.

La consecuencia operativa es incómoda: dos sistemas con la misma etiqueta SOCKS5 pueden ofrecer evidencia de seguridad distinta. Hay que conservar método, resultado y nivel de protección reales. El éxito de la versión o de la petición UDP no rellena automáticamente ese registro.

Los fragmentos tenían una memoria corta y opcional

FRAG=0 indicaba un datagrama independiente dentro de SOCKS. Los valores 1 a 127 ordenaban fragmentos, y el bit alto señalaba el final. No era fragmentación IP: era estado definido por la envoltura del relé.

El soporte era opcional. Quien no lo implementara debía descartar todo FRAG distinto de cero. Quien sí lo hiciera mantenía una cola y un temporizador de al menos cinco segundos. La expiración eliminaba la secuencia incompleta; también la reiniciaba un nuevo fragmento con número menor que el mayor procesado. RFC 1928 recomendaba evitar la fragmentación siempre que fuera posible.

No aparecía un protocolo fiable oculto. No había acuses ni garantía de reenvío. El reensamblado era una decisión local con caducidad. Una cola completa solo habilitaba el siguiente paso; no probaba que ese paso terminara bien.

Por eso los contadores deben distinguir origen inesperado, FRAG no soportado, retroceso de secuencia, expiración, fallo de política y envío posterior. Una sola categoría “UDP perdido” traslada incertidumbre a quien menos puede resolverla.

El control TCP impedía un relé huérfano

Mantener la asociación mientras hubiera tráfico reduciría interrupciones, pero convertiría el conocimiento del puerto en poder de renovación. Esperar solo a un timeout tampoco revelaría si el cliente estaba vivo o simplemente callado.

La conexión TCP ofrecía un hecho intermedio: no era identidad humana ni salud de la aplicación, pero sí una conversación que el servidor podía observar, cerrar y vincular a un método y una petición. Al terminar, la norma eligió revocar. La incertidumbre se resolvía exigiendo otra negociación, no ampliando silenciosamente el alcance de paquetes posteriores.

Esta política sacrificaba continuidad durante fallos transitorios y complicaba cambios de red. A cambio, hacía visible quién debía reconstruir el estado y cuándo. La recuperación consistía en una nueva asociación, una acción que podía registrarse y probarse.

Una pasarela de direcciones siguió siendo una aplicación

El documento Informational RFC 3089 utilizó SOCKS en 2001 para una pasarela IPv6/IPv4. Terminaba comunicaciones de ambas familias en la capa de aplicación y podía delegar la resolución de nombres a un nodo de doble pila, ayudando a software incapaz de almacenar direcciones IPv6.

La utilidad no borró la arquitectura. Nombre, resolución, conexión de control y datos seguían siendo objetos diferentes. La pasarela heredaba los comandos SOCKS; no se convertía por ello en un router transparente ni en autoridad sobre la identidad de los extremos.

La historia de UDP ASSOCIATE muestra una forma sobria de coordinación. Una norma común define qué petición puede comprobar el código. El relé decide localmente si actúa. Las observaciones posteriores conservan sus propios dueños. La interoperabilidad no requiere fingir que todo el camino comparte un solo estado.

Fuentes