Servidor DHCP+Mysql en Python

Servidor DHCP+Mysql en Python

A finalidade deste proxecto foi:

  • Aprende sobre DHCP nunha rede IPv4
  • Aprendendo Python (un pouco máis que desde cero 😉)
  • substitución do servidor DB2DHCP (o meu garfo), orixinal aquí, que é cada vez máis difícil de montar para o novo sistema operativo. E non me gusta que sexa un binario que non hai forma de "cambiar agora mesmo"
  • obter un servidor DHCP que funcione coa capacidade de seleccionar o enderezo IP do abonado mediante a combinación de mac do abonado ou cambiar mac+porto (Opción 82)
  • escribir outra bicicleta (Oh! esta é a miña actividade favorita)
  • recibindo comentarios sobre o teu club en Habrahabr (ou mellor aínda, unha invitación) 😉

Resultado: funciona 😉 Probado en FreeBSD e Ubuntu OS. Teoricamente, pódese pedir que o código funcione en calquera sistema operativo, porque Parece que non hai ligazóns específicas no código.
Coidado! Hai moito máis por vir.

Ligazón ao repositorio para afeccionados "tocar vivo".

O proceso de instalación, configuración e uso do resultado de "estudar o hardware" é moito menor, e despois un pouco de teoría sobre o protocolo DHCP. Para min. E pola historia 😉

Un pouco de teoría

Que é DHCP

Este é un protocolo de rede que permite que un dispositivo descubra o seu enderezo IP (e outros parámetros como pasarela, DNS, etc.) desde un servidor DHCP. Os paquetes intercambian mediante o protocolo UDP. O principio xeral de funcionamento do dispositivo cando se solicitan parámetros de rede é o seguinte:

  1. O dispositivo (cliente) envía unha solicitude de difusión UDP (DHCPDISCOVER) por toda a rede coa solicitude "ben, alguén me dá un enderezo IP". Ademais, normalmente (pero non sempre) a solicitude prodúcese dende o porto 68 (fonte) e o destino é o porto 67 (destino). Algúns dispositivos tamén envían paquetes desde o porto 67. O enderezo MAC do dispositivo cliente inclúese dentro do paquete DHCPDISCOVER.
  2. Todos os servidores DHCP situados na rede (e pode haber varios deles) forman unha oferta DHCPOFFER con axustes de rede para o dispositivo que enviou DHCPDISCOVER e tamén o emiten pola rede. A identificación de quen está destinado este paquete baséase no enderezo MAC do cliente proporcionado anteriormente na solicitude DHCPDISCOVER.
  3. O cliente acepta paquetes con propostas de configuración de rede, selecciona o máis atractivo (os criterios poden ser diferentes, por exemplo, a hora de entrega do paquete, o número de rutas intermedias) e realiza unha "solicitude oficial" DHCPREQUEST coa configuración da rede. desde o servidor DHCP que lle gusta. Neste caso, o paquete vai a un servidor DHCP específico.
  4. O servidor que recibiu a DHCPREQUEST envía un paquete de formato DHCPACK, no que volve a enumerar a configuración de rede destinada a este cliente

Servidor DHCP+Mysql en Python

Ademais, hai paquetes DHCPINFORM que proveñen do cliente, e cuxo propósito é informar ao servidor DHCP de que o "cliente está vivo" e está a usar a configuración de rede emitida. Na implementación deste servidor, estes paquetes son ignorados.

Formato do paquete

En xeral, unha trama de paquete Ethernet ten un aspecto similar ao seguinte:

Servidor DHCP+Mysql en Python

No noso caso, consideraremos só os datos directamente do contido do paquete UDP, sen cabeceiras de protocolo de capa OSI, é dicir, a estrutura DHCP:

DHCPDESCUBRIR

Así, o proceso de obtención dun enderezo IP para un dispositivo comeza co cliente DHCP que envía unha solicitude de difusión desde o porto 68 ata 255.255.255.255:67. Neste paquete, o cliente inclúe o seu enderezo MAC, así como o que quere recibir exactamente do servidor DHCP. A estrutura do paquete descríbese na seguinte táboa.

Táboa de estrutura de paquetes DHCPDISCOVER

Posición no paquete
Nome do valor
Exemplo
Introdución
Byte
Esclarecemento

1
Solicitude de arranque
1
Feitizo
1
Tipo de mensaxe. 1 - solicitude de cliente a servidor, 2 - resposta de servidor a cliente

2
Tipo de hardware
1
Feitizo
1
Tipo de enderezo de hardware, neste protocolo 1 - MAC

3
Lonxitude de enderezos de hardware
6
Feitizo
1
Lonxitude do enderezo MAC do dispositivo

4
Lúpulo
1
Feitizo
1
Número de rutas intermedias

5
ID de transacción
23:cf:de:1d
Feitizo
4
Identificador único de transacción. Xerado polo cliente ao comezo dunha operación de solicitude

7
Segundo pasou
0
Feitizo
4
Tempo en segundos desde o inicio do proceso de obtención dun enderezo

9
Bandeiras de arranque
0
Feitizo
2
Algunhas bandeiras que se poden configurar para indicar parámetros de protocolo

11
Enderezo IP do cliente
0.0.0.0
Liña
4
Enderezo IP do cliente (se o hai)

15
O enderezo IP do teu cliente
0.0.0.0
Liña
4
Enderezo IP ofrecido polo servidor (se está dispoñible)

19
O seguinte enderezo IP do servidor
0.0.0.0
Liña
4
Enderezo IP do servidor (se se coñece)

23
Enderezo IP do axente de retransmisión
172.16.114.41
Liña
4
Enderezo IP do axente de retransmisión (por exemplo, un interruptor)

27
Enderezo MAC do cliente
14:d6:4d:a7:c9:55
Feitizo
6
Enderezo MAC do remitente do paquete (cliente)

31
Recheo de enderezos de hardware do cliente
 
Feitizo
10
Asento reservado. Normalmente está cheo de ceros

41
Nome do servidor do servidor
 
Liña
64
Nome do servidor DHCP. Normalmente non se transmite

105
Nome do ficheiro de arranque
 
Liña
128
Nome do ficheiro no servidor utilizado polas estacións sen disco ao iniciar

235
Galletas máxicas
63: 82: 53: 63
Feitizo
4
Número "máxico", segundo o cal, incl. pode determinar que este paquete pertence ao protocolo DHCP

Opcións de DHCP. Pode ir en calquera orde

236
Número de opción
53
decembro
1
Opción 53, que especifica o tipo de paquete DHCP

1 - DHCPDISCOVER
3 - SOLICITUDE DHCP
2 - OFERTA DHCP
5 - DHCPACK
8 - DHCPINFORM

 
Duración da opción
1
decembro
1

 
Valor da opción
1
decembro
1

 
Número de opción
50
decembro
1
Que enderezo IP quere recibir o cliente?

 
Duración da opción
4
decembro
1

 
Valor da opción
172.16.134.61
Liña
4

 
Número de opción
55
 
1
Parámetros de rede solicitados polo cliente. A composición pode variar

01 — Máscara de rede
03 - Pasarela
06 - DNS
oc — Nome do servidor
0f - nome de dominio da rede
1c - enderezo da solicitude de emisión (emisión)
42 - Nome do servidor TFTP
79 - Ruta estática sen clase

 
Duración da opción
8
 
1

 
Valor da opción
01:03:06:0c:0f:1c:42:79
 
8

 
Número de opción
82
decembro
 
Opción 82, que transmite o enderezo MAC do dispositivo repetidor e algúns valores adicionais.

Na maioría das veces, este é o porto do switch no que se executa o cliente DHCP final. Esta opción contén parámetros adicionais. O primeiro byte é o número da "subopción", o segundo é a súa lonxitude e despois o seu valor.

Neste caso, na opción 82, as subopcións están aniñadas:
ID do circuíto do axente = 00:04:00:01:00:04, onde os dous últimos bytes son o porto do cliente DHCP do que procedeu a solicitude

ID de axente remoto = 00:06:c8:be:19:93:11:48 - Enderezo MAC do dispositivo repetidor DHCP

 
Duración da opción
18
decembro
 

 
Valor da opción
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Feitizo
 

 
Fin do paquete
255
decembro
1
255 simboliza o final do paquete

OFERTA DHCP

En canto o servidor recibe o paquete DHCPDISCOVER e se ve que pode ofrecerlle ao cliente algo do solicitado, xera unha resposta para iso - DHCPDISCOVER. A resposta envíase ao porto “de onde veu”, por emisión, porque neste momento, o cliente aínda non ten un enderezo IP, polo que só pode aceptar o paquete se é enviado por emisión. O cliente recoñece que se trata dun paquete para el polo seu enderezo MAC dentro do paquete, así como polo número de transacción que xera no momento en que se crea o primeiro paquete.

Táboa de estrutura de paquetes DHCPOFFER

Posición no paquete
Nome do valor (común)
Exemplo
Introdución
Byte
Esclarecemento

1
Solicitude de arranque
1
Feitizo
1
Tipo de mensaxe. 1 - solicitude de cliente a servidor, 2 - resposta de servidor a cliente

2
Tipo de hardware
1
Feitizo
1
Tipo de enderezo de hardware, neste protocolo 1 - MAC

3
Lonxitude de enderezos de hardware
6
Feitizo
1
Lonxitude do enderezo MAC do dispositivo

4
Lúpulo
1
Feitizo
1
Número de rutas intermedias

5
ID de transacción
23:cf:de:1d
Feitizo
4
Identificador único de transacción. Xerado polo cliente ao comezo dunha operación de solicitude

7
Segundo pasou
0
Feitizo
4
Tempo en segundos desde o inicio do proceso de obtención dun enderezo

9
Bandeiras de arranque
0
Feitizo
2
Algunhas bandeiras que se poden configurar para indicar parámetros de protocolo. Neste caso, 0 significa o tipo de solicitude Unicast

11
Enderezo IP do cliente
0.0.0.0
Liña
4
Enderezo IP do cliente (se o hai)

15
O enderezo IP do teu cliente
172.16.134.61
Liña
4
Enderezo IP ofrecido polo servidor (se está dispoñible)

19
O seguinte enderezo IP do servidor
0.0.0.0
Liña
4
Enderezo IP do servidor (se se coñece)

23
Enderezo IP do axente de retransmisión
172.16.114.41
Liña
4
Enderezo IP do axente de retransmisión (por exemplo, un interruptor)

27
Enderezo MAC do cliente
14:d6:4d:a7:c9:55
Feitizo
6
Enderezo MAC do remitente do paquete (cliente)

31
Recheo de enderezos de hardware do cliente
 
Feitizo
10
Asento reservado. Normalmente está cheo de ceros

41
Nome do servidor do servidor
 
Liña
64
Nome do servidor DHCP. Normalmente non se transmite

105
Nome do ficheiro de arranque
 
Liña
128
Nome do ficheiro no servidor utilizado polas estacións sen disco ao iniciar

235
Galletas máxicas
63: 82: 53: 63
Feitizo
4
Número "máxico", segundo o cal, incl. pode determinar que este paquete pertence ao protocolo DHCP

Opcións de DHCP. Pode ir en calquera orde

236
Número de opción
53
decembro
1
Opción 53, que define o tipo de paquete DHCP 2 - DHCPOFFER

 
Duración da opción
1
decembro
1

 
Valor da opción
2
decembro
1

 
Número de opción
1
decembro
1
Opción para ofrecer ao cliente DHCP unha máscara de rede

 
Duración da opción
4
decembro
1

 
Valor da opción
255.255.224.0
Liña
4

 
Número de opción
3
decembro
1
Opción para ofrecer ao cliente DHCP unha pasarela predeterminada

 
Duración da opción
4
decembro
1

 
Valor da opción
172.16.12.1
Liña
4

 
Número de opción
6
decembro
1
Opción para ofrecer DHCP ao cliente DNS

 
Duración da opción
4
decembro
1

 
Valor da opción
8.8.8.8
Liña
4

 
Número de opción
51
decembro
1
A vida útil dos parámetros de rede emitidos en segundos, despois do cal o cliente DHCP debe solicitalos de novo

 
Duración da opción
4
decembro
1

 
Valor da opción
86400
decembro
4

 
Número de opción
82
decembro
1
Opción 82, repite o que veu en DHCPDISCOVER

 
Duración da opción
18
decembro
1

 
Valor da opción
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembro
18

 
Fin do paquete
255
decembro
1
255 simboliza o final do paquete

SOLICITUDE DHCP

Despois de que o cliente recibe DHCPOFFER, forma un paquete solicitando parámetros de rede non a todos os servidores DHCP da rede, senón só a un específico, cuxa oferta DHCPOFFER "lle gustou" máis. Os criterios de "gústame" poden ser diferentes e depender da implementación de DHCP do cliente. O destinatario da solicitude especifícase mediante o enderezo MAC do servidor DHCP. Ademais, o cliente pode enviar un paquete DHCPREQUEST sen xerar previamente DHCPDISCOVER, se o enderezo IP do servidor xa se obtivo previamente.

Táboa de estrutura de paquetes DHCPREQUEST

Posición no paquete
Nome do valor (común)
Exemplo
Introdución
Byte
Esclarecemento

1
Solicitude de arranque
1
Feitizo
1
Tipo de mensaxe. 1 - solicitude de cliente a servidor, 2 - resposta de servidor a cliente

2
Tipo de hardware
1
Feitizo
1
Tipo de enderezo de hardware, neste protocolo 1 - MAC

3
Lonxitude de enderezos de hardware
6
Feitizo
1
Lonxitude do enderezo MAC do dispositivo

4
Lúpulo
1
Feitizo
1
Número de rutas intermedias

5
ID de transacción
23:cf:de:1d
Feitizo
4
Identificador único de transacción. Xerado polo cliente ao comezo dunha operación de solicitude

7
Segundo pasou
0
Feitizo
4
Tempo en segundos desde o inicio do proceso de obtención dun enderezo

9
Bandeiras de arranque
8000
Feitizo
2
Algunhas bandeiras que se poden configurar para indicar parámetros de protocolo. Neste caso, establécese "difusión".

11
Enderezo IP do cliente
0.0.0.0
Liña
4
Enderezo IP do cliente (se o hai)

15
O enderezo IP do teu cliente
172.16.134.61
Liña
4
Enderezo IP ofrecido polo servidor (se está dispoñible)

19
O seguinte enderezo IP do servidor
0.0.0.0
Liña
4
Enderezo IP do servidor (se se coñece)

23
Enderezo IP do axente de retransmisión
172.16.114.41
Liña
4
Enderezo IP do axente de retransmisión (por exemplo, un interruptor)

27
Enderezo MAC do cliente
14:d6:4d:a7:c9:55
Feitizo
6
Enderezo MAC do remitente do paquete (cliente)

31
Recheo de enderezos de hardware do cliente
 
Feitizo
10
Asento reservado. Normalmente está cheo de ceros

41
Nome do servidor do servidor
 
Liña
64
Nome do servidor DHCP. Normalmente non se transmite

105
Nome do ficheiro de arranque
 
Liña
128
Nome do ficheiro no servidor utilizado polas estacións sen disco ao iniciar

235
Galletas máxicas
63: 82: 53: 63
Feitizo
4
Número "máxico", segundo o cal, incl. pode determinar que este paquete pertence ao protocolo DHCP

Opcións de DHCP. Pode ir en calquera orde

236
Número de opción
53
decembro
3
Opción 53, que define o tipo de paquete DHCP 3 - DHCPREQUEST

 
Duración da opción
1
decembro
1

 
Valor da opción
3
decembro
1

 
Número de opción
61
decembro
1
ID de cliente: 01 (para Ehernet) + enderezo MAC do cliente

 
Duración da opción
7
decembro
1

 
Valor da opción
01:2c:ab:25:ff:72:a6
Feitizo
7

 
Número de opción
60
decembro
 
"Identificador de clase de provedor". No meu caso, informa da versión do cliente DHCP. Quizais outros dispositivos devolvan algo diferente. Windows, por exemplo, informa MSFT 5.0

 
Duración da opción
11
decembro
 

 
Valor da opción
udhcp 0.9.8
Liña
 

 
Número de opción
55
 
1
Parámetros de rede solicitados polo cliente. A composición pode variar

01 — Máscara de rede
03 - Pasarela
06 - DNS
oc — Nome do servidor
0f - nome de dominio da rede
1c - enderezo da solicitude de emisión (emisión)
42 - Nome do servidor TFTP
79 - Ruta estática sen clase

 
Duración da opción
8
 
1

 
Valor da opción
01:03:06:0c:0f:1c:42:79
 
8

 
Número de opción
82
decembro
1
Opción 82, repite o que veu en DHCPDISCOVER

 
Duración da opción
18
decembro
1

 
Valor da opción
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembro
18

 
Fin do paquete
255
decembro
1
255 simboliza o final do paquete

DHCPACK

Como confirmación de que "si, é certo, este é o teu enderezo IP, e non llo darei a ninguén máis" desde o servidor DHCP, serve un paquete en formato DHCPACK do servidor ao cliente. Envíase difundido igual que outros paquetes. Aínda que, no código de abaixo para un servidor DHCP implementado en Python, por se acaso, duplico calquera solicitude de difusión enviando un paquete a unha IP de cliente específica, se xa se coñece. Ademais, ao servidor DHCP non lle importa en absoluto se o paquete DHCPACK chegou ao cliente. Se o cliente non recibe DHCPACK, despois dun tempo simplemente repite DHCPREQUEST

Táboa de estrutura de paquetes DHCPACK

Posición no paquete
Nome do valor (común)
Exemplo
Introdución
Byte
Esclarecemento

1
Solicitude de arranque
2
Feitizo
1
Tipo de mensaxe. 1 - solicitude de cliente a servidor, 2 - resposta de servidor a cliente

2
Tipo de hardware
1
Feitizo
1
Tipo de enderezo de hardware, neste protocolo 1 - MAC

3
Lonxitude de enderezos de hardware
6
Feitizo
1
Lonxitude do enderezo MAC do dispositivo

4
Lúpulo
1
Feitizo
1
Número de rutas intermedias

5
ID de transacción
23:cf:de:1d
Feitizo
4
Identificador único de transacción. Xerado polo cliente ao comezo dunha operación de solicitude

7
Segundo pasou
0
Feitizo
4
Tempo en segundos desde o inicio do proceso de obtención dun enderezo

9
Bandeiras de arranque
8000
Feitizo
2
Algunhas bandeiras que se poden configurar para indicar parámetros de protocolo. Neste caso, establécese "difusión".

11
Enderezo IP do cliente
0.0.0.0
Liña
4
Enderezo IP do cliente (se o hai)

15
O enderezo IP do teu cliente
172.16.134.61
Liña
4
Enderezo IP ofrecido polo servidor (se está dispoñible)

19
O seguinte enderezo IP do servidor
0.0.0.0
Liña
4
Enderezo IP do servidor (se se coñece)

23
Enderezo IP do axente de retransmisión
172.16.114.41
Liña
4
Enderezo IP do axente de retransmisión (por exemplo, un interruptor)

27
Enderezo MAC do cliente
14:d6:4d:a7:c9:55
Feitizo
6
Enderezo MAC do remitente do paquete (cliente)

31
Recheo de enderezos de hardware do cliente
 
Feitizo
10
Asento reservado. Normalmente está cheo de ceros

41
Nome do servidor do servidor
 
Liña
64
Nome do servidor DHCP. Normalmente non se transmite

105
Nome do ficheiro de arranque
 
Liña
128
Nome do ficheiro no servidor utilizado polas estacións sen disco ao iniciar

235
Galletas máxicas
63: 82: 53: 63
Feitizo
4
Número "máxico", segundo o cal, incl. pode determinar que este paquete pertence ao protocolo DHCP

Opcións de DHCP. Pode ir en calquera orde

236
Número de opción
53
decembro
3
Opción 53, que define o tipo de paquete DHCP 5 - DHCPACK

 
Duración da opción
1
decembro
1

 
Valor da opción
5
decembro
1

 
Número de opción
1
decembro
1
Opción para ofrecer ao cliente DHCP unha máscara de rede

 
Duración da opción
4
decembro
1

 
Valor da opción
255.255.224.0
Liña
4

 
Número de opción
3
decembro
1
Opción para ofrecer ao cliente DHCP unha pasarela predeterminada

 
Duración da opción
4
decembro
1

 
Valor da opción
172.16.12.1
Liña
4

 
Número de opción
6
decembro
1
Opción para ofrecer DHCP ao cliente DNS

 
Duración da opción
4
decembro
1

 
Valor da opción
8.8.8.8
Liña
4

 
Número de opción
51
decembro
1
A vida útil dos parámetros de rede emitidos en segundos, despois do cal o cliente DHCP debe solicitalos de novo

 
Duración da opción
4
decembro
1

 
Valor da opción
86400
decembro
4

 
Número de opción
82
decembro
1
Opción 82, repite o que veu en DHCPDISCOVER

 
Duración da opción
18
decembro
1

 
Valor da opción
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembro
18

 
Fin do paquete
255
decembro
1
255 simboliza o final do paquete

Instalación

A instalación en realidade consiste na instalación dos módulos python necesarios para o traballo. Suponse que MySQL xa está instalado e configurado.

FreeBSD

pkg instalar python3 python3 -m asegurarpip pip3 instalar mysql-connector

Ubuntu

sudo apt-get install python3 sudo apt-get install pip3 sudo pip3 install mysql-connector

Creamos unha base de datos MySQL, cargamos nela o volcado pydhcp.sql e configuramos o ficheiro de configuración.

Configuración

Toda a configuración do servidor está nun ficheiro xml. Ficheiro de referencia:

1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 localhost proba proba pydhcp opción_8.8.8.8_hex:sw_port82:1:20 opción_22_hex:sw_port82:2:16 opción_18_hex:sw_mac:82:26 40 seleccione ip, máscara, enrutador, dns dos usuarios onde upper(mac)=upper('{option_3_AgentRemoteId_hex}') e upper(port)=upper('{option_1_AgentCircuitId_port_hex}') seleccione ip, máscara, enrutador, dns dos usuarios onde upper(mac)=upper('{sw_mac}') e upper(port)=upper('{sw_port82}') seleccione ip, máscara, enrutador, dns dos usuarios onde upper(mac)=upper('{ClientMacAddress}') inserir no historial (id,dt,mac,ip,comment) valores (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Agora con máis detalle sobre as etiquetas:

A sección dhcpserver describe a configuración básica para iniciar o servidor, a saber:

  • host: que enderezo IP escoita o servidor no porto 67
  • broadcast: cal ip é a transmisión para DHCPOFFER e DHCPACK
  • DHCPServer - cal é a ip do servidor DHCP
  • Tempo de arrendamento LeaseTime do enderezo IP emitido
  • ThreadLimit: cantos fíos se executan simultaneamente para procesar os paquetes UDP entrantes no porto 67. Suponse que axuda en proxectos de alta carga 😉
  • defaultMask,defaultRouter,defaultDNS: o que se ofrece ao subscritor por defecto se se atopa unha IP na base de datos, pero non se especifican parámetros adicionais para iso

sección mysql:

host, nome de usuario, contrasinal, nome base: todo fala por si só. Cómprese unha estrutura aproximada da base de datos GitHub

Sección de consulta: as solicitudes para recibir OFERTA/ACK descríbense aquí:

  • offer_count — o número de liñas con solicitudes que devolven un resultado como ip, mask, router, dns
  • offer_n — cadea de consulta. Se a devolución está baleira, executa a seguinte solicitude de oferta
  • history_sql - unha consulta que escribe, por exemplo, no "historial de autorizacións" dun subscritor

As solicitudes poden incluír calquera variable da sección de opcións ou opcións do protocolo DHCP.

Sección de opcións. Aquí é onde se fai máis interesante. Aquí podemos crear variables que podemos usar máis tarde na sección de consulta.

Por exemplo:

option_82_hex:sw_port1:20:22

, esta liña de comandos toma toda a liña que veu na solicitude DHCP para a opción 82, en formato hexadecimal, no intervalo de bytes 20 a 22 inclusive e colócaa na nova variable sw_port1 (cambiar o porto de onde veu a solicitude)

option_82_hex:sw_mac:26:40

, define a variable sw_mac, tomando o hexadecimal do intervalo 26:40

Podes ver todas as opcións posibles que se poden usar nas consultas iniciando o servidor co interruptor -d. Veremos algo así como este rexistro:

--chegou un paquete DHCPINFORM ao porto 67, desde 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': '0025224c': 'ClientMacAddress': '764:'Address'Client:'ClientMac:'00 7 %"Jxd91d" , ' HType': 'Ethernet', 'HostName': b'x5xa0xe3xa5xa9xa8-x8fx43a', 'ReqListDNS': True, 'ReqListDomainName': True, 'ReqListPerfowmRouterDiscover': True, 'ReqList: TruetauRouter': True, 'ReqList: TruetauRouter,' 'ReqListSubnetM ask': True, 'ReqListVendorSpecInfo': 0.0.0.0, 'RequestedIpAddress': '5.0', 'Vendor': b'MSFT 0025224', 'chaddr': '764ad172.30.128.13', 'ciaddr.':00', '00.':172.30.114.25 , 'flags': b'x308x6', 'giaddr': '1', 'gpoz': 82, 'hlen': 12, 'hops': 12, 'htype': 'MAC', 'magic_cookie': b'cx53Sc ', 'op': 'DHCPINFORM', 'option53': 55, 'option55': 60, 'option60': 61, 'option61': 82, 'option82': 82, 'option12': 01, ' option_06_byte': b'x00x04x00x01x00x06x02x08x00x06x00x1' b'x9x2x82eXx12010600040001000602080006001exb589xad', 'option_2_hex': '82 18_len': 82 12, 'option_01_str': "b'x06x00x04x00x01x00x06x02x08x00x06x00x1x9x2eXx768exb0.0.0.0xad'", 'resultado': Falso, 'secs': 001, 'siaddr': '589', 'sw_mac': '2e1eb06ad', 'sw_port89': '8', 'xidbyte': b'

En consecuencia, podemos envolver calquera variable en {} e utilizarase na consulta SQL.

Imos rexistrar para o historial que o cliente recibiu o enderezo IP:

Servidor DHCP+Mysql en Python

Servidor DHCP+Mysql en Python

Iniciando o servidor

./pydhcpdb.py -d -c config.xml

— d modo de saída da consola DEBUG
- c <filename> ficheiro de configuración

Debriefing

E agora máis detalles sobre a implementación do servidor en Python. É unha dor. Python aprendeuse sobre a marcha. Moitos momentos fanse ao estilo de "Guau, dalgún xeito o fixen funcionar". Non está optimizado en absoluto, e deixouse nesta forma principalmente debido á pouca experiencia no desenvolvemento de Python. Deterereime nos aspectos máis interesantes da implementación do servidor en "código".

Analizador de ficheiros de configuración XML

Utilízase o módulo estándar de Python xml.dom. Parece sinxelo, pero durante a implementación houbo unha notable falta de documentación e exemplos claros na rede 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("username")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("contrasinal")[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_default] =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultRouter"] defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("consulta") para elem en qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[1].firstChild.data para num en intervalo(int(gconfig["offer_count"])): gconfig["offer_"+str(num+1)]=elem.getElementsByTagName("oferta_"+str(num+0))[0].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[XNUMX].firstChild.data options=tree.getElementsByTagName("opcións") para o elemento en opcións: node=elem.getElementsByTagName("opción") para as opcións no nodo : optionsMod.append(options.firstChild.data)

Multithreading

Curiosamente, o multithreading en Python está implementado de forma moi clara e sinxela.

def PacketWork(data,addr): ... # implementación de analizar o paquete entrante e responder a el ... mentres que True: data, addr = udp_socket.recvfrom(1024) # esperando polo paquete UDP thread = threading.Thread( target=PacketWork , args=(data,addr,)).start() # como veu - iniciamos a función PacketWork previamente definida en segundo plano con parámetros mentres enhebramos.active_count() >gconfig["dhcp_ThreadLimit"]: time. sleep(1) # se o número Xa hai máis fíos en execución que na configuración, agardamos ata que haxa menos

Recibir/enviar paquete DHCP

Para interceptar os paquetes UDP que chegan a través da tarxeta de rede, cómpre "elevar" o socket:

udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,socket.IPPROTO_UDP) udp_socket.bind((gconfig["dhcp_host"],67))

, onde están as bandeiras:

  • AF_INET - significa que o formato de enderezo será IP: porto. Tamén pode haber AF_UNIX, onde o enderezo vén dado polo nome do ficheiro.
  • SOCK_DGRAM - significa que non aceptamos un "paquete en bruto", senón un que xa pasou polo firewall e cun paquete parcialmente recortado. Eses. recibimos só un paquete UDP sen o compoñente "físico" do envoltorio de paquetes UDP. Se usas a marca SOCK_RAW, tamén terás que analizar este "envoltorio".

O envío dun paquete pode ser como unha emisión:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #cambiar o socket ao modo broadcast rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, e ao enderezo "de onde veu o paquete":

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # cambia o socket ao modo multi-ouvir rz=udp_socket.sendto(packetack, addr)

, onde SOL_SOCKET significa o "nivel de protocolo" para configurar as opcións,

, opción SO_BROADCAST que o paquete do casco está "difundido"

  A opción ,SO_REUSEADDR cambia o socket ao modo "moitos oíntes". En teoría, neste caso é innecesario, pero nun dos servidores FreeBSD nos que probei, o código non funcionaba sen esta opción.

Analizando un paquete DHCP

Aquí é onde me gustou moito Python. Resulta que fóra da caixa permíteche ser bastante flexible co bytecode. Permitindo que se traduza moi facilmente en valores decimais, cadeas e hexadecimales, é dicir. isto é o que realmente necesitamos para comprender a estrutura do paquete. Así, por exemplo, pode obter un intervalo de bytes en HEX e só bytes:

    res["xidhex"]=datos[4:8].hex() res["xidbyte"]=datos[4:8]

, empaqueta os bytes nunha estrutura:

res["bandeiras"]=pack('BB',datos[10],datos[11])

Obter a IP da estrutura:

res["ciaddr"]=socket.inet_ntoa(pack('BBBB',datos[12],datos[13],datos[14],datos[15]));

E viceversa:

res=res+socket.inet_pton(socket.AF_INET, gconfig["dhcp_Server"])

Iso é todo por agora 😉

Fonte: www.habr.com

Engadir un comentario