замена серверу DB2DHCP (мой форк), арыгінал тут, Які збіраць пад новую АС усё цяжэй і цяжэй. Ды і не падабаецца, што бінарнік, які няма магчымасці «памяняць прам зара»
атрыманне працаздольнага сервера DHCP з магчымасцю выбаркі IP адраса абанента па mac абанента ці звязку mac свіча+порт (Option 82)
напісанне чарговага ровара (О! гэты мой любімы занятак)
атрыманне люлей пра сваю касарукасць на Хабрахабр (а лепш инвайта) 😉
Вынік: працуе 😉 Апрабавана на АС FreeBSD і Ubuntu. Тэарэтычна код можна папрасіць працаваць пад любой АС, т.я. спецыфічных прывязак у кодзе як быццам няма.
Асцярожна! Далей многа.
Спасылка на рэпазітар для аматараў «пакратаць жыўцом».
Працэс усталёўкі, налады і выкарыстанні выніку "вывучэння матчасты" шмат ніжэй, а далей трошкі тэорыі па пратаколе DHCP. Для сябе. І для гісторыі 😉
Крыху тэорыі
Што такое DHCP
Гэта сеткавы пратакол які дазваляе прыладзе пазнаць свой IP адрас (ну і іншыя параметры накшталт шлюза, DNS і іншага), у сервера DHCP. Абмен пакетамі ідзе па пратаколе UDP. Агульны прынцып працы прылады пры запыце параметраў сеткі наступны:
Прылада (кліент) рассылае шырокавяшчальны UDP запыт (DHCPDISCOVER) па ўсёй сетцы з запытам «ну хто-небудзь, дайце мне IP адрас». Прычым звычайна (але не заўсёды) запыт адбываецца з 68 порта (крыніца), а прызначэнне - 67 порт (прызначэнне). Некаторыя прылады адпраўляюць пакеты і з 67 порта. Унутры пакета DHCPDISCOVER уключаны MAC адрас прылады кліента.
Усе серверы DHCP, змешчаныя ў сеткі (а іх можа быць некалькі), фармуюць для прылады які адправіў DHCPDISCOVER, прапанова DHCPOFFER з сеткавымі наладамі, і гэтак жа шырокавяшчальна яго адсылае яго па сетцы. Ідэнтыфікацыя каму прызначаны гэты пакет ідзе па MAC адрасе кліента, прадстаўленага раней у запыце DHCPDISCOVER.
Кліент прымае пакеты з прапановамі сеткавых налад, выбірае найболей прывабны (крытэрыі могуць быць рознымі, напрыклад у т.л. і па часе дастаўкі пакета, колькасці прамежкавых маршрутаў), і робіць у ўпадабанага сервера DHCP «афіцыйны запыт» DHCPREQUEST з сеткавымі наладамі. У гэтым выпадку пакет ідзе ўжо да канкрэтнага сервера DHCP.
Сервер, які атрымаў DHCPREQUEST, адпраўляе пакет фармату DHCPACK, у якім у чарговы раз пералічвае сеткавыя наладкі прызначаныя для дадзенага кліента
Акрамя таго, ёсць пакеты DHCPINFORM, якія ходзяць ад кліента, і мэта якіх праінфармаваць DHCP сервер аб тым, што "кліент жывы" і карыстаецца выдадзенымі сеткавымі наладамі. У рэалізацыі дадзенага сервера гэтыя пакеты ігнаруюцца.
Фармат пакетаў
У цэлым фрэйм пакета Ethernet выглядае прыкладна так:
У нашым выпадку мы разгледзім толькі дадзеныя непасрэдна змесціва пакета UDP, без загалоўкаў пратаколаў узроўняў OSI, а менавіта структуру DHCP:
DHCPDISCOVER
Такім чынам, працэс атрымання IP адрасы для прылады пачынаецца з таго, што кліент DHCP рассылае шырокавяшчальны запыт з порта 68 на 255.255.255.255:67. У гэтым пакеце кліент уключае свой MAC адрас, а так-жа што менавіта ён жадае атрымаць ад DHCP сервера. Структура пакета апісана ў выглядзе табліцы ніжэй.
Табліца структуры пакета DHCPDISCOVER
Пазіцыя ў пакеце
Назва значэння
Прыклад
прадстаўленне
байт
Тлумачэнне
1
Boot Request
1
Hex
1
Тып паведамлення. 1 - запыт ад кліента да сервера, 2 - адказ ад сервера кліенту
2
Тып апаратнага забеспячэння
1
Hex
1
Тып апаратнага адраса, у дадзеным пратаколе 1 - MAC
3
Hardware adrees length
6
Hex
1
Даўжыня MAC адрасы прылады
4
Хмель
1
Hex
1
Колькасць прамежкавых маршрутаў
5
Ідэнтыфікацыя здзелкі
23:cf:de:1d
Hex
4
Унікальны ідэнтыфікатар транзакцыі. Генеруе кліент у пачатку аперацыі запыту
7
Second elapsed
0
Hex
4
Час у секундах з пачатку працэсу атрымання адрасу
9
Bootp flags
0
Hex
2
Некаторыя сцягі, якія могуць усталёўвацца, у якасці ўказання параметраў пратакола
11
Client IP address
0.0.0.0
радок
4
IP адрас кліента (калі ёсць)
15
Your client IP address
0.0.0.0
радок
4
IP адрас прапанаваны серверам (калі ёсць)
19
Next server IP address
0.0.0.0
радок
4
IP адрас сервера (калі вядомы)
23
Relay agent IP address
172.16.114.41
радок
4
IP адрас агента рэтрансляцыі (напрыклад свіча)
27
Client MAC address
14:d6:4d:a7:c9:55
Hex
6
MAC адрас адпраўніка пакета (кліента)
31
Client hardware address padding
Hex
10
Зарэзерваванае месца. Звычайна забіта нулямі
41
Server host name
радок
64
Імя сервера DHCP. Звычайна не перадаецца
105
Boot file name
радок
128
Імя файла на серверы, якое выкарыстоўваецца бездыскавымі станцыямі пры загрузцы
235
Magic cookie
63: 82: 53: 63
Hex
4
"Магічны" лік, па якім у т.л. можна вызначыць, што гэты пакет - належыць пратаколу DHCP
Опцыі DHCP. Могуць ісці ў любым парадку
236
Нумар опцыі
53
снежні
1
Опцыя 53, якая вызначае тып пакета DHCP
Нумар опцыі
50
снежні
1
Які IP адрас хоча атрымаць кліент
Даўжыня опцыі
4
снежні
1
Значэнне опцыі
172.16.134.61
радок
4
Нумар опцыі
55
1
Запытаныя кліентам сеткавыя параметры. Склад можа быць розным
01 - Маска сеткі
03 - Шлюз
06 - DNS
oc - Імя хаста
0f - імя дамена сеткі
1c - адрас шырокавяшчальнага запыту (бродкаста)
42 - імя сервера TFTP
79 — Classless Static Route
Даўжыня опцыі
8
1
Значэнне опцыі
01:03:06:0c:0f:1c:42:79
8
Нумар опцыі
82
снежні
Опцыя 82, у якой перадаецца MAC адрас прылады - рэтранслятара і нейкія дадатковыя значэння.
Часцей за ўсё – порт свіча на якім працуе канчатковы кліент DHCP У дадзенай опцыі «ўкладзены» дадатковыя параметры. Першы байт – нумар «падапцыі», другі яе даўжыня, далей яе значэнне.
У дадзеным выпадку ў опцыі 82, укладзены падопцыі:
Agent Circuit ID = 00:04:00:01:00:04, дзе апошнія два байта - порт кліента DHCP з якога прыйшоў запыт
Agent Remote 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
Hex
Канчатак пакета
255
снежні
1
255 сімвалізуе канчатак пакета
DHCPOFFER
Як толькі сервер атрымлівае пакет DHCPDISCOVER і калі ён бачыць, што можа кліенту нешта прапанаваць з запытанага, то ён фармуе для яго адказ – DHCPDISCOVER. Адказ высылаецца на порт "адкуль прыйшоў", бродкастам, т.я. у гэты момант, у кліента яшчэ няма IP адрасу, такім чынам пакет ён можа прыняць, толькі калі ён дасланы шырокавяшчальна. Кліент распазнае што гэта пакет для яго па MAC свайму адрасу ўнутры пакета, а таксама нумару транзакцыі, які ён генеруе ў момант стварэння першага пакета.
Табліца структуры пакета DHCPOFFER
Пазіцыя ў пакеце
Назва значэння (агульнапрынятае)
Прыклад
прадстаўленне
байт
Тлумачэнне
1
Boot Request
1
Hex
1
Тып паведамлення. 1 - запыт ад кліента да сервера, 2 - адказ ад сервера кліенту
2
Тып апаратнага забеспячэння
1
Hex
1
Тып апаратнага адраса, у дадзеным пратаколе 1 - MAC
3
Hardware adrees length
6
Hex
1
Даўжыня MAC адрасы прылады
4
Хмель
1
Hex
1
Колькасць прамежкавых маршрутаў
5
Ідэнтыфікацыя здзелкі
23:cf:de:1d
Hex
4
Унікальны ідэнтыфікатар транзакцыі. Генеруе кліент у пачатку аперацыі запыту
7
Second elapsed
0
Hex
4
Час у секундах з пачатку працэсу атрымання адрасу
9
Bootp flags
0
Hex
2
Некаторыя сцягі, якія могуць усталёўвацца, у якасці ўказання параметраў пратакола. У дадзеным выпадку, 0 - азначае тып запыту Unicast
11
Client IP address
0.0.0.0
радок
4
IP адрас кліента (калі ёсць)
15
Your client IP address
172.16.134.61
радок
4
IP адрас прапанаваны серверам (калі ёсць)
19
Next server IP address
0.0.0.0
радок
4
IP адрас сервера (калі вядомы)
23
Relay agent IP address
172.16.114.41
радок
4
IP адрас агента рэтрансляцыі (напрыклад свіча)
27
Client MAC address
14:d6:4d:a7:c9:55
Hex
6
MAC адрас адпраўніка пакета (кліента)
31
Client hardware address padding
Hex
10
Зарэзерваванае месца. Звычайна забіта нулямі
41
Server host name
радок
64
Імя сервера DHCP. Звычайна не перадаецца
105
Boot file name
радок
128
Імя файла на серверы, якое выкарыстоўваецца бездыскавымі станцыямі пры загрузцы
235
Magic cookie
63: 82: 53: 63
Hex
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
Boot Request
1
Hex
1
Тып паведамлення. 1 - запыт ад кліента да сервера, 2 - адказ ад сервера кліенту
2
Тып апаратнага забеспячэння
1
Hex
1
Тып апаратнага адраса, у дадзеным пратаколе 1 - MAC
3
Hardware adrees length
6
Hex
1
Даўжыня MAC адрасы прылады
4
Хмель
1
Hex
1
Колькасць прамежкавых маршрутаў
5
Ідэнтыфікацыя здзелкі
23:cf:de:1d
Hex
4
Унікальны ідэнтыфікатар транзакцыі. Генеруе кліент у пачатку аперацыі запыту
7
Second elapsed
0
Hex
4
Час у секундах з пачатку працэсу атрымання адрасу
9
Bootp flags
8000
Hex
2
Некаторыя сцягі, якія могуць усталёўвацца, у якасці ўказання параметраў пратакол. У дадзеным выпадку выстаўлена "бродкаст"
11
Client IP address
0.0.0.0
радок
4
IP адрас кліента (калі ёсць)
15
Your client IP address
172.16.134.61
радок
4
IP адрас прапанаваны серверам (калі ёсць)
19
Next server IP address
0.0.0.0
радок
4
IP адрас сервера (калі вядомы)
23
Relay agent IP address
172.16.114.41
радок
4
IP адрас агента рэтрансляцыі (напрыклад свіча)
27
Client MAC address
14:d6:4d:a7:c9:55
Hex
6
MAC адрас адпраўніка пакета (кліента)
31
Client hardware address padding
Hex
10
Зарэзерваванае месца. Звычайна забіта нулямі
41
Server host name
радок
64
Імя сервера DHCP. Звычайна не перадаецца
105
Boot file name
радок
128
Імя файла на серверы, якое выкарыстоўваецца бездыскавымі станцыямі пры загрузцы
235
Magic cookie
63: 82: 53: 63
Hex
4
"Магічны" лік, па якім у т.л. можна вызначыць, што гэты пакет - належыць пратаколу DHCP
Опцыі DHCP. Могуць ісці ў любым парадку
236
Нумар опцыі
53
снежні
3
Опцыя 53, якая вызначае тып пакета DHCP 3 - DHCPREQUEST
Даўжыня опцыі
1
снежні
1
Значэнне опцыі
3
снежні
1
Нумар опцыі
61
снежні
1
Ідэнтыфікатар кліента: 01 (для Ehernet) + MAC адрас кліента
Даўжыня опцыі
7
снежні
1
Значэнне опцыі
01:2c:ab:25:ff:72:a6
Hex
7
Нумар опцыі
60
снежні
"Vendor class identifier". У маім выпадку спалучае версію DHCP кліента. Магчыма іншыя прылады, вяртаюць нешта іншае. Windows напрыклад паведамляе MSFT 5.0
Даўжыня опцыі
11
снежні
Значэнне опцыі
udhcp 0.9.8
радок
Нумар опцыі
55
1
Запытаныя кліентам сеткавыя параметры. Склад можа быць розным
01 - Маска сеткі
03 - Шлюз
06 - DNS
oc - Імя хаста
0f - імя дамена сеткі
1c - адрас шырокавяшчальнага запыту (бродкаста)
42 - імя сервера TFTP
79 — Classless Static Route
Даўжыня опцыі
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
Boot Request
2
Hex
1
Тып паведамлення. 1 - запыт ад кліента да сервера, 2 - адказ ад сервера кліенту
2
Тып апаратнага забеспячэння
1
Hex
1
Тып апаратнага адраса, у дадзеным пратаколе 1 - MAC
3
Hardware adrees length
6
Hex
1
Даўжыня MAC адрасы прылады
4
Хмель
1
Hex
1
Колькасць прамежкавых маршрутаў
5
Ідэнтыфікацыя здзелкі
23:cf:de:1d
Hex
4
Унікальны ідэнтыфікатар транзакцыі. Генеруе кліент у пачатку аперацыі запыту
7
Second elapsed
0
Hex
4
Час у секундах з пачатку працэсу атрымання адрасу
9
Bootp flags
8000
Hex
2
Некаторыя сцягі, якія могуць усталёўвацца, у якасці ўказання параметраў пратакол. У дадзеным выпадку выстаўлена "бродкаст"
11
Client IP address
0.0.0.0
радок
4
IP адрас кліента (калі ёсць)
15
Your client IP address
172.16.134.61
радок
4
IP адрас прапанаваны серверам (калі ёсць)
19
Next server IP address
0.0.0.0
радок
4
IP адрас сервера (калі вядомы)
23
Relay agent IP address
172.16.114.41
радок
4
IP адрас агента рэтрансляцыі (напрыклад свіча)
27
Client MAC address
14:d6:4d:a7:c9:55
Hex
6
MAC адрас адпраўніка пакета (кліента)
31
Client hardware address padding
Hex
10
Зарэзерваванае месца. Звычайна забіта нулямі
41
Server host name
радок
64
Імя сервера DHCP. Звычайна не перадаецца
105
Boot file name
радок
128
Імя файла на серверы, якое выкарыстоўваецца бездыскавымі станцыямі пры загрузцы
235
Magic cookie
63: 82: 53: 63
Hex
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 ужо ўсталявана і настроена.
Ствараем БД 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 localhost test test 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 select ip,mask,router,dns from users where upper(mac)=upper('{option_3_AgentRemoteId_hex}') and upper(port)=upper('{option_1_AgentCircuitId_port_hex}') select ip,mask,router,dns from users where upper(mac)=upper('{sw_mac}') and upper(port)=upper('{sw_port82}') select ip,mask,router,dns from users where upper(mac)=upper('{ClientMacAddress}') insert in history (id,dt,mac,ip,comment) values (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')
Цяпер падрабязней па тэгах:
Секцыя dhcpserver апісвае асноўныя наладкі для запуску сервера, а менавіта:
host - які ip адрас слухае сервер на порце 67
broadcast - які ip з'яўляецца бродкастам для DHCPOFFER і DHCPACK
DHCPServer - які ip у DHCP сервера
LeaseTime час арэнды выдадзенага ip адраса
ThreadLimit - колькі адначасова патокаў запушчана па апрацоўцы паступілі пакетаў UDP на порце 67. Мяркуецца што дапаможа на высоканагружаных праектах 😉
defaultMask,defaultRouter,defaultDNS — тое, што прапануецца абаненту па змаўчанні, калі IP у базе знойдзены, але дадатковыя параметры для яго не пазначаны
Секцыя mysql:
host,username,password,basename - усё кажа само за сябе. Прыкладная структура базы даных выкладзена на GitHub
Секцыя query: тут апісваюцца запыты для атрымання OFFER/ACK:
offer_count - колькасць радкоў з запытамі якія вяртаюць вынік выгляду ip,mask,router,dns
offer_n - радок запыту. Калі вяртанне - пуста, то выконвае наступны запыт offer
history_sql - запыт пішучы напрыклад у «гісторыю аўтарызацыі» па абаненту
У запытах могуць удзельнічаць любыя зменныя з секцыі options ці опцыі з пратаколу DHCP.
Секцыя options. Вось тут ужо цікавей. Тут мы можам ствараць зменныя якія можам выкарыстоўваць у далейшым у секцыі query.
Напрыклад:
option_82_hex:sw_port1:20:22
, гэтая радок-каманда ўзяць увесь радок якая прыйшла ў DHCP запыце опцыі 82, у фармаце hex, у дыяпазоне з 20 па 22 байт уключна і пакласці яе ў новую зменную sw_port1 (порт свіча адкуль прыйшоў запыт)
option_82_hex:sw_mac:26:40
, апярэджваем зменную sw_mac, узяўшы hex з дыяпазону 26:40
Убачыць усе магчымыя опцыі якія можна выкарыстоўваць у запытах, можна пры дапамозе запуску сервера з ключом -d. Убачым прыкладна такі лог:
Адпаведна мы можам любую зменную абгарнуць у {} і яна будзе выкарыстана ў SQL запыце.
Адлюструем для гісторыі, што IP адрас кліент атрымаў:
Запуск сервера
./pydhcpdb.py -d -c config.xml
- d рэжым вываду ў кансоль DEBUG
- c <імя_файла> канфігурацыйны файл
разбор палётаў
А зараз падрабязней па рэалізацыі сервера на Python. Гэта боль. Python вывучаўся "на лёце". Многія моманты зроблены ў стылі: "ухты, неяк зрабіў што працуе". Зусім не аптымізаваны, і пакінутыя ў такім выглядзе ў асноўным з-за малога досведу распрацоўкі на python. Спынюся на найболей цікавых момантах рэалізацыі сервера ў «кодзе».
Парсер файла канфігурацыі XML
Выкарыстоўваецца стандартны модуль Python xml.dom. Здаецца і проста, але пры рэалізацыі адчувальна не хапала тлумачальнай дакументацыі і прыкладаў у сеткі з выкарыстаннем дадзенага модуля.
tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") для elem in mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["mysql_username"]=elem.getElementsByTagName("username")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("password")[0].firstChild.data gconfig["mysql_basename" =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") для elem in 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].firstChil dhcp_ThreadLimit"]=int(elem.getElementsByTagName("ThreadLimit")[0].firstChild.data) gconfig["dhcp_Server"]=elem.getElementsByTagName("DHCPServer")[0].firstChild.data =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_de defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") для elem in qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.data for range(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("options") : optionsMod.append(options.firstChild.data)
Шматструменнасць
Як ні дзіўна, шматструменнасць у Python рэалізаваная вельмі зразумела і проста.
def PacketWork(data,addr): ... # рэалізацыя разбору які прыйшоў пакета, і адказу на яго ... while True: data, addr = udp_socket.recvfrom(1024) # чакаем пакет UDP thread = threading.Thread(target=PacketWork , args=(data,addr,)).start() # як прыйшоў - запускаем у фоне вызначаную раней функцыю PacketWork з параметрамі while threading.active_count() >gconfig["dhcp_ThreadLimit"]: time.sleep(1) # калі лік ужо запушчаных патокаў больш чым у наладах, чакаем пакуль іх стане менш
Прыём/адпраўка пакета DHCP
Для таго каб перахапіць пакеты UDP ідучыя праз сеткавую карту, трэба "падняць" сокет:
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
Вось тут мне сапраўды спадабаўся Python. Аказваецца з "скрынкі" ён дазваляе даволі вольна абыходзіцца з байт-кодам. Дазваляючы яго вельмі проста пераводзіць у дзесятковыя значэнні, радкі і hex - г.зн. тое што нам уласна і трэба, каб зразумець структуру пакета. Так напрыклад можна атрымаць дыяпазон байт у HEX і проста байтах: