socket que puertos protocolos protocolo lista informatica ejemplos caracteristicas linux network-programming

linux - que - Protocolo de enlace TCP con socket SOCK_RAW



socket tcp (7)

Ok, me doy cuenta de que esta situación es algo inusual, pero necesito establecer una conexión TCP (el handshake de 3 vías) utilizando solo sockets crudos (en C, en Linux), es decir, necesito construir los encabezados IP y los encabezados TCP yo mismo . Estoy escribiendo un servidor (así que primero tengo que responder al paquete SYN entrante) y, por la razón que sea, parece que no puedo hacerlo bien. Sí, me doy cuenta de que SOCK_STREAM se encargará de esto por mí, pero por razones que no quiero mencionar, no es una opción.

Los tutoriales que he encontrado en línea sobre el uso de sockets sin procesar describen cómo crear un flooder SYN, pero esto es algo más fácil que establecer realmente una conexión TCP, ya que no tiene que construir una respuesta basada en el paquete original. Obtuve el funcionamiento de los ejemplos de Flooder SYN, y puedo leer el paquete SYN entrante sin problemas desde el socket sin formato, pero todavía tengo problemas para crear una respuesta SYN / ACK válida a un SYN entrante del cliente.

Entonces, ¿alguien sabe un buen tutorial sobre el uso de sockets sin formato que va más allá de crear un flooder SYN, o alguien tiene algún código que pueda hacer esto (usando SOCK_RAW, y no SOCK_STREAM)? Estaría muy agradecido.

MarkR tiene toda la razón: el problema es que el kernel está enviando paquetes de reinicio en respuesta al paquete inicial porque cree que el puerto está cerrado. El núcleo me está golpeando a la respuesta y la conexión muere. Ya estaba usando tcpdump para monitorear la conexión, debería haber sido más observador y haber notado que había DOS respuestas, una de las cuales era un reinicio que estaba estropeando las cosas, así como la respuesta que creó mi programa. D''OH!

La solución que parece funcionar mejor es usar una regla de iptables, como sugiere MarkR, para bloquear los paquetes de salida. Sin embargo, hay una manera más fácil de hacerlo que usar la opción de marca, como se sugiere. Solo coincido si está configurado el indicador de reinicio TCP. Durante el curso de una conexión normal, es poco probable que sea necesario, y realmente no importa a mi aplicación si bloqueo todos los paquetes de reinicio salientes del puerto que se está utilizando. Esto efectivamente bloquea la respuesta no deseada del kernel, pero no mis propios paquetes. Si el puerto en el que mi programa está escuchando es 9999, entonces la regla de iptables se ve así:

iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP


Dependiendo de lo que intente hacer, puede ser más fácil hacer que el software existente maneje el protocolo de enlace TCP por usted.

Una pila IP de fuente abierta es lwIP ( http://savannah.nongnu.org/projects/lwip/ ) que proporciona una pila completa de tcp / ip. Es muy posible ejecutarlo en modo de usuario usando SOCK_RAW o pcap.


Desea implementar parte de una pila TCP en el espacio de usuario ... esto está bien, algunas otras aplicaciones lo hacen.

Un problema con el que se encontrará es que el kernel enviará respuestas (generalmente negativas, inútiles) a los paquetes entrantes. Esto va a arruinar cualquier comunicación que intente iniciar.

Una forma de evitar esto es usar una dirección IP e interfaz que indique que el núcleo no tiene su propia pila de IP, lo que está bien, pero tendrá que ocuparse de cosas de la capa de enlace (específicamente, arp) usted mismo. Eso requeriría un socket más bajo que IPPROTO_IP, SOCK_RAW - necesitas un socket de paquete (creo).

También puede ser posible bloquear las respuestas del kernel usando una regla de iptables, pero sospecho que las reglas se aplicarán también a tus propios paquetes, a menos que puedas tratarlos de manera diferente (quizás aplicando una "marca" de netfilter). tus propios paquetes?)

Lee las páginas man

paquete de socket (7) ip (7) (7)

Lo cual explica sobre varias opciones y ioctls que se aplican a tipos de sockets.

Por supuesto, necesitará una herramienta como Wireshark para inspeccionar lo que está sucediendo. Necesitará varias máquinas para probar esto. Recomiendo usar vmware (o similar) para reducir la cantidad de hardware requerido.

Lo siento, no puedo recomendar un tutorial específico.

Buena suerte.


Existen estructuras para encabezados de IP y TCP declaradas en netinet / ip.h y netinet / tcp.h respectivamente. Es posible que desee ver los otros encabezados en este directorio para macros extra y cosas que pueden ser de utilidad.

Envía un paquete con el conjunto de banderas SYN y un número de secuencia aleatorio (x). Debería recibir un SYN + ACK del otro lado. Este paquete tendrá un número de reconocimiento (y) que indica el próximo número de secuencia que el otro lado espera recibir, así como otro número de secuencia (z). Usted devuelve un paquete ACK que tiene el número de secuencia x + 1 y el número de entrada z + 1 para completar la conexión.

También debe asegurarse de calcular las sumas de comprobación de TCP / IP adecuadas y completar el resto del encabezado de los paquetes que envía. Además, no se olvide de cosas como el orden de bytes del host y la red.

TCP se define en RFC 793, disponible aquí: http://www.faqs.org/rfcs/rfc793.html



No puedo ayudarte con ningún tutorial.

Pero puedo darle algunos consejos sobre las herramientas que podría usar para ayudar en la depuración.

En primer lugar, como ha sugerido bmdhacks , obtén una copia de wireshark (o tcpdump, pero wireshark es más fácil de usar). Capture un buen apretón de manos. Asegúrate de guardar esto.

Capture uno de sus apretones de manos que falla. Wireshark tiene un análisis de paquetes y una comprobación de errores bastante buenos, por lo que si hay un error directo probablemente se lo diga.

A continuación, obtenga una copia de tcpreplay . Esto también debería incluir una herramienta llamada "tcprewrite". tcprewrite le permitirá dividir los archivos de captura previamente guardados en dos: uno para cada lado del intercambio de información. A continuación, puede usar tcpreplay para reproducir un lado del enlace de modo que tenga un conjunto consistente de paquetes para jugar.

Luego usa wireshark (nuevamente) para verificar sus respuestas.


No tengo un tutorial, pero recientemente utilicé Wireshark con buenos resultados para depurar algunos de los sockets sin procesar de la programación que estaba haciendo. Si captura los paquetes que está enviando, wireshark hará un buen trabajo mostrándole si están malformados o no. También es útil para comparar con una conexión normal.


si está utilizando sockets sin formato, si envía usando una dirección mac de origen diferente a la real, linux ignorará el paquete de respuesta y no enviará una primera.