Διακομιστής DHCP+Mysql στην Python

Διακομιστής DHCP+Mysql στην Python

Σκοπός αυτού του έργου ήταν:

  • Εκμάθηση για το DHCP σε δίκτυο IPv4
  • Μαθαίνοντας Python (λίγο περισσότερο από το μηδέν 😉)
  • αντικατάσταση διακομιστή DB2DHCP (το πιρούνι μου), πρωτότυπο εδώ, το οποίο γίνεται όλο και πιο δύσκολο να συναρμολογηθεί για το νέο λειτουργικό σύστημα. Και δεν μου αρέσει που είναι ένα δυαδικό που δεν υπάρχει τρόπος να «αλλάξουμε αυτήν τη στιγμή»
  • απόκτηση ενός λειτουργικού διακομιστή DHCP με δυνατότητα επιλογής της διεύθυνσης IP ενός συνδρομητή χρησιμοποιώντας το συνδυασμό mac ή μεταγωγής mac+port του συνδρομητή (Επιλογή 82)
  • γράφοντας ένα άλλο ποδήλατο (Ω! αυτή είναι η αγαπημένη μου δραστηριότητα)
  • να λαμβάνετε σχόλια σχετικά με την ομαδικότητα σας στο Habrahabr (ή καλύτερα, μια πρόσκληση) 😉

Αποτέλεσμα: λειτουργεί 😉 Δοκιμασμένο σε 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 ότι ο «πελάτης είναι ζωντανός» και χρησιμοποιεί τις εκδοθείσες ρυθμίσεις δικτύου. Στην υλοποίηση αυτού του διακομιστή, αυτά τα πακέτα αγνοούνται.

Μορφή πακέτου

Γενικά, ένα πλαίσιο πακέτων Ethernet μοιάζει κάπως έτσι:

Διακομιστής DHCP+Mysql στην Python

Στην περίπτωσή μας, θα εξετάσουμε μόνο τα δεδομένα απευθείας από τα περιεχόμενα του πακέτου UDP, χωρίς κεφαλίδες πρωτοκόλλου επιπέδου OSI, δηλαδή τη δομή DHCP:

DHCPDISCOVER

Έτσι, η διαδικασία απόκτησης μιας διεύθυνσης IP για μια συσκευή ξεκινά με τον πελάτη DHCP να στέλνει ένα αίτημα μετάδοσης από τη θύρα 68 στη θύρα 255.255.255.255:67. Σε αυτό το πακέτο, ο πελάτης περιλαμβάνει τη διεύθυνση MAC του, καθώς και τι ακριβώς θέλει να λάβει από τον διακομιστή DHCP. Η δομή του πακέτου περιγράφεται στον παρακάτω πίνακα.

Πίνακας Δομής Πακέτων DHCPDISCOVER

Θέση στη συσκευασία
Όνομα τιμής
Παράδειγμα
Εισαγωγή
Byte
διευκρίνιση

1
Αίτημα εκκίνησης
1
Hex
1
Τύπος μηνύματος. 1 - αίτημα από πελάτη σε διακομιστή, 2 - απάντηση από διακομιστή σε πελάτη

2
Τύπος υλικού
1
Hex
1
Τύπος διεύθυνσης υλικού, σε αυτό το πρωτόκολλο 1 - MAC

3
Μήκος διευθύνσεων υλικού
6
Hex
1
Μήκος διεύθυνσης MAC συσκευής

4
Λυκίσκος
1
Hex
1
Αριθμός ενδιάμεσων διαδρομών

5
Ταυτότητα συναλλαγής
23:cf:de:1d
Hex
4
Μοναδικό αναγνωριστικό συναλλαγής. Δημιουργήθηκε από τον πελάτη στην αρχή μιας λειτουργίας αιτήματος

7
Πέρασε το δεύτερο
0
Hex
4
Χρόνος σε δευτερόλεπτα από την έναρξη της διαδικασίας απόκτησης διεύθυνσης

9
Σημαίες μπότας
0
Hex
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
Hex
6
Διεύθυνση MAC του αποστολέα πακέτου (πελάτης)

31
Επένδυση διεύθυνσης υλικού πελάτη
 
Hex
10
Πιασμένη θέση. Συνήθως γεμίζουν με μηδενικά

41
Όνομα κεντρικού υπολογιστή διακομιστή
 
Σειρά
64
Όνομα διακομιστή DHCP. Συνήθως δεν μεταδίδεται

105
Όνομα αρχείου εκκίνησης
 
Σειρά
128
Όνομα αρχείου στον διακομιστή που χρησιμοποιείται από σταθμούς χωρίς δίσκο κατά την εκκίνηση

235
Μαγικά μπισκότα
63: 82: 53: 63
Hex
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 - όνομα τομέα δικτύου
1c - διεύθυνση αιτήματος εκπομπής (μετάδοση)
42 - Όνομα διακομιστή TFTP
79 - Ταξική στατική διαδρομή

 
Μήκος επιλογής
8
 
1

 
Τιμή επιλογής
01:03:06:0c:0f:1c:42:79
 
8

 
Αριθμός επιλογής
82
Δεκέμβριος
 
Επιλογή 82, η οποία μεταδίδει τη διεύθυνση MAC της συσκευής επαναλήπτη και ορισμένες πρόσθετες τιμές.

Τις περισσότερες φορές, αυτή είναι η θύρα του μεταγωγέα στην οποία εκτελείται ο τελικός πελάτης DHCP. Αυτή η επιλογή περιέχει πρόσθετες παραμέτρους. Το πρώτο byte είναι ο αριθμός της "υποεπιλογής", το δεύτερο είναι το μήκος του και μετά η τιμή του.

Σε αυτήν την περίπτωση, στην επιλογή 82, οι υποεπιλογές είναι ένθετες:
Agent Circuit ID = 00:04:00:01:00:04, όπου τα δύο τελευταία byte είναι η θύρα πελάτη 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

Θέση στη συσκευασία
Όνομα αξίας (κοινό)
Παράδειγμα
Εισαγωγή
Byte
διευκρίνιση

1
Αίτημα εκκίνησης
1
Hex
1
Τύπος μηνύματος. 1 - αίτημα από πελάτη σε διακομιστή, 2 - απάντηση από διακομιστή σε πελάτη

2
Τύπος υλικού
1
Hex
1
Τύπος διεύθυνσης υλικού, σε αυτό το πρωτόκολλο 1 - MAC

3
Μήκος διευθύνσεων υλικού
6
Hex
1
Μήκος διεύθυνσης MAC συσκευής

4
Λυκίσκος
1
Hex
1
Αριθμός ενδιάμεσων διαδρομών

5
Ταυτότητα συναλλαγής
23:cf:de:1d
Hex
4
Μοναδικό αναγνωριστικό συναλλαγής. Δημιουργήθηκε από τον πελάτη στην αρχή μιας λειτουργίας αιτήματος

7
Πέρασε το δεύτερο
0
Hex
4
Χρόνος σε δευτερόλεπτα από την έναρξη της διαδικασίας απόκτησης διεύθυνσης

9
Σημαίες μπότας
0
Hex
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
Hex
6
Διεύθυνση MAC του αποστολέα πακέτου (πελάτης)

31
Επένδυση διεύθυνσης υλικού πελάτη
 
Hex
10
Πιασμένη θέση. Συνήθως γεμίζουν με μηδενικά

41
Όνομα κεντρικού υπολογιστή διακομιστή
 
Σειρά
64
Όνομα διακομιστή DHCP. Συνήθως δεν μεταδίδεται

105
Όνομα αρχείου εκκίνησης
 
Σειρά
128
Όνομα αρχείου στον διακομιστή που χρησιμοποιείται από σταθμούς χωρίς δίσκο κατά την εκκίνηση

235
Μαγικά μπισκότα
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

Θέση στη συσκευασία
Όνομα αξίας (κοινό)
Παράδειγμα
Εισαγωγή
Byte
διευκρίνιση

1
Αίτημα εκκίνησης
1
Hex
1
Τύπος μηνύματος. 1 - αίτημα από πελάτη σε διακομιστή, 2 - απάντηση από διακομιστή σε πελάτη

2
Τύπος υλικού
1
Hex
1
Τύπος διεύθυνσης υλικού, σε αυτό το πρωτόκολλο 1 - MAC

3
Μήκος διευθύνσεων υλικού
6
Hex
1
Μήκος διεύθυνσης MAC συσκευής

4
Λυκίσκος
1
Hex
1
Αριθμός ενδιάμεσων διαδρομών

