the ugly org - dns al toque

desu

Aqui, dns.

repos

hamlet

Y sobre todo esto: sé sincero contigo mismo, y de ello ha de seguirse, como la noche sigue al día, que no podrás entonces ser falso con ninguno.

que es dns

dig y nc

Voy a empezar enseñando una tecnica que he visto que varios tutoriales utilizan para capturar paquetes. Es una tecnica bastante común cuando quieres hacer troubleshooting de paquetes (udl o tcp). También podríamos utilizar Wireshark.

Por un lado haré una petición a mi localhost:1053 preguntando por la ip de google.com

dig +retry=0 -p 1053 @127.0.0.1 +noedns google.com

Por otro lado levanto un servidor con nc y re-dirijo el trafico a un archivo:

nc -u -l 1053 > query_packet.txt

Realizamos la petición y hacemos un hexdump:

 
flox [default] ➜  rust-dns git:(master) ✗ hexdump -C query_packet.txt
00000000  27 02 01 00 00 01 00 00  00 00 00 00 06 67 6f 6f  |'............goo|
00000010  67 6c 65 03 63 6f 6d 00  00 01 00 01              |gle.com.....|
0000001c

Estos bytes, son la petición DNS. Si agarramos el standard y vamos comparando byte a byte lo que significa veremos su significado. Simple.

todo

Vamos entonces a escribir un servidor, para los casos de uso básicos de DNS.

  • enviar queries de dns
  • recibir queries de servidores dns
  • enviar y recibir, repulsivamente, queries dns
1
desu

enviar queries de dns

He empezando con la tarea mas simple y fácil que existe. Hacer una petición por udp.

Pero antes, de explicar que he picado, como y porque, Hamlet.

Corazón mío, no flaquees; no dejes que entre nunca el alma de Nerón en este pecho firme;

Ahora si.

Lo bueno de interceptar paquetes es que te genera tests de integración gratis. Realizas un par de peticiones y guardas el paquete que envías, y también puedes guardar la respuesta.

Lo primero que he hecho es estructurar mi codigo en tres componentes. DNSQuery, DNSQuestion, DNSHeaders.

Como ya explique en el hilo del BitTorrent, este es el metido de empaquetado que recomiendo:


Técnicamente superior, objetivamente hablando, a cualquier otra practica de programación. Crear un buffer y llenarlo o bien, escribir en el stream de network directamente. De esta manera tenemos control sobre el orden, el tamaño, la memoria alocada, y big/little endian. El big/little endian hace referencia a que tipo de bailes de Bollywood bailaran nuestros bytes:

Hamlet y SRK nos acompañaran en este viaje. Estemos tranquilos que nuestro server de DNS sera blazingly fast.

Si completamos este primer paso, y construimos correctamente nuestros paquetes de DNSQuery, podemos usar servidores como "1.1.1.1" o "8.8.8.8" en el puerto 53. Y recibiremos una respuesta.

Siguiente paso. Parsear la respuesta.

empaquetar structs

diferenciaria entre dos casos de uso:

  • lo que vamos a mandar tiene un tamaño fijo
  • lo que vamos a mandar tiene un componente dinámico

si lo que vamos a mandar es siempre el mismo tamaño, podríamos usar bitfields. por ejemplo: https://crates.io/crates/bilge
si lo que vamos a mandar tiene un componente dinámico, aunque tenga un max_size, como vimos en el BitTorrent o este ejemplo, escribir la serializacion y deserializacion nos dará control absoluto y nadie se va a morir por picar 4 lineas de código.

en el mundo real nos vamos a encontrar en que la representación en memoria de nuestros paquetes, y la representación en cable van a diferir. que quiere decir esto? si no hablas indio te lo explico con un ejemplo:

tu puedes mandar por cable "0011", pero es responsabilidad del protocolo especificar esto en memoria que significa:

  • 0011 => 3
  • 0011 => El enum 3 de un Header?
  • 0011 => la letra "c" o "C"? y solo estamos mandando 4 bits para ahorrar bandwith?
  • etc

No recomiendo explicar protocolos de networking para ligar en la Infierno.

2

Usuarios habituales

  • desu