
El prop贸sito de este proyecto fue:
- Aprendizaje de DHCP a trav茅s de una red IPv4
- Python de aprendizaje (un poco m谩s que desde cero;))
- reemplazando el servidor DB2DHCP (mi fork), el original aqu铆 , que es cada vez m谩s dif铆cil de ensamblar bajo el nuevo sistema operativo. S铆, y no me gusta que el binario, que no es posible "cambiar en este momento"
- obtener un servidor DHCP que funcione con la capacidad de seleccionar la direcci贸n IP del suscriptor por mac del suscriptor o un grupo de conmutadores mac + puerto (Opci贸n 82)
- escribiendo otra bicicleta (隆Oh! este es mi pasatiempo favorito)
- obtener Lyuli sobre su estrabismo en Habrahabr (o mejor invitaci贸n);)
Resultado: funciona;) Probado en FreeBSD y Ubuntu OS. Te贸ricamente, se le puede pedir al c贸digo que funcione bajo cualquier sistema operativo, porque No hay enlaces espec铆ficos en el c贸digo.
Precauci贸n Mucho m谩s lejos.
Enlace al repositorio para que los fan谩ticos
"toquen vivos" .
El proceso de instalaci贸n, configuraci贸n y uso del resultado del "estudio del hardware" es mucho m谩s bajo, y luego una peque帽a teor铆a sobre el protocolo DHCP. Para mi Y para la historia;)
Un poco de teor铆a
驴Qu茅 es el DHCP?
Este es un protocolo de red que permite que un dispositivo encuentre su direcci贸n IP (bueno, otros par谩metros como una puerta de enlace, DNS, etc.) desde un servidor DHCP. Los paquetes se intercambian a trav茅s de UDP. El principio general de funcionamiento del dispositivo cuando se solicitan par谩metros de red es el siguiente:
- El dispositivo (cliente) env铆a una solicitud de difusi贸n UDP (DHCPDISCOVER) a trav茅s de la red con la solicitud "Bueno, alguien, dame una direcci贸n IP". Y generalmente (pero no siempre) la solicitud es del puerto 68 (fuente), y el destino es el puerto 67 (destino). Algunos dispositivos tambi茅n env铆an paquetes desde el puerto 67. Dentro del paquete DHCPDISCOVER, se incluye la direcci贸n MAC del dispositivo cliente.
- Todos los servidores DHCP ubicados en la red (y puede haber varios) forman el dispositivo que envi贸 a DHCPDISCOVER una oraci贸n DHCPOFFER con configuraciones de red, y tambi茅n la transmite a trav茅s de la red. La identificaci贸n a qui茅n est谩 destinado este paquete va a la direcci贸n MAC del cliente proporcionada anteriormente en la solicitud DHCPDISCOVER.
- El cliente recibe paquetes con ofertas de configuraciones de red, selecciona los m谩s atractivos (los criterios pueden ser diferentes, por ejemplo, en el momento de la entrega de paquetes, el n煤mero de rutas intermedias) y hace que el servidor DHCP "solicite oficialmente" DHCPREQUEST con configuraciones de red. En este caso, el paquete va a un servidor DHCP espec铆fico.
- El servidor que recibi贸 DHCPREQUEST env铆a un paquete DHCPACK en el que una vez m谩s enumera la configuraci贸n de red para este cliente

Adem谩s, hay paquetes DHCPINFORM que provienen del cliente y cuyo prop贸sito es informar al servidor DHCP que el "cliente est谩 vivo" y utiliza la configuraci贸n de red emitida. En la implementaci贸n de este servidor, estos paquetes se ignoran.
Formato de paquete
En general, la trama del paquete Ethernet se ve as铆:

En nuestro caso, solo consideraremos los datos directamente del contenido del paquete UDP, sin los encabezados del protocolo de capa OSI, es decir, la estructura DHCP:
DHCPDISCOVER
Entonces, el proceso para obtener la direcci贸n IP del dispositivo comienza con el hecho de que el cliente DHCP env铆a una solicitud de transmisi贸n desde el puerto 68 al 255.255.255.255:67. En este paquete, el cliente incluye su direcci贸n MAC, as铆 como lo que quiere recibir del servidor DHCP. La estructura del paquete se describe en la tabla a continuaci贸n.
Tabla de estructura de paquetes DHCPDISCOVERPosici贸n del paquete | Nombre del valor | Ejemplo | Sumisi贸n | Byte | Explicaci贸n |
1 | Solicitud de arranque | 1 | Maleficio | 1 | Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente |
2 | Tipo de hardware | 1 | Maleficio | 1 | Tipo de direcci贸n de hardware, en este protocolo 1 - MAC |
3 | Longitud de adrees de hardware | 6 6 | Maleficio | 1 | Longitud de la direcci贸n MAC del dispositivo |
4 4 | L煤pulo | 1 | Maleficio | 1 | Numero de rutas intermedias |
5 5 | ID de transacci贸n | 23: cf: de: 1d | Maleficio | 4 4 | Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud. |
7 7 | Segundo transcurrido | 0 0 | Maleficio | 4 4 | Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n. |
9 9 | Banderas de Bootp | 0 0 | Maleficio | 2 | Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo |
11 | Direcci贸n IP del cliente | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del cliente (si la hay) |
15 | La direcci贸n IP de su cliente | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP propuesta por el servidor (si existe) |
19 | Siguiente direcci贸n IP del servidor | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del servidor (si se conoce) |
23 | Direcci贸n IP del agente de retransmisi贸n | 172.16.114.41 | Cadena | 4 4 | Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador) |
27 | Direcci贸n MAC del cliente | 14: d6: 4d: a7: c9: 55 | Maleficio | 6 6 | Direcci贸n MAC del remitente del paquete (cliente) |
31 | Relleno de direcci贸n de hardware del cliente | | Maleficio | 10 | Lugar reservado Generalmente ceros |
41 | Nombre de host del servidor | | Cadena | 64 | El nombre del servidor DHCP. Generalmente no se transmite |
105 | Nombre del archivo de arranque | | Cadena | 128 | El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque |
235 | Galleta m谩gica | 63: 82: 53: 63 | Maleficio | 4 4 | El n煤mero "m谩gico", por el cual incl. puede determinar que este paquete pertenece al protocolo DHCP |
Opciones de DHCP. Puede ir en cualquier orden |
236 | Numero de opcion | 53 | Dic | 1 | Opci贸n 53 que especifica el tipo de paquete DHCP
1 - DHCPDISCOVER 3 - DHCPREQUEST 2 - DHCPOFFER 5 - DHCPACK 8 - DHCPINFORM |
| Longitud de la opci贸n | 1 | Dic | 1 |
| Valor de la opci贸n | 1 | Dic | 1 |
| Numero de opcion | 50 | Dic | 1 | 驴Qu茅 direcci贸n IP desea recibir el cliente? |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 172.16.134.61 | Cadena | 4 4 |
| Numero de opcion | 55 | | 1 | Los par谩metros de red solicitados por el cliente. La composici贸n puede ser diferente
01 - M谩scara de red 03 - Gateway 06 - DNS oc - nombre de host 0f - nombre de dominio de red 1c - direcci贸n de la solicitud de difusi贸n (Broadcast) 42 - Nombre del servidor TFTP 79 - Ruta est谩tica sin clase |
| Longitud de la opci贸n | 8 | | 1 |
| Valor de la opci贸n | 01: 03: 06: 0c: 0f: 1c: 42: 79 | | 8 |
| Numero de opcion | 82 | Dic | | Opci贸n 82, en la que se transmiten la direcci贸n MAC del dispositivo repetidor y algunos valores adicionales.
Muy a menudo, el puerto del conmutador en el que se ejecuta el cliente final de DHCP. Las opciones adicionales est谩n "integradas" en esta opci贸n. El primer byte es el n煤mero de la "subopci贸n", el segundo es su longitud y luego su valor.
En este caso, en la opci贸n 82, las subopciones est谩n anidadas: ID de circuito del agente = 00: 04: 00: 01: 00: 04, donde los dos 煤ltimos bytes son el puerto del cliente DHCP del que proviene la solicitud
ID remoto del agente = 00: 06: c8: be: 19: 93: 11: 48 - Direcci贸n MAC del dispositivo de retransmisi贸n DHCP |
| Longitud de la opci贸n | 18 a帽os | Dic | |
| Valor de la opci贸n | 01:06 00: 04: 00: 01: 00: 04 02:08 00: 06: c8: be: 19: 93: 11: 48 | Maleficio | |
| Fin del paquete | 255 | Dic | 1 | 255 simboliza el final del paquete |
DHCPOFFER
Tan pronto como el servidor recibe el paquete DHCPDISCOVER y si ve que puede ofrecerle al cliente algo del pedido, entonces forma una respuesta: DHCPOFFER. La respuesta se env铆a al puerto "de donde vino", Broadcast, porque en este momento, el cliente a煤n no tiene una direcci贸n IP, por lo tanto, puede recibir un paquete solo si se env铆a difusi贸n. El cliente reconoce que es un paquete para 茅l por MAC en su direcci贸n dentro del paquete, as铆 como el n煤mero de transacci贸n que genera al momento de la creaci贸n del primer paquete.
Tabla de estructura de paquetes DHCPOFFERPosici贸n del paquete | Nombre del valor (com煤n) | Ejemplo | Sumisi贸n | Byte | Explicaci贸n |
1 | Solicitud de arranque | 1 | Maleficio | 1 | Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente |
2 | Tipo de hardware | 1 | Maleficio | 1 | Tipo de direcci贸n de hardware, en este protocolo 1 - MAC |
3 | Longitud de adrees de hardware | 6 6 | Maleficio | 1 | Longitud de la direcci贸n MAC del dispositivo |
4 4 | L煤pulo | 1 | Maleficio | 1 | Numero de rutas intermedias |
5 5 | ID de transacci贸n | 23: cf: de: 1d | Maleficio | 4 4 | Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud. |
7 7 | Segundo transcurrido | 0 0 | Maleficio | 4 4 | Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n. |
9 9 | Banderas de Bootp | 0 0 | Maleficio | 2 | Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo. En este caso, 0 significa el tipo de solicitud Unicast |
11 | Direcci贸n IP del cliente | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del cliente (si la hay) |
15 | La direcci贸n IP de su cliente | 172.16.134.61 | Cadena | 4 4 | Direcci贸n IP propuesta por el servidor (si existe) |
19 | Siguiente direcci贸n IP del servidor | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del servidor (si se conoce) |
23 | Direcci贸n IP del agente de retransmisi贸n | 172.16.114.41 | Cadena | 4 4 | Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador) |
27 | Direcci贸n MAC del cliente | 14: d6: 4d: a7: c9: 55 | Maleficio | 6 6 | Direcci贸n MAC del remitente del paquete (cliente) |
31 | Relleno de direcci贸n de hardware del cliente | | Maleficio | 10 | Lugar reservado Generalmente ceros |
41 | Nombre de host del servidor | | Cadena | 64 | El nombre del servidor DHCP. Generalmente no se transmite |
105 | Nombre del archivo de arranque | | Cadena | 128 | El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque |
235 | Galleta m谩gica | 63: 82: 53: 63 | Maleficio | 4 4 | El n煤mero "m谩gico", por el cual incl. puede determinar que este paquete pertenece al protocolo DHCP |
Opciones de DHCP. Puede ir en cualquier orden |
236 | Numero de opcion | 53 | Dic | 1 | Opci贸n 53 que especifica el tipo de paquete DHCP 2 - DHCPOFFER |
| Longitud de la opci贸n | 1 | Dic | 1 |
| Valor de la opci贸n | 2 | Dic | 1 |
| Numero de opcion | 1 | Dic | 1 | Opci贸n que ofrece la m谩scara de red del cliente DHCP |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 255.255.224.0 | Cadena | 4 4 |
| Numero de opcion | 3 | Dic | 1 | Opci贸n que ofrece la puerta de enlace predeterminada del cliente DHCP |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 172.16.12.1 | Cadena | 4 4 |
| Numero de opcion | 6 6 | Dic | 1 | Opci贸n que ofrece DHCP al cliente DNS |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 8.8.8.8 | Cadena | 4 4 |
| Numero de opcion | 51 | Dic | 1 | La vida 煤til de los par谩metros de red emitidos en segundos, despu茅s de lo cual el cliente DHCP debe solicitarlos nuevamente |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 86400 | Dic | 4 4 |
| Numero de opcion | 82 | Dic | 1 | Opci贸n 82, repite lo que vino en DHCPDISCOVER |
| Longitud de la opci贸n | 18 a帽os | Dic | 1 |
| Valor de la opci贸n | 01: 08: 00: 06: 00 01: 01: 00: 00: 01 02: 06: 00: 03: 0f 26: 4d: ec | Dic | 18 a帽os |
| Fin del paquete | 255 | Dic | 1 | 255 simboliza el final del paquete |
DHCPREQUEST
Despu茅s de que el cliente recibe DHCPOFFER, forma un paquete con una solicitud de par谩metros de red, no a todos los servidores DHCP de la red, sino solo a uno espec铆fico, cuya propuesta DHCPOFFER le gust贸 m谩s. Los criterios para "me gusta" pueden ser diferentes y dependen de la implementaci贸n del cliente DHCP. El destinatario de la solicitud se indica utilizando la direcci贸n MAC del servidor DHCP. Adem谩s, el cliente puede enviar el paquete DHCPREQUEST sin formar DHCPDISCOVER anteriormente, si la direcci贸n IP del servidor se recibi贸 anteriormente.
Tabla de estructura de paquetes DHCPREQUESTPosici贸n del paquete | Nombre del valor (com煤n) | Ejemplo | Sumisi贸n | Byte | Explicaci贸n |
1 | Solicitud de arranque | 1 | Maleficio | 1 | Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente |
2 | Tipo de hardware | 1 | Maleficio | 1 | Tipo de direcci贸n de hardware, en este protocolo 1 - MAC |
3 | Longitud de adrees de hardware | 6 6 | Maleficio | 1 | Longitud de la direcci贸n MAC del dispositivo |
4 4 | L煤pulo | 1 | Maleficio | 1 | Numero de rutas intermedias |
5 5 | ID de transacci贸n | 23: cf: de: 1d | Maleficio | 4 4 | Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud. |
7 7 | Segundo transcurrido | 0 0 | Maleficio | 4 4 | Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n. |
9 9 | Banderas de Bootp | 8000 | Maleficio | 2 | Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo. En este caso, "Broadcast" |
11 | Direcci贸n IP del cliente | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del cliente (si la hay) |
15 | La direcci贸n IP de su cliente | 172.16.134.61 | Cadena | 4 4 | Direcci贸n IP propuesta por el servidor (si existe) |
19 | Siguiente direcci贸n IP del servidor | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del servidor (si se conoce) |
23 | Direcci贸n IP del agente de retransmisi贸n | 172.16.114.41 | Cadena | 4 4 | Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador) |
27 | Direcci贸n MAC del cliente | 14: d6: 4d: a7: c9: 55 | Maleficio | 6 6 | Direcci贸n MAC del remitente del paquete (cliente) |
31 | Relleno de direcci贸n de hardware del cliente | | Maleficio | 10 | Lugar reservado Generalmente ceros |
41 | Nombre de host del servidor | | Cadena | 64 | El nombre del servidor DHCP. Generalmente no se transmite |
105 | Nombre del archivo de arranque | | Cadena | 128 | El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque |
235 | Galleta m谩gica | 63: 82: 53: 63 | Maleficio | 4 4 | El n煤mero "m谩gico", por el cual incl. puede determinar que este paquete pertenece al protocolo DHCP |
Opciones de DHCP. Puede ir en cualquier orden |
236 | Numero de opcion | 53 | Dic | 3 | Opci贸n 53 que especifica el tipo de paquete DHCP 3 - DHCPREQUEST |
| Longitud de la opci贸n | 1 | Dic | 1 |
| Valor de la opci贸n | 3 | Dic | 1 |
| Numero de opcion | 61 | Dic | 1 | ID de cliente: 01 (para Ehernet) + direcci贸n MAC del cliente |
| Longitud de la opci贸n | 7 7 | Dic | 1 |
| Valor de la opci贸n | 01: 2c: ab: 25: ff: 72: a6 | Maleficio | 7 7 |
| Numero de opcion | 60 60 | Dic | | "Identificador de clase de proveedor". En mi caso, se informa la versi贸n del cliente DHCP. Quiz谩s otros dispositivos devuelvan algo m谩s. Windows, por ejemplo, informa MSFT 5.0 |
| Longitud de la opci贸n | 11 | Dic | |
| Valor de la opci贸n | udhcp 0.9.8 | Cadena | |
| Numero de opcion | 55 | | 1 | Los par谩metros de red solicitados por el cliente. La composici贸n puede ser diferente
01 - M谩scara de red 03 - Gateway 06 - DNS oc - nombre de host 0f - nombre de dominio de red 1c - direcci贸n de la solicitud de difusi贸n (Broadcast) 42 - Nombre del servidor TFTP 79 - Ruta est谩tica sin clase |
| Longitud de la opci贸n | 8 | | 1 |
| Valor de la opci贸n | 01: 03: 06: 0c: 0f: 1c: 42: 79 | | 8 |
| Numero de opcion | 82 | Dic | 1 | Opci贸n 82, repite lo que vino en DHCPDISCOVER |
| Longitud de la opci贸n | 18 a帽os | Dic | 1 |
| Valor de la opci贸n | 01: 08: 00: 06: 00 01: 01: 00: 00: 01 02: 06: 00: 03: 0f 26: 4d: ec | Dic | 18 a帽os |
| Fin del paquete | 255 | Dic | 1 | 255 simboliza el final del paquete |
DHCPACK
Como confirmaci贸n del hecho de que "s铆, es su direcci贸n IP, y no se la dar茅 a nadie m谩s" desde el servidor DHCP, hay un paquete en formato DHCPACK del servidor al cliente. Es lo mismo que el resto de los paquetes enviados transmitidos. Aunque, en el siguiente c贸digo del servidor DHCP implementado en Python, por si acaso, duplico cualquier solicitud de transmisi贸n enviando un paquete a una IP de cliente espec铆fica, si ya se conoce. Adem谩s, al servidor DHCP no le importa en absoluto si el paquete DHCPACK ha llegado al cliente. Si el cliente no recibe DHCPACK, luego de un tiempo simplemente repite DHCPREQUEST
Tabla de estructura de paquetes DHCPACKPosici贸n del paquete | Nombre del valor (com煤n) | Ejemplo | Sumisi贸n | Byte | Explicaci贸n |
1 | Solicitud de arranque | 2 | Maleficio | 1 | Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente |
2 | Tipo de hardware | 1 | Maleficio | 1 | Tipo de direcci贸n de hardware, en este protocolo 1 - MAC |
3 | Longitud de adrees de hardware | 6 6 | Maleficio | 1 | Longitud de la direcci贸n MAC del dispositivo |
4 4 | L煤pulo | 1 | Maleficio | 1 | Numero de rutas intermedias |
5 5 | ID de transacci贸n | 23: cf: de: 1d | Maleficio | 4 4 | Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud. |
7 7 | Segundo transcurrido | 0 0 | Maleficio | 4 4 | Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n. |
9 9 | Banderas de Bootp | 8000 | Maleficio | 2 | Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo. En este caso, "Broadcast" |
11 | Direcci贸n IP del cliente | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del cliente (si la hay) |
15 | La direcci贸n IP de su cliente | 172.16.134.61 | Cadena | 4 4 | Direcci贸n IP propuesta por el servidor (si existe) |
19 | Siguiente direcci贸n IP del servidor | 0.0.0.0 | Cadena | 4 4 | Direcci贸n IP del servidor (si se conoce) |
23 | Direcci贸n IP del agente de retransmisi贸n | 172.16.114.41 | Cadena | 4 4 | Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador) |
27 | Direcci贸n MAC del cliente | 14: d6: 4d: a7: c9: 55 | Maleficio | 6 6 | Direcci贸n MAC del remitente del paquete (cliente) |
31 | Relleno de direcci贸n de hardware del cliente | | Maleficio | 10 | Lugar reservado Generalmente ceros |
41 | Nombre de host del servidor | | Cadena | 64 | El nombre del servidor DHCP. Generalmente no se transmite |
105 | Nombre del archivo de arranque | | Cadena | 128 | El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque |
235 | Galleta m谩gica | 63: 82: 53: 63 | Maleficio | 4 4 | El n煤mero "m谩gico", por el cual incl. puede determinar que este paquete pertenece al protocolo DHCP |
Opciones de DHCP. Puede ir en cualquier orden |
236 | Numero de opcion | 53 | Dic | 3 | Opci贸n 53 que especifica el tipo de paquete DHCP 5 - DHCPACK |
| Longitud de la opci贸n | 1 | Dic | 1 |
| Valor de la opci贸n | 5 5 | Dic | 1 |
| Numero de opcion | 1 | Dic | 1 | Opci贸n que ofrece la m谩scara de red del cliente DHCP |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 255.255.224.0 | Cadena | 4 4 |
| Numero de opcion | 3 | Dic | 1 | Opci贸n que ofrece la puerta de enlace predeterminada del cliente DHCP |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 172.16.12.1 | Cadena | 4 4 |
| Numero de opcion | 6 6 | Dic | 1 | Opci贸n que ofrece DHCP al cliente DNS |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 8.8.8.8 | Cadena | 4 4 |
| Numero de opcion | 51 | Dic | 1 | La vida 煤til de los par谩metros de red emitidos en segundos, despu茅s de lo cual el cliente DHCP debe solicitarlos nuevamente |
| Longitud de la opci贸n | 4 4 | Dic | 1 |
| Valor de la opci贸n | 86400 | Dic | 4 4 |
| Numero de opcion | 82 | Dic | 1 | Opci贸n 82, repite lo que vino en DHCPDISCOVER |
| Longitud de la opci贸n | 18 a帽os | Dic | 1 |
| Valor de la opci贸n | 01: 08: 00: 06: 00 01: 01: 00: 00: 01 02: 06: 00: 03: 0f 26: 4d: ec | Dic | 18 a帽os |
| Fin del paquete | 255 | Dic | 1 | 255 simboliza el final del paquete |
Instalaci贸n
La instalaci贸n en realidad consiste en instalar los m贸dulos de Python necesarios para el trabajo. Se supone que MySQL ya est谩 instalado y configurado.
Freebsd
paquete instalar python3
python3 -m surepip
pip3 instalar mysql-connector
Ubuntu
sudo apt-get install python3
sudo apt-get install pip3
sudo pip3 install mysql-connector
Creamos la base de datos MySQL, rellenamos el volcado pydhcp.sql, configuramos el archivo de configuraci贸n.
Configuracion
Todas las configuraciones del servidor est谩n en el formato de archivo xml. Archivo de referencia:
<? xml version = "1.0"?>
<config>
<dhcpserver>
<host> 0.0.0.0 </host>
<broadcast> 255.255.255.255 </broadcast>
<DHCPServer> 192.168.0.71 </DHCPServer>
<LeaseTime> 8600 </LeaseTime>
<ThreadLimit> 1 </ThreadLimit>
<defaultMask> 255.255.255.0 </defaultMask>
<defaultRouter> 192.168.0.1 </defaultRouter>
<defaultDNS> 8.8.8.8 </defaultDNS>
</dhcpserver>
<mysql>
<host> localhost </host>
<username> prueba </username>
<password> prueba </password>
<basename> pydhcp </basename>
</mysql>
<opciones>
<option> option_82_hex: sw_port1: 20:22 </option>
<option> option_82_hex: sw_port2: 16:18 </option>
<option> option_82_hex: sw_mac: 26: 40 </option>
</options>
<consulta>
<offer_count> 3 </offer_count>
<offer_1> seleccione ip, m谩scara, enrutador, dns de los usuarios donde upper (mac) = upper ('{option_82_AgentRemoteId_hex}') y upper (port) = upper ('{option_82_AgentCircuitId_port_hex}') </offer_1>
<offer_2> seleccione ip, m谩scara, enrutador, dns de los usuarios donde upper (mac) = upper ('{sw_mac}') y upper (port) = upper ('{sw_port2}') </offer_2>
<offer_3> seleccione ip, m谩scara, enrutador, dns de los usuarios donde upper (mac) = upper ('{ClientMacAddress}') </offer_3>
<history_sql> insertar en el historial (id, dt, mac, ip, comment) valores (nulo, ahora (), '{ClientMacAddress}', '{RequestedIpAddress}', 'DHCPACK / INFORM') </history_sql>
</query>
</config>
Ahora con m谩s detalle en las etiquetas:
La secci贸n dhcpserver describe la configuraci贸n b谩sica para iniciar el servidor, a saber:
- host: qu茅 direcci贸n IP est谩 escuchando el servidor en el puerto 67
- broadcast: qu茅 ip es una difusi贸n para DHCPOFFER y DHCPACK
- DHCPServer: 驴cu谩l es la ip del servidor DHCP?
- Tiempo de arrendamiento de LeaseTime de la direcci贸n IP emitida
- ThreadLimit: cu谩ntos subprocesos se ejecutan simult谩neamente para procesar paquetes UDP entrantes en el puerto 67. Se supone que esto ayudar谩 en proyectos altamente cargados;)
- defaultMask, defaultRouter, defaultDNS: lo que se ofrece al suscriptor de forma predeterminada si se encuentra IP en la base de datos, pero no se especifican par谩metros adicionales para 茅l
Secci贸n Mysql:
host, nombre de usuario, contrase帽a, nombre base: todo habla por s铆 mismo. Estructura de base de datos de muestra publicada en
GitHubSecci贸n de consulta: Esta secci贸n describe las solicitudes de OFERTA / ACK:
- offer_count: el n煤mero de l铆neas con solicitudes que devuelven un resultado de la forma ip, m谩scara, enrutador, dns
- offer_n es la cadena de consulta. Si la devoluci贸n est谩 vac铆a, se ejecuta la siguiente solicitud de oferta
- history_sql: solicitud de escritura, por ejemplo, al "historial de autorizaciones" por suscriptor
Cualquier variable de la secci贸n de opciones u opciones del protocolo DHCP puede participar en las solicitudes.
Opciones de secci贸n. Aqu铆 ya es m谩s interesante. Aqu铆 podemos crear variables que podemos usar m谩s adelante en la secci贸n de consulta.
Por ejemplo:
option_82_hex:sw_port1:20:22
, esta l铆nea es el comando para tomar toda la l铆nea que vino en la solicitud DHCP de la opci贸n 82, en formato hexadecimal, en el rango de 20 a 22 bytes, inclusive, y ponerla en la nueva variable sw_port1 (el puerto del conmutador de donde vino la solicitud)
option_82_hex:sw_mac:26:40
, defina la variable sw_mac, tomando hex del rango 26:40
Puede ver todas las opciones posibles que se pueden usar en las consultas iniciando el servidor con el modificador -d. Veremos algo como este registro:
- el paquete DHCPINFORM lleg贸 en el puerto 67, desde 0025224ad764, b '\ x91 \ xa5 \ xe0 \ xa3 \ xa5 \ xa9- \ x8f \ x8a', ('172.30.114.25', 68)
{'ClientMacAddress': '0025224ad764',
'ClientMacAddressByte': b '\ x00% "J \ xd7d',
'HType': 'Ethernet',
'HostName': b '\ x91 \ xa5 \ xe0 \ xa3 \ xa5 \ xa9- \ x8f \ x8a',
'ReqListDNS': verdadero,
'ReqListDomainName': verdadero,
'ReqListPerfowmRouterDiscover': verdadero,
'ReqListRouter': verdadero,
'ReqListStaticRoute': verdadero,
'ReqListSubnetMask': verdadero,
'ReqListVendorSpecInfo': 43,
'RequestedIpAddress': '0.0.0.0',
'Proveedor': b'MSFT 5.0 ',
'chaddr': '0025224ad764',
'ciaddr': '172.30.128.13',
'flags': b '\ x00 \ x00',
'giaddr': '172.30.114.25',
'gpoz': 308,
'hlen': 6,
'l煤pulo': 1,
'htype': 'MAC',
'magic_cookie': b'c \ x82Sc ',
'op': 'DHCPINFORM',
'option12': 12,
'option53': 53,
'option55': 55,
'option60': 60,
'option61': 61,
'option82': 82,
'option_82_byte': b '\ x12 \ x01 \ x06 \ x00 \ x04 \ x00 \ x01 \ x00 \ x06 \ x02 \ x08 \ x00'
b '\ x06 \ x00 \ x1eX \ x9e \ xb2 \ xad',
'option_82_hex': '12010600040001000602080006001e589eb2ad',
'option_82_len': 18,
'option_82_str': "b '\\ x12 \\ x01 \\ x06 \\ x00 \\ x04 \\ x00 \\ x01 \\ x00 \\ x06 \\ x02 \\ x08 \\ x00 \\ x06 \\ x00 \ \ x1eX \\ x9e \\ xb2 \\ xad '",
'resultado': falso,
'segundos': 768,
'siaddr': '0.0.0.0',
'sw_mac': '001e589eb2ad',
'sw_port1': '06',
'xidbyte': b '<\ x89} \ x8c',
'xidhex': '3c897d8c',
'yiaddr': '0.0.0.0'}
En consecuencia, podemos ajustar cualquier variable en {} y se usar谩 en la consulta SQL.
Capturemos para el historial que el cliente recibi贸 la direcci贸n IP:


Inicio del servidor
./pydhcpdb.py -d -c config.xml
- d modo de salida a la consola DEBUG
- archivo de configuraci贸n c <nombre de archivo>
Debriefing
Y ahora m谩s sobre la implementaci贸n del servidor en Python. Esto es un dolor Python fue estudiado sobre la marcha. Muchos momentos se hacen al estilo de: "wow, de alguna manera hice lo que funciona". No est谩 optimizado en absoluto, y se dej贸 en esta forma principalmente debido a la peque帽a experiencia de desarrollo en python. Me detendr茅 en los momentos m谩s interesantes de la implementaci贸n del servidor en el "c贸digo".
Analizador de archivos de configuraci贸n XML
Se utiliza el m贸dulo est谩ndar de Python xml.dom. Parece ser simple, pero durante la implementaci贸n hubo una notable falta de documentaci贸n sensible y ejemplos en la red usando este m贸dulo.
tree = minidom.parse (gconfig ["config_file"])
mconfig = tree.getElementsByTagName ("mysql")
para elem en mconfig:
gconfig ["mysql_host"] = elem.getElementsByTagName ("host") [0] .firstChild.data
gconfig ["mysql_username"] = elem.getElementsByTagName ("nombre de usuario") [0] .firstChild.data
gconfig ["mysql_password"] = elem.getElementsByTagName ("contrase帽a") [0] .firstChild.data
gconfig ["mysql_basename"] = elem.getElementsByTagName ("basename") [0] .firstChild.data
dconfig = tree.getElementsByTagName ("dhcpserver")
para elem en dconfig:
gconfig ["broadcast"] = elem.getElementsByTagName ("broadcast") [0] .firstChild.data
gconfig ["dhcp_host"] = elem.getElementsByTagName ("host") [0] .firstChild.data
gconfig ["dhcp_LeaseTime"] = elem.getElementsByTagName ("LeaseTime") [0] .firstChild.data
gconfig ["dhcp_ThreadLimit"] = int (elem.getElementsByTagName ("ThreadLimit") [0] .firstChild.data)
gconfig ["dhcp_Server"] = elem.getElementsByTagName ("DHCPServer") [0] .firstChild.data
gconfig ["dhcp_defaultMask"] = elem.getElementsByTagName ("defaultMask") [0] .firstChild.data
gconfig ["dhcp_defaultRouter"] = elem.getElementsByTagName ("defaultRouter") [0] .firstChild.data
gconfig ["dhcp_defaultDNS"] = elem.getElementsByTagName ("defaultDNS") [0] .firstChild.data
qconfig = tree.getElementsByTagName ("consulta")
para elem en qconfig:
gconfig ["offer_count"] = elem.getElementsByTagName ("offer_count") [0] .firstChild.data
para num en rango (int (gconfig ["offer_count"])):
gconfig ["oferta _" + str (num + 1)] = elem.getElementsByTagName ("oferta _" + str (num + 1)) [0] .firstChild.data
gconfig ["history_sql"] = elem.getElementsByTagName ("history_sql") [0] .firstChild.data
opciones = tree.getElementsByTagName ("opciones")
para elem en opciones:
nodo = elem.getElementsByTagName ("opci贸n")
para opciones en nodo:
optionsMod.append (options.firstChild.data)
Multithreading
Curiosamente, el multihilo en Python se implementa de manera muy clara y simple.
def PacketWork (datos, addr):
...
# implementaci贸n del an谩lisis del paquete recibido y la respuesta
...
mientras cierto:
datos, addr = udp_socket.recvfrom (1024) # espera el paquete UDP
thread = threading.Thread (target = PacketWork, args = (data, addr,)). start () # tal como vino - ejecuta la funci贸n PacketWork definida anteriormente en segundo plano con par谩metros
while threading.active_count ()> gconfig ["dhcp_ThreadLimit"]:
time.sleep (1) # si el n煤mero de subprocesos ya en ejecuci贸n es mayor que en la configuraci贸n, espere hasta que se reduzcan
Recibir / enviar paquete DHCP
Para interceptar paquetes UDP que llegan a trav茅s de la tarjeta de red, debe "elevar" el socket:
udp_socket = socket.socket (socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
udp_socket.bind ((gconfig ["dhcp_host"], 67))
donde est谩n las banderas:
- AF_INET: significa que el formato de la direcci贸n ser谩 IP: puerto. Quiz谩s AF_UNIX, donde la direcci贸n viene dada por el nombre del archivo.
- SOCK_DGRAM: significa que no estamos aceptando un "paquete sin procesar", sino que ya pasamos a trav茅s de un firewall y con un paquete parcialmente cortado. Es decir obtenemos solo el paquete UDP sin el componente "f铆sico" del envoltorio de paquetes UDP. Si usa el indicador SOCK_RAW, tambi茅n necesitar谩 analizar este "contenedor".
Enviar un paquete puede ser como una transmisi贸n:
udp_socket.setsockopt (socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # cambia el socket al modo Broadcast
rz = udp_socket.sendto (packetack, (gconfig ["broadcast"], 68))
y a la direcci贸n "de d贸nde vino el paquete":
udp_socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # cambia el socket al modo "muchos oyentes"
rz = udp_socket.sendto (packetack, addr)
donde SOL_SOCKET significa "nivel de protocolo" para configurar opciones,
La opci贸n SO_BROADCAST es que el paquete de casco Broadcast
La opci贸n SO_REUSEADDR cambia el socket al modo de escucha m煤ltiple. En teor铆a, es innecesario en este caso, pero en uno de los servidores de FreeBSD que prob茅, el c贸digo no funcion贸 sin esta opci贸n.
An谩lisis de paquetes DHCP
Aqu铆 es donde realmente me gust贸 Python. Resulta de la "caja" que le permite tratar con bastante facilidad el c贸digo de bytes. Permitiendo que sea muy simple traducir a valores decimales, cadenas y hexadecimales, es decir lo que realmente necesitamos para entender la estructura del paquete. Entonces, por ejemplo, puede obtener un rango de bytes en HEX y solo bytes:
res ["xidhex"] = datos [4: 8] .hex ()
res ["xidbyte"] = datos [4: 8]
, empaquetar bytes en una estructura:
res ["flags"] = paquete ('BB', datos [10], datos [11])
Obtenga IP de la estructura:
res ["ciaddr"] = socket.inet_ntoa (paquete ('BBBB', datos [12], datos [13], datos [14], datos [15]));
Y viceversa:
res = res + socket.inet_pton (socket.AF_INET, gconfig ["dhcp_Server"])
Eso es todo;)