5
Ταυτότητα συναλλαγής
23:cf:de:1d
Hex
4
Μοναδικό αναγνωριστικό συναλλαγής. Δημιουργήθηκε από τον πελάτη στην αρχή μιας λειτουργίας αιτήματος

7
Πέρασε το δεύτερο
0
Hex
4
Χρόνος σε δευτερόλεπτα από την έναρξη της διαδικασίας απόκτησης διεύθυνσης

9
Σημαίες μπότας
8000
Hex
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
Hex
6
Διεύθυνση MAC του αποστολέα πακέτου (πελάτης)

31
Επένδυση διεύθυνσης υλικού πελάτη
 
Hex
10
Πιασμένη θέση. Συνήθως γεμίζουν με μηδενικά

41
Όνομα κεντρικού υπολογιστή διακομιστή
 
Σειρά
64
Όνομα διακομιστή DHCP. Συνήθως δεν μεταδίδεται

105
Όνομα αρχείου εκκίνησης
 
Σειρά
128
Όνομα αρχείου στον διακομιστή που χρησιμοποιείται από σταθμούς χωρίς δίσκο κατά την εκκίνηση

235
Μαγικά μπισκότα
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
Δεκέμβριος
 
"Αναγνωριστικό κλάσης προμηθευτή". Στην περίπτωσή μου, αναφέρει την έκδοση πελάτη DHCP. Ίσως άλλες συσκευές επιστρέφουν κάτι διαφορετικό. Τα Windows για παράδειγμα αναφέρουν το MSFT 5.0

 
Μήκος επιλογής
11
Δεκέμβριος
 

 
Τιμή επιλογής
udhcp 0.9.8
Σειρά
 

 
Αριθμός επιλογής
55
 
1
Παράμετροι δικτύου που ζητούνται από τον πελάτη. Η σύνθεση μπορεί να διαφέρει

01 — Μάσκα δικτύου
03 - Πύλη
06 - DNS
oc — Όνομα κεντρικού υπολογιστή
0f - όνομα τομέα δικτύου
1c - διεύθυνση αιτήματος εκπομπής (μετάδοση)
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

Θέση στη συσκευασία
Όνομα αξίας (κοινό)
Παράδειγμα
Εισαγωγή
Byte
διευκρίνιση

1
Αίτημα εκκίνησης
2
Hex
1
Τύπος μηνύματος. 1 - αίτημα από πελάτη σε διακομιστή, 2 - απάντηση από διακομιστή σε πελάτη

2
Τύπος υλικού
1
Hex
1
Τύπος διεύθυνσης υλικού, σε αυτό το πρωτόκολλο 1 - MAC

3
Μήκος διευθύνσεων υλικού
6
Hex
1
Μήκος διεύθυνσης MAC συσκευής

4
Λυκίσκος
1
Hex
1
Αριθμός ενδιάμεσων διαδρομών

5
Ταυτότητα συναλλαγής
23:cf:de:1d
Hex
4
Μοναδικό αναγνωριστικό συναλλαγής. Δημιουργήθηκε από τον πελάτη στην αρχή μιας λειτουργίας αιτήματος

7
Πέρασε το δεύτερο
0
Hex
4
Χρόνος σε δευτερόλεπτα από την έναρξη της διαδικασίας απόκτησης διεύθυνσης

9
Σημαίες μπότας
8000
Hex
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
Hex
6
Διεύθυνση MAC του αποστολέα πακέτου (πελάτης)

31
Επένδυση διεύθυνσης υλικού πελάτη
 
Hex
10
Πιασμένη θέση. Συνήθως γεμίζουν με μηδενικά

41
Όνομα κεντρικού υπολογιστή διακομιστή
 
Σειρά
64
Όνομα διακομιστή DHCP. Συνήθως δεν μεταδίδεται

105
Όνομα αρχείου εκκίνησης
 
Σειρά
128
Όνομα αρχείου στον διακομιστή που χρησιμοποιείται από σταθμούς χωρίς δίσκο κατά την εκκίνηση

235
Μαγικά μπισκότα
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 είναι ήδη εγκατεστημένη και ρυθμισμένη.

FreeBSD

pkg εγκατάσταση python3 python3 -m surepip pip3 εγκατάσταση mysql-connector

Ubuntu

sudo apt-get εγκατάσταση python3 sudo apt-get εγκατάσταση pip3 sudo pip3 εγκατάσταση mysql-connector

