DHCP + Mysql сервер во Python

DHCP + Mysql сервер во Python

Целта на овој проект беше:

  • Учење за DHCP на IPv4 мрежа
  • Учење Пајтон (малку повеќе од нула 😉)
  • замена на серверот DB2DHCP (мојата вилушка), оригинал тука, кој станува сè потешко да се состави за новиот ОС. И не ми се допаѓа што е бинарно што не постои начин да се „промени во моментов“
  • добивање на работен DHCP сервер со можност да се избере IP адресата на претплатникот користејќи ја комбинацијата на Mac на претплатникот или прекинувач mac+port (Опција 82)
  • пишување друг велосипед (О! ова е мојата омилена активност)
  • примање коментари за вашата клубска рака на Хабрахабр (или уште подобро, покана) 😉

Резултат: работи 😉 Тестирано на FreeBSD и Ubuntu OS. Теоретски, кодот може да се побара да работи под кој било ОС, бидејќи Се чини дека нема специфични врски во кодот.
Внимателно! Има уште многу да дојде.

Врска до складиштето за аматери „допир жив“.

Процесот на инсталирање, конфигурирање и користење на резултатот од „проучување на хардверот“ е многу помал, а потоа и малку теорија за протоколот DHCP. За мене. И за историјата 😉

Малку теорија

Што е DHCP

Ова е мрежен протокол кој му овозможува на уредот да ја дознае својата IP адреса (и други параметри како портал, DNS, итн.) од DHCP сервер. Пакетите се разменуваат со помош на протоколот UDP. Општиот принцип на работа на уредот при барање мрежни параметри е како што следува:

  1. Уредот (клиентот) испраќа барање за емитување UDP (DHCPDISCOVER) низ мрежата со барање „па, некој да ми даде IP адреса“. Покрај тоа, обично (но не секогаш) барањето се јавува од портата 68 (извор), а дестинацијата е порта 67 (дестинација). Некои уреди испраќаат пакети и од портата 67. MAC адресата на клиентскиот уред е вклучена во пакетот DHCPDISCOVER.
  2. Сите DHCP сервери лоцирани на мрежата (а може да има неколку од нив) формираат понуда DHCPOFFER со мрежни поставки за уредот што испрати DHCPDISCOVER, а исто така го емитуваат преку мрежата. Идентификацијата за кого е наменет овој пакет се заснова на MAC адресата на клиентот дадена претходно во барањето DHCPDISCOVER.
  3. Клиентот прифаќа пакети со предлози за мрежни поставки, го избира најатрактивниот (критериумите може да бидат различни, на пример, времето на испорака на пакетите, бројот на средни рути) и поднесува „официјално барање“ DHCPREQUEST со мрежните поставки од DHCP серверот што му се допаѓа. Во овој случај, пакетот оди до одреден DHCP сервер.
  4. Серверот што го примил DHCPREQUEST испраќа пакет со формат DHCPACK, во кој уште еднаш ги наведува мрежните поставки наменети за овој клиент

DHCP + Mysql сервер во Python

Дополнително, има DHCPINFORM пакети кои доаѓаат од клиентот и чија цел е да го информираат DHCP-серверот дека „клиентот е жив“ и ги користи издадените мрежни поставки. Во имплементацијата на овој сервер, овие пакети се игнорираат.

Формат на пакет

Во принцип, рамката за етернет пакет изгледа вака:

DHCP + Mysql сервер во Python

Во нашиот случај, ќе ги разгледаме само податоците директно од содржината на UDP пакетот, без заглавија на протоколот на слојот OSI, имено структурата DHCP:

DHCPDISCOVER

Значи, процесот на добивање IP адреса за уред започнува со тоа што клиентот DHCP испраќа барање за емитување од портата 68 на 255.255.255.255:67. Во овој пакет, клиентот ја вклучува својата MAC адреса, како и што точно сака да добие од серверот DHCP. Структурата на пакетот е опишана во табелата подолу.

Табела со структура на пакети DHCPDISCOVER

Позиција во пакувањето
Име на вредност
Пример
Вовед
Бајт
појаснување

1
Барање за подигање
1
Двојна
1
Тип на порака. 1 - барање од клиент до сервер, 2 - одговор од сервер до клиент

2
Тип на хардвер
1
Двојна
1
Тип на хардверска адреса, во овој протокол 1 - MAC

3
Должина на хардверски адреси
6
Двојна
1
Должина на MAC адресата на уредот

4
Хмел
1
Двојна
1
Број на средни правци

5
ID на трансакција
23:cf:de:1d
Двојна
4
Единствен идентификатор на трансакција. Генериран од клиентот на почетокот на операцијата за барање

7
Второто помина
0
Двојна
4
Време во секунди од почетокот на процесот на добивање адреса

9
Знамиња за подигање
0
Двојна
2
Одредени знаменца што може да се постават да укажуваат на параметри на протоколот

11
IP адреса на клиентот
0.0.0.0
Линија
4
IP адреса на клиентот (ако има)

15
IP адреса на вашиот клиент
0.0.0.0
Линија
4
IP адреса понудена од серверот (ако е достапна)

19
Следна IP адреса на серверот
0.0.0.0
Линија
4
IP адреса на серверот (ако е позната)

23
IP адреса на агентот за реле
172.16.114.41
Линија
4
IP адреса на релејниот агент (на пример, прекинувач)

27
MAC адреса на клиентот
14:d6:4d:a7:c9:55
Двојна
6
MAC адреса на испраќачот на пакети (клиент)

31
Пополнување на адресата на хардверот на клиентот
 
Двојна
10
Резервирано седиште. Обично се полни со нули

41
Име на домаќин на серверот
 
Линија
64
Име на серверот DHCP. Обично не се пренесува

105
Име на датотеката за подигање
 
Линија
128
Име на датотеката на серверот што го користат станиците без диск при подигнување

235
Магични колачиња
63: 82: 53: 63
Двојна
4
„Магичен“ број, според кој, вкл. можете да одредите дека овој пакет припаѓа на протоколот DHCP

Опции за DHCP. Може да оди по кој било редослед

236
Број на опција
53
декември
1
Опција 53, која го одредува типот на пакетот DHCP

1 - DHCPDISCOVER
3 - DHCPREQUEST
2 - DHCPOFFER
5 - DHCPACK
8 - DHCPINFORM

 
Должина на опцијата
1
декември
1

 
Вредност на опцијата
1
декември
1

 
Број на опција
50
декември
1
Која IP адреса сака да ја добие клиентот?

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
172.16.134.61
Линија
4

 
Број на опција
55
 
1
Мрежни параметри побарани од клиентот. Составот може да варира

01 — Мрежна маска
03 - Порта
06 - DNS
oc — име на домаќин
0f - име на мрежен домен
1в - адреса на барање за емитување (емитување)
42 - Име на TFTP сервер
79 - Безкласна статична рута

 
Должина на опцијата
8
 
1

 
Вредност на опцијата
01:03:06:0c:0f:1c:42:79
 
8

 
Број на опција
82
декември
 
Опција 82, која ја пренесува MAC адресата на уредот со повторувач и некои дополнителни вредности.

Најчесто ова е портот на прекинувачот на кој работи крајниот DHCP клиент.Оваа опција содржи дополнителни параметри.Првиот бајт е бројот на „подопцијата“, вториот е неговата должина, потоа неговата вредност.

Во овој случај, во опцијата 82, под-опциите се вгнездени:
ИД на коло на агент = 00:04:00:01:00:04, каде што последните два бајта се портата на клиентот DHCP од која дојде барањето

Далечински ID на агент = 00:06:c8:be:19:93:11:48 - MAC адреса на уредот со повторувач DHCP

 
Должина на опцијата
18
декември
 

 
Вредност на опцијата
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Двојна
 

 
Крај на пакетот
255
декември
1
255 го симболизира крајот на пакетот

DHCPOFFER

Штом серверот го прими пакетот DHCPDISCOVER и ако види дека може да му понуди на клиентот нешто од бараното, тогаш генерира одговор за него - DHCPDISCOVER. Одговорот се испраќа до пристаништето „од каде што дојде“, со емитување, бидејќи во овој момент, клиентот сè уште нема IP адреса, затоа може да го прифати пакетот само ако е испратен преку емитување. Клиентот препознава дека ова е пакет за него по неговата MAC адреса во пакетот, како и бројот на трансакцијата што го генерира во моментот на креирање на првиот пакет.

Табела со структура на пакети DHCPOFFER

Позиција во пакувањето
Име на вредноста (заедничко)
Пример
Вовед
Бајт
појаснување

1
Барање за подигање
1
Двојна
1
Тип на порака. 1 - барање од клиент до сервер, 2 - одговор од сервер до клиент

2
Тип на хардвер
1
Двојна
1
Тип на хардверска адреса, во овој протокол 1 - MAC

3
Должина на хардверски адреси
6
Двојна
1
Должина на MAC адресата на уредот

4
Хмел
1
Двојна
1
Број на средни правци

5
ID на трансакција
23:cf:de:1d
Двојна
4
Единствен идентификатор на трансакција. Генериран од клиентот на почетокот на операцијата за барање

7
Второто помина
0
Двојна
4
Време во секунди од почетокот на процесот на добивање адреса

9
Знамиња за подигање
0
Двојна
2
Одредени знаменца што може да се постават да укажуваат на параметри на протоколот. Во овој случај, 0 значи тип на барање Unicast

11
IP адреса на клиентот
0.0.0.0
Линија
4
IP адреса на клиентот (ако има)

15
IP адреса на вашиот клиент
172.16.134.61
Линија
4
IP адреса понудена од серверот (ако е достапна)

19
Следна IP адреса на серверот
0.0.0.0
Линија
4
IP адреса на серверот (ако е позната)

23
IP адреса на агентот за реле
172.16.114.41
Линија
4
IP адреса на релејниот агент (на пример, прекинувач)

27
MAC адреса на клиентот
14:d6:4d:a7:c9:55
Двојна
6
MAC адреса на испраќачот на пакети (клиент)

31
Пополнување на адресата на хардверот на клиентот
 
Двојна
10
Резервирано седиште. Обично се полни со нули

41
Име на домаќин на серверот
 
Линија
64
Име на серверот DHCP. Обично не се пренесува

105
Име на датотеката за подигање
 
Линија
128
Име на датотеката на серверот што го користат станиците без диск при подигнување

235
Магични колачиња
63: 82: 53: 63
Двојна
4
„Магичен“ број, според кој, вкл. можете да одредите дека овој пакет припаѓа на протоколот DHCP

Опции за DHCP. Може да оди по кој било редослед

236
Број на опција
53
декември
1
Опција 53, која го дефинира типот на пакет DHCP 2 - DHCPOFFER

 
Должина на опцијата
1
декември
1

 
Вредност на опцијата
2
декември
1

 
Број на опција
1
декември
1
Опција да му се понуди на клиентот DHCP мрежна маска

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
255.255.224.0
Линија
4

 
Број на опција
3
декември
1
Опција да му се понуди на клиентот DHCP стандардна порта

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
172.16.12.1
Линија
4

 
Број на опција
6
декември
1
Опција да се понуди DHCP на клиентот DNS

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
8.8.8.8
Линија
4

 
Број на опција
51
декември
1
Животниот век на издадените мрежни параметри во секунди, по што клиентот DHCP мора повторно да ги побара

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
86400
декември
4

 
Број на опција
82
декември
1
Опција 82, го повторува она што дојде во DHCPDISCOVER

 
Должина на опцијата
18
декември
1

 
Вредност на опцијата
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
декември
18

 
Крај на пакетот
255
декември
1
255 го симболизира крајот на пакетот

DHCPREQUEST

Откако клиентот ќе добие DHCPOFFER, тој формира пакет кој бара мрежни параметри не на сите DHCP сервери на мрежата, туку само на еден специфичен, чија понуда DHCPOFFER „му се допадна“ најмногу. Критериумите „како“ можат да бидат различни и да зависат од имплементацијата на DHCP на клиентот. Примачот на барањето се одредува со помош на MAC адресата на серверот DHCP. Исто така, клиентот може да испрати пакет DHCPREQUEST без претходно да се генерира DHCPDISCOVER, доколку IP адресата на серверот е веќе добиена претходно.

Табела со структура на пакети DHCPREQUEST

Позиција во пакувањето
Име на вредноста (заедничко)
Пример
Вовед
Бајт
појаснување

1
Барање за подигање
1
Двојна
1
Тип на порака. 1 - барање од клиент до сервер, 2 - одговор од сервер до клиент

2
Тип на хардвер
1
Двојна
1
Тип на хардверска адреса, во овој протокол 1 - MAC

3
Должина на хардверски адреси
6
Двојна
1
Должина на MAC адресата на уредот

4
Хмел
1
Двојна
1
Број на средни правци

5
ID на трансакција
23:cf:de:1d
Двојна
4
Единствен идентификатор на трансакција. Генериран од клиентот на почетокот на операцијата за барање

7
Второто помина
0
Двојна
4
Време во секунди од почетокот на процесот на добивање адреса

9
Знамиња за подигање
8000
Двојна
2
Одредени знаменца што може да се постават да укажуваат на параметри на протоколот. Во овој случај, се поставува „емитување“.

11
IP адреса на клиентот
0.0.0.0
Линија
4
IP адреса на клиентот (ако има)

15
IP адреса на вашиот клиент
172.16.134.61
Линија
4
IP адреса понудена од серверот (ако е достапна)

19
Следна IP адреса на серверот
0.0.0.0
Линија
4
IP адреса на серверот (ако е позната)

23
IP адреса на агентот за реле
172.16.114.41
Линија
4
IP адреса на релејниот агент (на пример, прекинувач)

27
MAC адреса на клиентот
14:d6:4d:a7:c9:55
Двојна
6
MAC адреса на испраќачот на пакети (клиент)

31
Пополнување на адресата на хардверот на клиентот
 
Двојна
10
Резервирано седиште. Обично се полни со нули

41
Име на домаќин на серверот
 
Линија
64
Име на серверот DHCP. Обично не се пренесува

105
Име на датотеката за подигање
 
Линија
128
Име на датотеката на серверот што го користат станиците без диск при подигнување

235
Магични колачиња
63: 82: 53: 63
Двојна
4
„Магичен“ број, според кој, вкл. можете да одредите дека овој пакет припаѓа на протоколот DHCP

Опции за DHCP. Може да оди по кој било редослед

236
Број на опција
53
декември
3
Опција 53, која го дефинира DHCP пакетот тип 3 - DHCPREQUEST

 
Должина на опцијата
1
декември
1

 
Вредност на опцијата
3
декември
1

 
Број на опција
61
декември
1
ID на клиент: 01 (за Ehernet) + MAC адреса на клиентот

 
Должина на опцијата
7
декември
1

 
Вредност на опцијата
01:2c:ab:25:ff:72:a6
Двојна
7

 
Број на опција
60
декември
 
„Идентификатор на класа на продавач“. Во мојот случај, ја известува верзијата на клиентот DHCP. Можеби другите уреди враќаат нешто поинакво. Windows на пример известува MSFT 5.0

 
Должина на опцијата
11
декември
 

 
Вредност на опцијата
патcp 0.9.8
Линија
 

 
Број на опција
55
 
1
Мрежни параметри побарани од клиентот. Составот може да варира

01 — Мрежна маска
03 - Порта
06 - DNS
oc — име на домаќин
0f - име на мрежен домен
1в - адреса на барање за емитување (емитување)
42 - Име на TFTP сервер
79 - Безкласна статична рута

 
Должина на опцијата
8
 
1

 
Вредност на опцијата
01:03:06:0c:0f:1c:42:79
 
8

 
Број на опција
82
декември
1
Опција 82, го повторува она што дојде во DHCPDISCOVER

 
Должина на опцијата
18
декември
1

 
Вредност на опцијата
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
декември
18

 
Крај на пакетот
255
декември
1
255 го симболизира крајот на пакетот

DHCPACK

Како потврда дека „да, така е, ова е вашата IP адреса и нема да ја дадам на никој друг“ од серверот DHCP, служи пакет во формат DHCPACK од серверот до клиентот. Се испраќа емитување исто како и другите пакети. Иако, во кодот подолу за DHCP сервер имплементиран во Python, за секој случај, го дуплирам секое барање за емитување со испраќање пакет до одредена IP адреса на клиентот, доколку е веќе познато. Покрај тоа, на DHCP серверот воопшто не му е грижа дали DHCPACK пакетот стигнал до клиентот. Ако клиентот не добие DHCPACK, тогаш по некое време едноставно го повторува DHCPREQUEST

Табела со структура на пакети DHCPACK

Позиција во пакувањето
Име на вредноста (заедничко)
Пример
Вовед
Бајт
појаснување

1
Барање за подигање
2
Двојна
1
Тип на порака. 1 - барање од клиент до сервер, 2 - одговор од сервер до клиент

2
Тип на хардвер
1
Двојна
1
Тип на хардверска адреса, во овој протокол 1 - MAC

3
Должина на хардверски адреси
6
Двојна
1
Должина на MAC адресата на уредот

4
Хмел
1
Двојна
1
Број на средни правци

5
ID на трансакција
23:cf:de:1d
Двојна
4
Единствен идентификатор на трансакција. Генериран од клиентот на почетокот на операцијата за барање

7
Второто помина
0
Двојна
4
Време во секунди од почетокот на процесот на добивање адреса

9
Знамиња за подигање
8000
Двојна
2
Одредени знаменца што може да се постават да укажуваат на параметри на протоколот. Во овој случај, се поставува „емитување“.

11
IP адреса на клиентот
0.0.0.0
Линија
4
IP адреса на клиентот (ако има)

15
IP адреса на вашиот клиент
172.16.134.61
Линија
4
IP адреса понудена од серверот (ако е достапна)

19
Следна IP адреса на серверот
0.0.0.0
Линија
4
IP адреса на серверот (ако е позната)

23
IP адреса на агентот за реле
172.16.114.41
Линија
4
IP адреса на релејниот агент (на пример, прекинувач)

27
MAC адреса на клиентот
14:d6:4d:a7:c9:55
Двојна
6
MAC адреса на испраќачот на пакети (клиент)

31
Пополнување на адресата на хардверот на клиентот
 
Двојна
10
Резервирано седиште. Обично се полни со нули

41
Име на домаќин на серверот
 
Линија
64
Име на серверот DHCP. Обично не се пренесува

105
Име на датотеката за подигање
 
Линија
128
Име на датотеката на серверот што го користат станиците без диск при подигнување

235
Магични колачиња
63: 82: 53: 63
Двојна
4
„Магичен“ број, според кој, вкл. можете да одредите дека овој пакет припаѓа на протоколот DHCP

Опции за DHCP. Може да оди по кој било редослед

236
Број на опција
53
декември
3
Опција 53, која го дефинира DHCP пакетот тип 5 - DHCPACK

 
Должина на опцијата
1
декември
1

 
Вредност на опцијата
5
декември
1

 
Број на опција
1
декември
1
Опција да му се понуди на клиентот DHCP мрежна маска

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
255.255.224.0
Линија
4

 
Број на опција
3
декември
1
Опција да му се понуди на клиентот DHCP стандардна порта

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
172.16.12.1
Линија
4

 
Број на опција
6
декември
1
Опција да се понуди DHCP на клиентот DNS

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
8.8.8.8
Линија
4

 
Број на опција
51
декември
1
Животниот век на издадените мрежни параметри во секунди, по што клиентот DHCP мора повторно да ги побара

 
Должина на опцијата
4
декември
1

 
Вредност на опцијата
86400
декември
4

 
Број на опција
82
декември
1
Опција 82, го повторува она што дојде во DHCPDISCOVER

 
Должина на опцијата
18
декември
1

 
Вредност на опцијата
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
декември
18

 
Крај на пакетот
255
декември
1
255 го симболизира крајот на пакетот

Инсталација

Инсталацијата всушност се состои од инсталирање на python модулите неопходни за работа. Се претпоставува дека MySQL е веќе инсталиран и конфигуриран.

FreeBSD

pkg инсталирај python3 python3 -m surepip pip3 инсталирај mysql-приклучок

Ubuntu

sudo apt-get инсталирај python3 sudo apt-get инсталирај pip3 sudo pip3 инсталирај mysql-приклучок

Создаваме база на податоци MySQL, ја поставуваме депонијата pydhcp.sql во неа и ја конфигурираме датотеката за конфигурација.

Конфигурација

Сите поставки на серверот се во датотека xml. Референтна датотека:

1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 локален домаќин тест тест pydhcp option_8.8.8.8_hex:sw_port82:1:20 option_22_hex:sw_port82:2:16 option_18_hex:sw_mac:82:26 40 изберете ip, маска, рутер, dns од корисници каде upper(mac)=upper('{option_3_AgentRemoteId_hex}') и upper(port)=upper('{option_1_AgentCircuitId_port_hex}') изберете ip, маска, рутер, dns од корисници каде upper(mac)=upper('{sw_mac}') и upper(port)=upper('{sw_port82}') изберете ip, маска, рутер, dns од корисници каде upper(mac)=upper('{ClientMacAddress}') вметнете во историјата (id, dt, mac, ip, коментар) вредности (null, now(), „{ClientMacAddress}“, „{RequestedIpAddress}“, „DHCPACK/INFORM“)

Сега подетално за ознаките:

Делот dhcpserver ги опишува основните поставки за стартување на серверот, имено:

  • домаќин - која IP адреса ја слуша серверот на портата 67
  • емитување - која IP е емитувањето за DHCPOFFER и DHCPACK
  • DHCPS-сервер - која е IP-а на серверот DHCP
  • LeaseTime време на закуп на издадената IP адреса
  • ThreadLimit - колку нишки се извршуваат истовремено за да се обработат дојдовните UDP пакети на портата 67. Би требало да помогне во проекти со големо оптоварување 😉
  • defaultMask,defaultRouter,defaultDNS - што стандардно му се нуди на претплатникот ако се најде IP во базата на податоци, но за него не се наведени дополнителни параметри

mysql дел:

домаќин, корисничко име, лозинка, основно име - сè зборува само за себе. Приближна структура на базата на податоци е објавена на GitHub

Оддел за барање: барањата за примање ПОНУДА/АЦК се опишани овде:

  • offer_count - бројот на линии со барања кои враќаат резултат како ip, маска, рутер, dns
  • offer_n — низа за пребарување. Ако враќањето е празно, тогаш го извршува следното барање за понуда
  • history_sql - барање што пишува, на пример, во „историјата на овластување“ за претплатник

Барањата може да вклучуваат какви било променливи од делот за опции или опции од протоколот DHCP.

Дел за опции. Овде станува поинтересно. Овде можеме да креираме променливи кои можеме да ги користиме подоцна во делот за пребарување.

На пример:

option_82_hex:sw_port1:20:22

, оваа командна линија ја зема целата линија што дојде во опцијата за барање DHCP 82, во хексадецимален формат, во опсег од 20 до 22 бајти вклучително и ја става во новата променлива sw_port1 (прекинувачка порта од каде дојде барањето)

option_82_hex:sw_mac:26:40

, дефинирајте ја променливата sw_mac, земајќи го шеснаесетникот од опсегот 26:40

Можете да ги видите сите можни опции што може да се користат во барањата со стартување на серверот со прекинувачот -d. Ќе видиме нешто како овој дневник:

--пакет DHCPINFORM пристигна на пристаништето 67, од 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': '0025224ClientMacAddress': '764ClientMacAddress': '00' % „Jxd7d“, 'Htype': 'Ethernet', 'име на домаќинот': b'x91xa5xe0xa3xa5xa9-x8fx8a ',' reqlistdns ': true,' reqlistdomainname ': true,' reqlistperfowmrouterdiscover ': true,' reqlistrouter ':' Reqlisttuthouterouteroutherouteroute 'reqlistticouterouter' ReqListSubnetMask ': Точно, 'ReqListVendorSpecInfo': 43, 'RequestedIpAddress': '0.0.0.0', 'Продавач': b'MSFT 5.0', 'chaddr': '0025224ad764', '172.30.128.13': '00': '00': '172.30.114.25': '308': '6. знаменца ': b'x1x82', 'giaddr': '12', 'gpoz': 12, 'hlen': 53, 'hops': 53, 'htype': 'MAC', 'magic_cookie': b' cx55Sc ', 'op': 'DHCPINFORM', 'option55': 60, 'option60': 61, 'option61': 82, 'option82': 82, 'option12': 01, 'option06': 00, 'option_04_byte' : b'x00x01x00x06x02x08x00x06x00x1x9x2' b'x82x12010600040001000602080006001x589eXx2exb82xad', 'option_18_hex': '82 12, 'option_01_str': "b'x06x00x04x00x01x00x06x02x08x00x06x00x1x9x2eXx768exb0.0.0.0xad", "резултат": неточно, "сек": 001, "siaddr" : '589', 'sw_mac': '2e1eb06ad', 'sw_port89': '8', 'xidbyte': b'

Соодветно на тоа, можеме да ја завиткаме секоја променлива во {} и таа ќе се користи во барањето SQL.

Дозволете ни да евидентираме за историјата дека клиентот ја добил IP адресата:

DHCP + Mysql сервер во Python

DHCP + Mysql сервер во Python

Стартување на серверот

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

— d излезен режим на конзола DEBUG
- в <име на датотека> конфигурациска датотека

Дебрифинг

И сега повеќе детали за имплементација на серверот во Python. Тоа е болка. Пајтон беше научен во лет. Многу моменти се направени во стилот „леле, некако успеав да функционира“. Воопшто не е оптимизиран и оставен во оваа форма главно поради малото искуство во развојот на Python. Ќе се задржам на најинтересните аспекти на имплементацијата на серверот во „кодот“.

Парсер на конфигурациска датотека XML

Се користи стандардниот Python модул xml.dom. Се чини едноставно, но за време на имплементацијата имаше забележлив недостаток на јасна документација и примери на мрежата што го користи овој модул.

    дрво = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") за елемент во mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("домаќин")[0].dast gconfig["mysql_username"]=elem.getElementsByTagName("корисничко име")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("лозинка")[0].firstqconfiglmy" =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") за елемент во dconfig: gconfig["broadcast"]=elem.getElementsByTagName.)"(0) firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("домаќин")[0].firstChild.data gconfig["dhcp_LeaseTime"]=elem.getElementsByTagName("LeaseTime")[0]configd.first dhcp_ThreadLimit"]=int(elem.getElementsByTagName("ThreadLimit")[0].firstChild.data) gconfig["dhcp_Server"]=elem.getElementsByTagName("DHCPS-сервер")[0]configd]dept. =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.податоци gconfig[element. defaultDNS")[0].firstChild.податоци qconfig=tree.getElementsByTagName("query") за елемент во qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.податоци за num опсег (int(gconfig["offer_count"]): gconfig["offer_"+str(num+1)]=elem.getElementsByTagName("offer_"+str(num+1))[0].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[0].firstChild.data options=tree.getElementsByTagName("опции") за елемент во опции: node=elem.getElementsByTagName опции")(" : optionsMod.append(options.firstChild.data)

Повеќенишки

Чудно е доволно, но мултинишките во Пајтон се имплементираат многу јасно и едноставно.

def PacketWork(data,addr): ... # имплементација на парсирање на дојдовниот пакет и одговарање на него ... додека True: data, addr = udp_socket.recvfrom(1024) # чекање за UDP пакетот нишка = threading.Thread( target=PacketWork , args=(data,addr,)).start() # како што дојде - ја стартуваме претходно дефинираната функција PacketWork во позадина со параметри додека threading.active_count() >gconfig["dhcp_ThreadLimit"]: време. спиење (1) # ако бројот Веќе има повеќе теми отколку во поставките, чекаме да има помалку од нив

Примајте/испратете DHCP пакет

За да ги пресретнете UDP пакетите што доаѓаат преку мрежната картичка, треба да го „подигнете“ штекерот:

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

, каде знамињата се:

  • AF_INET - значи дека форматот на адресата ќе биде IP: порта. Може да има и AF_UNIX - каде што адресата е дадена со името на датотеката.
  • SOCK_DGRAM - значи дека не прифаќаме „суров пакет“, туку оној што веќе поминал низ заштитниот ѕид и со делумно исечен пакет. Оние. добиваме само UDP пакет без „физичката“ компонента на обвивката на UDP пакетот. Ако го користите знамето SOCK_RAW, тогаш исто така ќе треба да ја анализирате оваа „обвивка“.

Испраќањето пакет може да биде како емитување:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #префрли го штекерот во режим на емитување rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, и на адресата „од каде дојде пакетот“:

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # префрли го штекерот во режим на повеќе слушатели rz=udp_socket.sendto(packetack, addr)

, каде што SOL_SOCKET значи „ниво на протокол“ за поставување опции,

, SO_BROADCAST опција дека пакетот кацига е „емитуван“

  Опцијата SO_REUSEADDR го префрла штекерот во режим „многу слушатели“. Во теорија, тоа е непотребно во овој случај, но на еден од серверите на FreeBSD на кои тестирав, кодот не работеше без оваа опција.

Парсирање на DHCP пакет

Ова е местото каде што навистина ми се допадна Пајтон. Излегува дека надвор од кутијата ви овозможува да бидете прилично флексибилни со бајтекодот. Дозволувајќи многу лесно да се преведе во децимални вредности, жици и хексадеци - т.е. ова е она што всушност ни треба за да ја разбереме структурата на пакетот. Така, на пример, можете да добиете опсег на бајти во HEX и само бајти:

    res["xidhex"]=податоци[4:8].hex() res["xidbyte"]=податоци[4:8]

, спакувајте ги бајтите во структура:

res["flags"]=pack('BB',податоци[10],податоци[11])

Добијте IP од структурата:

res["ciaddr"]=socket.inet_ntoa(pack('BBBB',податоци[12],податоци[13],податоци[14],податоци[15]));

И обратно:

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

Тоа е се за сега 😉

Извор: www.habr.com

Додадете коментар