Las cookies SYN son una técnica utilizada para resistir los ataques de inundación SYN . El inventor principal de la técnica, Daniel J. Bernstein, define las cookies SYN como "elecciones particulares de números de secuencia TCP iniciales por parte de servidores TCP". En particular, el uso de cookies SYN permite que un servidor evite perder conexiones cuando la cola SYN se llena. En lugar de almacenar conexiones adicionales, se codifica una entrada de la cola SYN en el número de secuencia enviado en la respuesta SYN+ACK . Si el servidor recibe una respuesta ACK posterior del cliente con el número de secuencia incrementado, el servidor puede reconstruir la entrada de la cola SYN utilizando la información codificada en el número de secuencia TCP y continuar como de costumbre con la conexión.
Para iniciar una conexión TCP, el cliente envía un paquete TCP SYN al servidor. El servidor responde con un paquete TCP SYN+ACK, que incluye un número de secuencia utilizado por TCP para reensamblar el flujo de datos. Según la especificación TCP, el número de secuencia inicial enviado por un punto final puede ser cualquier valor elegido por ese punto final. Dado que este número de secuencia lo elige el remitente, lo devuelve el destinatario y no tiene una estructura interna predefinida, se puede sobrecargar para transportar datos adicionales. A continuación se describe una posible implementación, aunque no existe un estándar público, por lo que el orden, la longitud y la semántica de los campos pueden variar entre las implementaciones de cookies SYN.
Las cookies SYN son números de secuencia iniciales que se construyen cuidadosamente de acuerdo con las siguientes reglas:
El número de secuencia TCP inicial, es decir, la cookie SYN , se calcula de la siguiente manera:
(Nota: dado que m debe codificarse utilizando 3 bits, el servidor está restringido a enviar hasta 8 valores únicos para m cuando se utilizan cookies SYN).
Cuando un cliente envía un paquete TCP ACK al servidor en respuesta al paquete SYN+ACK del servidor, el cliente debe (según la especificación TCP) utilizar n+1 en el número de reconocimiento del paquete , donde n es el número de secuencia inicial enviado por el servidor. Luego, el servidor resta 1 del número de reconocimiento para revelar la cookie SYN enviada al cliente.
A continuación, el servidor realiza las siguientes operaciones.
A partir de este momento la conexión se desarrolla de forma normal.
El uso de cookies SYN no rompe ninguna especificación de protocolo y, por lo tanto, debería ser compatible con todas las implementaciones de TCP. Sin embargo, hay dos advertencias que entran en vigencia cuando se utilizan cookies SYN. En primer lugar, el servidor está limitado a solo 8 valores MSS únicos, ya que eso es todo lo que se puede codificar en 3 bits. En segundo lugar, las implementaciones anteriores rechazaron todas las opciones TCP (como ventanas grandes o marcas de tiempo), porque el servidor descartaba la entrada de la cola SYN donde de lo contrario se almacenaría esa información. [1] Sin embargo, la v2.6.26 del kernel de Linux agregó soporte parcial de opciones TCP al codificarlas en la opción de marca de tiempo . [2] Finalmente, las cookies SYN colocan una mayor carga en los recursos del servidor. Cifrar las respuestas es computacionalmente costoso. La cookie SYN no reduce el tráfico, lo que la hace ineficaz contra ataques de inundación SYN que apuntan al ancho de banda como vector de ataque.
Si bien estas restricciones necesariamente conducen a una experiencia subóptima, los clientes rara vez notan su efecto porque solo se aplican cuando se produce un ataque. En tal situación, la pérdida de las opciones TCP para salvar la conexión suele considerarse un compromiso razonable.
Surge un problema cuando se pierde el paquete ACK de finalización de conexión enviado por el cliente y el protocolo de la capa de aplicación requiere que el servidor hable primero ( SMTP y SSH son dos ejemplos). En este caso, el cliente supone que la conexión se estableció correctamente y espera a que el servidor envíe su banner de protocolo o reenvíe el paquete SYN+ACK; sin embargo, el servidor no está al tanto de la sesión y no reenviará el paquete SYN+ACK porque descartó la entrada de la cola de espera que le permitiría hacerlo. Finalmente, el cliente abortará la conexión debido a un tiempo de espera de la capa de aplicación, pero esto puede llevar un tiempo relativamente largo. [3]
El estándar TCP Cookie Transactions (TCPCT) fue diseñado para superar estas deficiencias de las cookies SYN y mejorarlas en un par de aspectos. A diferencia de las cookies SYN, TCPCT es una extensión TCP y requiere soporte de ambos puntos finales. En 2016, pasó a estado "histórico" mediante la RFC 7805.
Los cortafuegos simples que están configurados para permitir todas las conexiones salientes pero para restringir los puertos a los que puede llegar una conexión entrante (por ejemplo, permitir conexiones entrantes a un servidor web en el puerto 80 pero restringir todos los demás puertos), funcionan bloqueando únicamente las solicitudes SYN entrantes a puertos no deseados. Si las cookies SYN están en funcionamiento, se debe tener cuidado para garantizar que un atacante no pueda eludir dicho cortafuegos falsificando ACK en su lugar, probando números de secuencia aleatorios hasta que se acepte uno. Las cookies SYN se deben activar y desactivar en función de cada puerto , de modo que la activación de las cookies SYN en un puerto público no haga que se reconozcan en un puerto no público. La implementación original del núcleo Linux entendió mal esta parte de la descripción de Bernstein y utilizó una única variable global para activar las cookies SYN para todos los puertos; [4] esto fue señalado por un estudiante de investigación [5] y posteriormente corregido en CVE - 2001-0851. [6]
La técnica fue creada por Daniel J. Bernstein y Eric Schenk en septiembre de 1996. La primera implementación (para SunOS ) fue lanzada por Jeff Weisberg un mes después, y Eric Schenk lanzó su implementación para Linux en febrero de 1997. FreeBSD implementa syncookies desde FreeBSD 4.5 (enero de 2002). [7]
static unsigned long tcp_lastsynq_overflow
La solución (como señaló DJ Bernstein en una comunicación privada en respuesta a lo anterior) es hacer que la variable tcp_lastsynq_overflow sea local para cada puerto de escucha, en lugar de ser global.