Servidor DHCP + Mysql en Python



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:

  1. 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.
  2. 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.
  3. 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.
  4. 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 DHCPDISCOVER
Posici贸n del paqueteNombre del valorEjemploSumisi贸nByteExplicaci贸n
1Solicitud de arranque1Maleficio1Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente
2Tipo de hardware1Maleficio1Tipo de direcci贸n de hardware, en este protocolo 1 - MAC
3Longitud de adrees de hardware6 6Maleficio1Longitud de la direcci贸n MAC del dispositivo
4 4L煤pulo1Maleficio1Numero de rutas intermedias
5 5ID de transacci贸n23: cf: de: 1dMaleficio4 4Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud.
7 7Segundo transcurrido0 0Maleficio4 4Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n.
9 9Banderas de Bootp0 0Maleficio2Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo
11Direcci贸n IP del cliente0.0.0.0Cadena4 4Direcci贸n IP del cliente (si la hay)
15La direcci贸n IP de su cliente0.0.0.0Cadena4 4Direcci贸n IP propuesta por el servidor (si existe)
19Siguiente direcci贸n IP del servidor0.0.0.0Cadena4 4Direcci贸n IP del servidor (si se conoce)
23Direcci贸n IP del agente de retransmisi贸n172.16.114.41Cadena4 4Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador)
27Direcci贸n MAC del cliente14: d6: 4d: a7: c9: 55Maleficio6 6Direcci贸n MAC del remitente del paquete (cliente)
31Relleno de direcci贸n de hardware del clienteMaleficio10Lugar reservado Generalmente ceros
41Nombre de host del servidorCadena64El nombre del servidor DHCP. Generalmente no se transmite
105Nombre del archivo de arranqueCadena128El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque
235Galleta m谩gica63: 82: 53: 63Maleficio4 4El 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
236Numero de opcion53Dic1Opci贸n 53 que especifica el tipo de paquete DHCP

1 - DHCPDISCOVER
3 - DHCPREQUEST
2 - DHCPOFFER
5 - DHCPACK
8 - DHCPINFORM
Longitud de la opci贸n1Dic1
Valor de la opci贸n1Dic1
Numero de opcion50Dic1驴Qu茅 direcci贸n IP desea recibir el cliente?
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n172.16.134.61Cadena4 4
Numero de opcion551Los 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贸n81
Valor de la opci贸n01: 03: 06: 0c: 0f: 1c: 42: 798
Numero de opcion82DicOpci贸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贸n18 a帽osDic
Valor de la opci贸n01:06
00: 04: 00: 01: 00: 04
02:08
00: 06: c8: be: 19: 93: 11: 48
Maleficio
Fin del paquete255Dic1255 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 DHCPOFFER
Posici贸n del paqueteNombre del valor (com煤n)EjemploSumisi贸nByteExplicaci贸n
1Solicitud de arranque1Maleficio1Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente
2Tipo de hardware1Maleficio1Tipo de direcci贸n de hardware, en este protocolo 1 - MAC
3Longitud de adrees de hardware6 6Maleficio1Longitud de la direcci贸n MAC del dispositivo
4 4L煤pulo1Maleficio1Numero de rutas intermedias
5 5ID de transacci贸n23: cf: de: 1dMaleficio4 4Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud.
7 7Segundo transcurrido0 0Maleficio4 4Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n.
9 9Banderas de Bootp0 0Maleficio2Algunas 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
11Direcci贸n IP del cliente0.0.0.0Cadena4 4Direcci贸n IP del cliente (si la hay)
15La direcci贸n IP de su cliente172.16.134.61Cadena4 4Direcci贸n IP propuesta por el servidor (si existe)
19Siguiente direcci贸n IP del servidor0.0.0.0Cadena4 4Direcci贸n IP del servidor (si se conoce)
23Direcci贸n IP del agente de retransmisi贸n172.16.114.41Cadena4 4Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador)
27Direcci贸n MAC del cliente14: d6: 4d: a7: c9: 55Maleficio6 6Direcci贸n MAC del remitente del paquete (cliente)
31Relleno de direcci贸n de hardware del clienteMaleficio10Lugar reservado Generalmente ceros
41Nombre de host del servidorCadena64El nombre del servidor DHCP. Generalmente no se transmite
105Nombre del archivo de arranqueCadena128El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque
235Galleta m谩gica63: 82: 53: 63Maleficio4 4El 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
236Numero de opcion53Dic1Opci贸n 53 que especifica el tipo de paquete DHCP 2 - DHCPOFFER
Longitud de la opci贸n1Dic1
Valor de la opci贸n2Dic1
Numero de opcion1Dic1Opci贸n que ofrece la m谩scara de red del cliente DHCP
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n255.255.224.0Cadena4 4
Numero de opcion3Dic1Opci贸n que ofrece la puerta de enlace predeterminada del cliente DHCP
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n172.16.12.1Cadena4 4
Numero de opcion6 6Dic1Opci贸n que ofrece DHCP al cliente DNS
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n8.8.8.8Cadena4 4
Numero de opcion51Dic1La 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贸n4 4Dic1
Valor de la opci贸n86400Dic4 4
Numero de opcion82Dic1Opci贸n 82, repite lo que vino en DHCPDISCOVER
Longitud de la opci贸n18 a帽osDic1
Valor de la opci贸n01: 08: 00: 06: 00
01: 01: 00: 00: 01
02: 06: 00: 03: 0f
26: 4d: ec
Dic18 a帽os
Fin del paquete255Dic1255 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 DHCPREQUEST
Posici贸n del paqueteNombre del valor (com煤n)EjemploSumisi贸nByteExplicaci贸n
1Solicitud de arranque1Maleficio1Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente
2Tipo de hardware1Maleficio1Tipo de direcci贸n de hardware, en este protocolo 1 - MAC
3Longitud de adrees de hardware6 6Maleficio1Longitud de la direcci贸n MAC del dispositivo
4 4L煤pulo1Maleficio1Numero de rutas intermedias
5 5ID de transacci贸n23: cf: de: 1dMaleficio4 4Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud.
7 7Segundo transcurrido0 0Maleficio4 4Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n.
9 9Banderas de Bootp8000Maleficio2Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo. En este caso, "Broadcast"
11Direcci贸n IP del cliente0.0.0.0Cadena4 4Direcci贸n IP del cliente (si la hay)
15La direcci贸n IP de su cliente172.16.134.61Cadena4 4Direcci贸n IP propuesta por el servidor (si existe)
19Siguiente direcci贸n IP del servidor0.0.0.0Cadena4 4Direcci贸n IP del servidor (si se conoce)
23Direcci贸n IP del agente de retransmisi贸n172.16.114.41Cadena4 4Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador)
27Direcci贸n MAC del cliente14: d6: 4d: a7: c9: 55Maleficio6 6Direcci贸n MAC del remitente del paquete (cliente)
31Relleno de direcci贸n de hardware del clienteMaleficio10Lugar reservado Generalmente ceros
41Nombre de host del servidorCadena64El nombre del servidor DHCP. Generalmente no se transmite
105Nombre del archivo de arranqueCadena128El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque
235Galleta m谩gica63: 82: 53: 63Maleficio4 4El 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
236Numero de opcion53Dic3Opci贸n 53 que especifica el tipo de paquete DHCP 3 - DHCPREQUEST
Longitud de la opci贸n1Dic1
Valor de la opci贸n3Dic1
Numero de opcion61Dic1ID de cliente: 01 (para Ehernet) + direcci贸n MAC del cliente
Longitud de la opci贸n7 7Dic1
Valor de la opci贸n01: 2c: ab: 25: ff: 72: a6Maleficio7 7
Numero de opcion60 60Dic"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贸n11Dic
Valor de la opci贸nudhcp 0.9.8Cadena
Numero de opcion551Los 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贸n81
Valor de la opci贸n01: 03: 06: 0c: 0f: 1c: 42: 798
Numero de opcion82Dic1Opci贸n 82, repite lo que vino en DHCPDISCOVER
Longitud de la opci贸n18 a帽osDic1
Valor de la opci贸n01: 08: 00: 06: 00
01: 01: 00: 00: 01
02: 06: 00: 03: 0f
26: 4d: ec
Dic18 a帽os
Fin del paquete255Dic1255 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 DHCPACK
Posici贸n del paqueteNombre del valor (com煤n)EjemploSumisi贸nByteExplicaci贸n
1Solicitud de arranque2Maleficio1Tipo de mensaje 1 - solicitud del cliente al servidor, 2 - respuesta del servidor al cliente
2Tipo de hardware1Maleficio1Tipo de direcci贸n de hardware, en este protocolo 1 - MAC
3Longitud de adrees de hardware6 6Maleficio1Longitud de la direcci贸n MAC del dispositivo
4 4L煤pulo1Maleficio1Numero de rutas intermedias
5 5ID de transacci贸n23: cf: de: 1dMaleficio4 4Identificador 煤nico de la transacci贸n. Generado por el cliente al comienzo de la operaci贸n de solicitud.
7 7Segundo transcurrido0 0Maleficio4 4Tiempo en segundos desde el inicio del proceso de obtenci贸n de la direcci贸n.
9 9Banderas de Bootp8000Maleficio2Algunas banderas que se pueden configurar como una indicaci贸n de los par谩metros del protocolo. En este caso, "Broadcast"
11Direcci贸n IP del cliente0.0.0.0Cadena4 4Direcci贸n IP del cliente (si la hay)
15La direcci贸n IP de su cliente172.16.134.61Cadena4 4Direcci贸n IP propuesta por el servidor (si existe)
19Siguiente direcci贸n IP del servidor0.0.0.0Cadena4 4Direcci贸n IP del servidor (si se conoce)
23Direcci贸n IP del agente de retransmisi贸n172.16.114.41Cadena4 4Direcci贸n IP del agente de retransmisi贸n (por ejemplo, un conmutador)
27Direcci贸n MAC del cliente14: d6: 4d: a7: c9: 55Maleficio6 6Direcci贸n MAC del remitente del paquete (cliente)
31Relleno de direcci贸n de hardware del clienteMaleficio10Lugar reservado Generalmente ceros
41Nombre de host del servidorCadena64El nombre del servidor DHCP. Generalmente no se transmite
105Nombre del archivo de arranqueCadena128El nombre del archivo en el servidor utilizado por las estaciones sin disco durante el arranque
235Galleta m谩gica63: 82: 53: 63Maleficio4 4El 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
236Numero de opcion53Dic3Opci贸n 53 que especifica el tipo de paquete DHCP 5 - DHCPACK
Longitud de la opci贸n1Dic1
Valor de la opci贸n5 5Dic1
Numero de opcion1Dic1Opci贸n que ofrece la m谩scara de red del cliente DHCP
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n255.255.224.0Cadena4 4
Numero de opcion3Dic1Opci贸n que ofrece la puerta de enlace predeterminada del cliente DHCP
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n172.16.12.1Cadena4 4
Numero de opcion6 6Dic1Opci贸n que ofrece DHCP al cliente DNS
Longitud de la opci贸n4 4Dic1
Valor de la opci贸n8.8.8.8Cadena4 4
Numero de opcion51Dic1La 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贸n4 4Dic1
Valor de la opci贸n86400Dic4 4
Numero de opcion82Dic1Opci贸n 82, repite lo que vino en DHCPDISCOVER
Longitud de la opci贸n18 a帽osDic1
Valor de la opci贸n01: 08: 00: 06: 00
01: 01: 00: 00: 01
02: 06: 00: 03: 0f
26: 4d: ec
Dic18 a帽os
Fin del paquete255Dic1255 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 GitHub

Secci贸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;)

Source: https://habr.com/ru/post/445338/


All Articles