Δημιουργούμε μια βάση δεδομένων 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 δοκιμή δοκιμή 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,mask,router,dns από χρήστες όπου upper(mac)=upper('{option_3_AgentRemoteId_hex}') και upper(port)=upper('{option_1_AgentCircuitId_port_hex}') επιλέξτε ip,mask,router,dns από χρήστες όπου upper(mac)=upper('{sw_mac}') και upper(port)=upper('{sw_port82}') επιλέξτε ip,mask,router,dns από χρήστες όπου upper(mac)=upper('{ClientMacAddress}') εισαγάγετε στο ιστορικό (id,dt,mac,ip,comment) τιμές (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Τώρα πιο αναλυτικά στις ετικέτες:

Η ενότητα dhcpserver περιγράφει τις βασικές ρυθμίσεις για την εκκίνηση του διακομιστή, και συγκεκριμένα:

  • host - ποια διεύθυνση IP ακούει ο διακομιστής στη θύρα 67
  • εκπομπή - ποια ip είναι η μετάδοση για το DHCPOFFER και το DHCPACK
  • DHCPServer - ποια είναι η ip του διακομιστή DHCP
  • Χρόνος μίσθωσης LeaseTime της εκδοθείσας διεύθυνσης IP
  • ThreadLimit - πόσα νήματα εκτελούνται ταυτόχρονα για την επεξεργασία των εισερχόμενων πακέτων UDP στη θύρα 67. Υποτίθεται ότι βοηθά σε έργα υψηλού φορτίου 😉
  • defaultMask,defaultRouter,defaultDNS - τι προσφέρεται στον συνδρομητή από προεπιλογή εάν βρεθεί IP στη βάση δεδομένων, αλλά δεν καθορίζονται πρόσθετες παράμετροι για αυτό

ενότητα mysql:

κεντρικός υπολογιστής, όνομα χρήστη, κωδικός πρόσβασης, όνομα βάσης - όλα μιλούν από μόνα τους. Αναρτάται μια κατά προσέγγιση δομή βάσης δεδομένων GitHub

Ενότητα ερωτήματος: τα αιτήματα για λήψη ΠΡΟΣΦΟΡΑΣ/ΕΠΙΔΕΞΗΣ περιγράφονται εδώ:

  • offer_count — ο αριθμός των γραμμών με αιτήματα που επιστρέφουν αποτέλεσμα όπως ip, mask, router, dns
  • offer_n — συμβολοσειρά ερωτήματος. Εάν η επιστροφή είναι κενή, τότε εκτελεί το ακόλουθο αίτημα προσφοράς
  • history_sql - ένα ερώτημα που γράφει, για παράδειγμα, στο "ιστορικό εξουσιοδότησης" για έναν συνδρομητή

Τα αιτήματα μπορούν να περιλαμβάνουν οποιεσδήποτε μεταβλητές από την ενότητα επιλογών ή επιλογές από το πρωτόκολλο DHCP.

Ενότητα επιλογών. Εδώ είναι που γίνεται πιο ενδιαφέρον. Εδώ μπορούμε να δημιουργήσουμε μεταβλητές που μπορούμε να χρησιμοποιήσουμε αργότερα στην ενότητα ερωτημάτων.

Για παράδειγμα:

option_82_hex:sw_port1:20:22

, αυτή η γραμμή εντολών παίρνει ολόκληρη τη γραμμή που ήρθε στην επιλογή αιτήματος DHCP 82, σε δεκαεξαδική μορφή, στην περιοχή από 20 έως 22 byte συμπεριλαμβανομένων και τη βάζει στη νέα μεταβλητή 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': '764yMacdress': '00ClientMacdress': '7yMac 91 5%"Jxd0d" , 'HType': 'Ethernet', 'HostName': b'x3xa5xe9xa8xa8xa43-x0.0.0.0fx5.0a', 'ReqListDNS': True, 'ReqListDomainName': True, 'ReqListPerfowmRouterDiscover':TrueqLuteRout': TrueRouter'ReqLute, Αλήθεια, 'ReqListSubnetM ask ': True, 'ReqListVendorSpecInfo': 0025224, 'RequestedIpAddress': '764', 'Vendor': b'MSFT 172.30.128.13', 'chaddr': '00ad00', '172.30.114.25r': '308. , 'flags': b'x6x1', 'giaddr': '82', 'gpoz': 12, 'hlen': 12, 'hops': 53, 'htype': 'MAC', 'magic_cookie': b'cx53Sc ', 'op': 'DHCPINFORM', 'option55': 55, 'option60': 60, 'option61': 61, 'option82': 82, 'option82': 12, 'option01': 06, ' option_00_byte': b'x04x00x01x00x06x02x08x00x06x00x1x9' b'x2x82x12010600040001000602080006001eXx589exb2xad', 'option_82_hex': '18 _82_len': 12 01, 'option_06_str': "b'x00x04x00x01x00x06x02x08x00x06x00x1x9x2x768eXx0.0.0.0exb001xad", "αποτέλεσμα": False, "secs": 589 'siaddr': '2', 'sw_mac': '1e06eb89ad', 'sw_port8': '3', 'xidbyte': b'

Αντίστοιχα, μπορούμε να τυλίξουμε οποιαδήποτε μεταβλητή στο {} και θα χρησιμοποιηθεί στο ερώτημα SQL.

Ας καταγράψουμε για το ιστορικό ότι ο πελάτης έλαβε τη διεύθυνση IP:

Διακομιστής DHCP+Mysql στην Python

Διακομιστής DHCP+Mysql στην Python

Έναρξη διακομιστή

./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") για το στοιχείο στο mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].dast gconfig["mysql_username"]=elem.getElementsByTagName("username")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("password")[0].first"sqlconfige"my. =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") για το στοιχείο στο dconfig: gconfig["broadcast"]=elem.getElementsByTagName. firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["dhcp_LeaseTime"]=elem.getElementsByTagName("LeaseTime")[0]config. dhcp_ThreadLimit"]=int(elem.getElementsByTagName("ThreadLimit")[0].firstChild.data) gconfig["dhcp_Server"]=elem.getElementsByTagName("DHCPServer")[0]configd]deff. =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig[=element. " defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") για το στοιχείο στο qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild in.data για num range(int(gconfig["offer_count"]): gconfig["offer_"+str(num+0)]=elem.getElementsByTagName("offer_"+str(αριθμός+1))[1].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[0].firstChild.data options=tree.getElementsByTagName("options") για το στοιχείο στις επιλογές: node=elem.getElementsByTagName")(options : optionsMod.append(options.firstChild.data)

Multithreading

Παραδόξως, το multithreading στην Python υλοποιείται πολύ καθαρά και απλά.

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"]: χρόνος. sleep(1) # if the number Υπάρχουν ήδη περισσότερα νήματα που εκτελούνται από ό,τι στις ρυθμίσεις, περιμένουμε μέχρι να υπάρξουν λιγότερα από αυτά

Λήψη/αποστολή πακέτου 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: port. Μπορεί επίσης να υπάρχει AF_UNIX - όπου η διεύθυνση δίνεται από το όνομα του αρχείου.
  • SOCK_DGRAM - σημαίνει ότι δεν δεχόμαστε ένα "ακατέργαστο πακέτο", αλλά ένα που έχει ήδη περάσει από το τείχος προστασίας και με ένα μερικώς κομμένο πακέτο. Εκείνοι. λαμβάνουμε μόνο ένα πακέτο UDP χωρίς το "φυσικό" στοιχείο του περιτυλίγματος πακέτου UDP. Εάν χρησιμοποιείτε τη σημαία SOCK_RAW, τότε θα πρέπει επίσης να αναλύσετε αυτό το "περιτύλιγμα".

Η αποστολή ενός πακέτου μπορεί να είναι σαν μια μετάδοση:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #switch the socket σε λειτουργία μετάδοσης 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. Αποδεικνύεται ότι από το κουτί σας επιτρέπει να είστε αρκετά ευέλικτοι με τον bytecode. Επιτρέποντάς του να μεταφραστεί πολύ εύκολα σε δεκαδικές τιμές, συμβολοσειρές και εξάγωνο - δηλ. Αυτό είναι που πραγματικά χρειαζόμαστε για να κατανοήσουμε τη δομή του πακέτου. Έτσι, για παράδειγμα, μπορείτε να λάβετε μια σειρά από byte σε HEX και μόνο byte:

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

, συσκευάστε τα byte σε μια δομή:

res["flags"]=pack('BB',data[10],data[11])

Λήψη IP από τη δομή:

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

Και αντίστροφα:

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

Αυτά προς το παρόν 😉

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο