thay thế máy chủ DB2DHCP (cái nĩa của tôi), bản gốc đây, ngày càng khó lắp ráp cho hệ điều hành mới. Và tôi không thích đó là một hệ nhị phân mà không có cách nào để “thay đổi ngay bây giờ”
có được một máy chủ DHCP đang hoạt động với khả năng chọn địa chỉ IP của người đăng ký bằng cách sử dụng máy mac của người đăng ký hoặc kết hợp cổng mac+switch (Tùy chọn 82)
viết một chiếc xe đạp khác (Ồ! đây là hoạt động yêu thích của tôi)
nhận được nhận xét về việc bạn ủng hộ câu lạc bộ trên Habrahabr (hoặc tốt hơn là lời mời) 😉
Kết quả: nó hoạt động 😉 Đã thử nghiệm trên FreeBSD và Ubuntu OS. Về mặt lý thuyết, mã có thể được yêu cầu hoạt động trong bất kỳ hệ điều hành nào, bởi vì Dường như không có ràng buộc cụ thể nào trong mã.
Cẩn thận! Còn rất nhiều điều nữa sẽ đến.
Link kho cho người nghiệp dư "chạm sống".
Quá trình cài đặt, cấu hình và sử dụng kết quả “nghiên cứu phần cứng” thấp hơn rất nhiều, sau đó là một chút lý thuyết về giao thức DHCP. Cho bản thân mình. Và vì lịch sử 😉
Một chút lý thuyết
DHCP là gì
Đây là giao thức mạng cho phép thiết bị tìm ra địa chỉ IP của nó (và các thông số khác như cổng, DNS, v.v.) từ máy chủ DHCP. Các gói được trao đổi bằng giao thức UDP. Nguyên lý hoạt động chung của thiết bị khi yêu cầu thông số mạng như sau:
Thiết bị (máy khách) gửi yêu cầu phát sóng UDP (DHCPDISCOVER) trên toàn mạng với yêu cầu “à, ai đó cho tôi địa chỉ IP”. Hơn nữa, thông thường (nhưng không phải luôn luôn) yêu cầu xảy ra từ cổng 68 (nguồn) và đích là cổng 67 (đích). Một số thiết bị cũng gửi gói từ cổng 67. Địa chỉ MAC của thiết bị khách được bao gồm trong gói DHCPDISCOVER.
Tất cả các máy chủ DHCP nằm trên mạng (và có thể có một số máy chủ trong số đó) tạo thành ưu đãi DHCPOFFER với cài đặt mạng cho thiết bị đã gửi DHCPDISCOVER và cũng phát nó qua mạng. Việc xác định gói tin này dành cho ai dựa trên địa chỉ MAC của máy khách được cung cấp trước đó trong yêu cầu DHCPDISCOVER.
Máy khách chấp nhận các gói có đề xuất về cài đặt mạng, chọn gói hấp dẫn nhất (tiêu chí có thể khác nhau, ví dụ: thời gian gửi gói, số lượng tuyến trung gian) và đưa ra “yêu cầu chính thức” DHCPREQUEST với cài đặt mạng từ máy chủ DHCP mà nó thích. Trong trường hợp này, gói sẽ đến một máy chủ DHCP cụ thể.
Máy chủ đã nhận được DHCPREQUEST sẽ gửi gói định dạng DHCPACK, trong đó nó một lần nữa liệt kê các cài đặt mạng dành cho máy khách này
Ngoài ra, còn có các gói DHCPINFORM đến từ máy khách và mục đích của nó là thông báo cho máy chủ DHCP rằng “máy khách vẫn hoạt động” và đang sử dụng cài đặt mạng đã cấp. Trong quá trình triển khai của máy chủ này, các gói này bị bỏ qua.
Định dạng gói
Nói chung, khung gói Ethernet trông giống như thế này:
Trong trường hợp của chúng tôi, chúng tôi sẽ chỉ xem xét dữ liệu trực tiếp từ nội dung của gói UDP mà không có tiêu đề giao thức lớp OSI, cụ thể là cấu trúc DHCP:
DHCP KHÁM PHÁ
Vì vậy, quá trình lấy địa chỉ IP cho thiết bị bắt đầu bằng việc máy khách DHCP gửi yêu cầu quảng bá từ cổng 68 đến 255.255.255.255:67. Trong gói này, máy khách bao gồm địa chỉ MAC của nó cũng như chính xác những gì nó muốn nhận từ máy chủ DHCP. Cấu trúc gói được mô tả trong bảng dưới đây.
Bảng cấu trúc gói DHCPDISCOVER
Vị trí trong gói
Tên giá trị
Ví dụ
Giới thiệu
Byte
làm rõ
1
Yêu cầu khởi động
1
Hex
1
Loại tin nhắn. 1 - yêu cầu từ máy khách đến máy chủ, 2 - phản hồi từ máy chủ đến máy khách
2
Loại phần cứng
1
Hex
1
Loại địa chỉ phần cứng, trong giao thức này 1 - MAC
3
Độ dài địa chỉ phần cứng
6
Hex
1
Độ dài địa chỉ MAC của thiết bị
4
Nhảy
1
Hex
1
Số lượng tuyến trung gian
5
ID giao dịch
23:cf:de:1d
Hex
4
Mã định danh giao dịch duy nhất. Được tạo bởi khách hàng khi bắt đầu thao tác yêu cầu
7
Thứ hai trôi qua
0
Hex
4
Thời gian tính bằng giây kể từ khi bắt đầu quá trình lấy địa chỉ
9
Cờ khởi động
0
Hex
2
Một số cờ nhất định có thể được đặt để biểu thị các tham số giao thức
11
Địa chỉ IP của khách hàng
0.0.0.0
Chuỗi
4
Địa chỉ IP của khách hàng (nếu có)
15
Địa chỉ IP khách hàng của bạn
0.0.0.0
Chuỗi
4
Địa chỉ IP do máy chủ cung cấp (nếu có)
19
Địa chỉ IP máy chủ tiếp theo
0.0.0.0
Chuỗi
4
Địa chỉ IP máy chủ (nếu biết)
23
Địa chỉ IP của đại lý chuyển tiếp
172.16.114.41
Chuỗi
4
Địa chỉ IP của tác nhân chuyển tiếp (ví dụ: bộ chuyển mạch)
27
Địa chỉ MAC của khách hàng
14:d6:4d:a7:c9:55
Hex
6
Địa chỉ MAC của người gửi gói (máy khách)
31
Đệm địa chỉ phần cứng của máy khách
Hex
10
Đã đặt chỗ. Thường chứa đầy số không
41
Tên máy chủ của máy chủ
Chuỗi
64
Tên máy chủ DHCP. Thường không được truyền
105
Tên tập tin khởi động
Chuỗi
128
Tên tệp trên máy chủ được sử dụng bởi các trạm không cần đĩa khi khởi động
235
Bánh quy ma thuật
63: 82: 53: 63
Hex
4
Con số "ma thuật", theo đó, bao gồm. bạn có thể xác định rằng gói này thuộc về giao thức DHCP
Tùy chọn DHCP. Có thể đi theo thứ tự bất kỳ
236
Số tùy chọn
53
Dec
1
Tùy chọn 53, chỉ định loại gói DHCP
Số tùy chọn
50
Dec
1
Khách hàng muốn nhận địa chỉ IP nào?
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
172.16.134.61
Chuỗi
4
Số tùy chọn
55
1
Các thông số mạng được khách hàng yêu cầu. Thành phần có thể thay đổi
01 — Mặt nạ mạng
03 - Cổng vào
06 - DNS
oc - Tên máy chủ
0f - tên miền mạng
1c - địa chỉ yêu cầu phát sóng (broadcast)
42 - Tên máy chủ TFTP
79 - Tuyến tĩnh không phân lớp
Độ dài tùy chọn
8
1
Giá trị tùy chọn
01:03:06:0c:0f:1c:42:79
8
Số tùy chọn
82
Dec
Tùy chọn 82, truyền địa chỉ MAC của thiết bị lặp lại và một số giá trị bổ sung.
Thông thường, đây là cổng của bộ chuyển mạch mà máy khách DHCP cuối chạy. Tùy chọn này chứa các tham số bổ sung... Byte đầu tiên là số của "tùy chọn phụ", byte thứ hai là độ dài của nó, sau đó là giá trị của nó.
Trong trường hợp này, trong tùy chọn 82, các tùy chọn phụ được lồng vào nhau:
ID mạch tác nhân = 00:04:00:01:00:04, trong đó hai byte cuối cùng là cổng máy khách DHCP nơi yêu cầu được gửi đến
Agent Remote ID = 00:06:c8:be:19:93:11:48 - Địa chỉ MAC của thiết bị lặp DHCP
Độ dài tùy chọn
18
Dec
Giá trị tùy chọn
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
Kết thúc gói
255
Dec
1
255 tượng trưng cho sự kết thúc của gói
DẠY DHCP
Ngay sau khi máy chủ nhận được gói DHCPDISCOVER và nếu nó thấy rằng nó có thể cung cấp cho máy khách thứ gì đó từ gói được yêu cầu thì nó sẽ tạo phản hồi cho gói đó - DHCPDISCOVER. Phản hồi được gửi đến cổng "từ nơi nó đến", bằng cách phát sóng, bởi vì tại thời điểm này, máy khách chưa có địa chỉ IP nên nó chỉ có thể chấp nhận gói nếu nó được gửi bằng phương thức phát sóng. Khách hàng nhận ra rằng đây là gói dành cho mình bằng địa chỉ MAC bên trong gói, cũng như số giao dịch mà anh ta tạo tại thời điểm gói đầu tiên được tạo.
Bảng cấu trúc gói DHCPOFFER
Vị trí trong gói
Tên giá trị (phổ biến)
Ví dụ
Giới thiệu
Byte
làm rõ
1
Yêu cầu khởi động
1
Hex
1
Loại tin nhắn. 1 - yêu cầu từ máy khách đến máy chủ, 2 - phản hồi từ máy chủ đến máy khách
2
Loại phần cứng
1
Hex
1
Loại địa chỉ phần cứng, trong giao thức này 1 - MAC
3
Độ dài địa chỉ phần cứng
6
Hex
1
Độ dài địa chỉ MAC của thiết bị
4
Nhảy
1
Hex
1
Số lượng tuyến trung gian
5
ID giao dịch
23:cf:de:1d
Hex
4
Mã định danh giao dịch duy nhất. Được tạo bởi khách hàng khi bắt đầu thao tác yêu cầu
7
Thứ hai trôi qua
0
Hex
4
Thời gian tính bằng giây kể từ khi bắt đầu quá trình lấy địa chỉ
9
Cờ khởi động
0
Hex
2
Một số cờ nhất định có thể được đặt để biểu thị các tham số giao thức. Trong trường hợp này, 0 có nghĩa là loại yêu cầu Unicast
11
Địa chỉ IP của khách hàng
0.0.0.0
Chuỗi
4
Địa chỉ IP của khách hàng (nếu có)
15
Địa chỉ IP khách hàng của bạn
172.16.134.61
Chuỗi
4
Địa chỉ IP do máy chủ cung cấp (nếu có)
19
Địa chỉ IP máy chủ tiếp theo
0.0.0.0
Chuỗi
4
Địa chỉ IP máy chủ (nếu biết)
23
Địa chỉ IP của đại lý chuyển tiếp
172.16.114.41
Chuỗi
4
Địa chỉ IP của tác nhân chuyển tiếp (ví dụ: bộ chuyển mạch)
27
Địa chỉ MAC của khách hàng
14:d6:4d:a7:c9:55
Hex
6
Địa chỉ MAC của người gửi gói (máy khách)
31
Đệm địa chỉ phần cứng của máy khách
Hex
10
Đã đặt chỗ. Thường chứa đầy số không
41
Tên máy chủ của máy chủ
Chuỗi
64
Tên máy chủ DHCP. Thường không được truyền
105
Tên tập tin khởi động
Chuỗi
128
Tên tệp trên máy chủ được sử dụng bởi các trạm không cần đĩa khi khởi động
235
Bánh quy ma thuật
63: 82: 53: 63
Hex
4
Con số "ma thuật", theo đó, bao gồm. bạn có thể xác định rằng gói này thuộc về giao thức DHCP
Tùy chọn DHCP. Có thể đi theo thứ tự bất kỳ
236
Số tùy chọn
53
Dec
1
Tùy chọn 53, xác định loại gói DHCP 2 - DHCPOFFER
Độ dài tùy chọn
1
Dec
1
Giá trị tùy chọn
2
Dec
1
Số tùy chọn
1
Dec
1
Tùy chọn cung cấp cho máy khách DHCP một mặt nạ mạng
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
255.255.224.0
Chuỗi
4
Số tùy chọn
3
Dec
1
Tùy chọn cung cấp cho máy khách DHCP một cổng mặc định
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
172.16.12.1
Chuỗi
4
Số tùy chọn
6
Dec
1
Tùy chọn cung cấp DHCP cho máy khách DNS
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
8.8.8.8
Chuỗi
4
Số tùy chọn
51
Dec
1
Thời gian tồn tại của các tham số mạng đã ban hành tính bằng giây, sau đó máy khách DHCP phải yêu cầu lại chúng
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
86400
Dec
4
Số tùy chọn
82
Dec
1
Tùy chọn 82, lặp lại những gì có trong DHCPDISCOVER
Độ dài tùy chọn
18
Dec
1
Giá trị tùy chọn
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4ngày:ec
Dec
18
Kết thúc gói
255
Dec
1
255 tượng trưng cho sự kết thúc của gói
YÊU CẦU DHCP
Sau khi khách hàng nhận được DHCPOFFER, anh ta tạo một gói yêu cầu các tham số mạng không phải tới tất cả các máy chủ DHCP trên mạng mà chỉ đến một máy chủ cụ thể mà DHCPOFFER cung cấp mà anh ta “thích” nhất. Tiêu chí "thích" có thể khác nhau và tùy thuộc vào việc triển khai DHCP của máy khách. Người nhận yêu cầu được chỉ định bằng địa chỉ MAC của máy chủ DHCP. Ngoài ra, gói DHCPREQUEST có thể được gửi bởi máy khách mà không cần tạo DHCPDISCOVER trước, nếu địa chỉ IP của máy chủ đã được lấy trước đó.
Bảng cấu trúc gói DHCPREQUEST
Vị trí trong gói
Tên giá trị (phổ biến)
Ví dụ
Giới thiệu
Byte
làm rõ
1
Yêu cầu khởi động
1
Hex
1
Loại tin nhắn. 1 - yêu cầu từ máy khách đến máy chủ, 2 - phản hồi từ máy chủ đến máy khách
2
Loại phần cứng
1
Hex
1
Loại địa chỉ phần cứng, trong giao thức này 1 - MAC
3
Độ dài địa chỉ phần cứng
6
Hex
1
Độ dài địa chỉ MAC của thiết bị
4
Nhảy
1
Hex
1
Số lượng tuyến trung gian
5
ID giao dịch
23:cf:de:1d
Hex
4
Mã định danh giao dịch duy nhất. Được tạo bởi khách hàng khi bắt đầu thao tác yêu cầu
7
Thứ hai trôi qua
0
Hex
4
Thời gian tính bằng giây kể từ khi bắt đầu quá trình lấy địa chỉ
9
Cờ khởi động
8000
Hex
2
Một số cờ nhất định có thể được đặt để biểu thị các tham số giao thức. Trong trường hợp này, "phát sóng" được thiết lập
11
Địa chỉ IP của khách hàng
0.0.0.0
Chuỗi
4
Địa chỉ IP của khách hàng (nếu có)
15
Địa chỉ IP khách hàng của bạn
172.16.134.61
Chuỗi
4
Địa chỉ IP do máy chủ cung cấp (nếu có)
19
Địa chỉ IP máy chủ tiếp theo
0.0.0.0
Chuỗi
4
Địa chỉ IP máy chủ (nếu biết)
23
Địa chỉ IP của đại lý chuyển tiếp
172.16.114.41
Chuỗi
4
Địa chỉ IP của tác nhân chuyển tiếp (ví dụ: bộ chuyển mạch)
27
Địa chỉ MAC của khách hàng
14:d6:4d:a7:c9:55
Hex
6
Địa chỉ MAC của người gửi gói (máy khách)
31
Đệm địa chỉ phần cứng của máy khách
Hex
10
Đã đặt chỗ. Thường chứa đầy số không
41
Tên máy chủ của máy chủ
Chuỗi
64
Tên máy chủ DHCP. Thường không được truyền
105
Tên tập tin khởi động
Chuỗi
128
Tên tệp trên máy chủ được sử dụng bởi các trạm không cần đĩa khi khởi động
235
Bánh quy ma thuật
63: 82: 53: 63
Hex
4
Con số "ma thuật", theo đó, bao gồm. bạn có thể xác định rằng gói này thuộc về giao thức DHCP
Tùy chọn DHCP. Có thể đi theo thứ tự bất kỳ
236
Số tùy chọn
53
Dec
3
Tùy chọn 53, xác định loại gói DHCP 3 - DHCPREQUEST
Độ dài tùy chọn
1
Dec
1
Giá trị tùy chọn
3
Dec
1
Số tùy chọn
61
Dec
1
ID khách hàng: 01 (đối với Ehernet) + địa chỉ MAC của khách hàng
Độ dài tùy chọn
7
Dec
1
Giá trị tùy chọn
01:2c:ab:25:ff:72:a6
Hex
7
Số tùy chọn
60
Dec
"Mã định danh lớp nhà cung cấp". Trong trường hợp của tôi, nó báo cáo phiên bản máy khách DHCP. Có lẽ các thiết bị khác trả về một cái gì đó khác. Ví dụ: Windows báo cáo MSFT 5.0
Độ dài tùy chọn
11
Dec
Giá trị tùy chọn
udhcp 0.9.8
Chuỗi
Số tùy chọn
55
1
Các thông số mạng được khách hàng yêu cầu. Thành phần có thể thay đổi
01 — Mặt nạ mạng
03 - Cổng vào
06 - DNS
oc - Tên máy chủ
0f - tên miền mạng
1c - địa chỉ yêu cầu phát sóng (broadcast)
42 - Tên máy chủ TFTP
79 - Tuyến tĩnh không phân lớp
Độ dài tùy chọn
8
1
Giá trị tùy chọn
01:03:06:0c:0f:1c:42:79
8
Số tùy chọn
82
Dec
1
Tùy chọn 82, lặp lại những gì có trong DHCPDISCOVER
Độ dài tùy chọn
18
Dec
1
Giá trị tùy chọn
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4ngày:ec
Dec
18
Kết thúc gói
255
Dec
1
255 tượng trưng cho sự kết thúc của gói
DHCPACK
Khi xác nhận rằng “vâng, đúng vậy, đây là địa chỉ IP của bạn và tôi sẽ không cung cấp nó cho bất kỳ ai khác” từ máy chủ DHCP, một gói ở định dạng DHCPACK từ máy chủ đến máy khách sẽ được phân phối. Nó được gửi phát sóng giống như các gói khác. Mặc dù, trong mã bên dưới dành cho máy chủ DHCP được triển khai bằng Python, để đề phòng, tôi sao chép bất kỳ yêu cầu phát sóng nào bằng cách gửi gói đến một IP máy khách cụ thể, nếu nó đã được biết. Hơn nữa, máy chủ DHCP hoàn toàn không quan tâm liệu gói DHCPACK có đến được máy khách hay không. Nếu máy khách không nhận được DHCPACK thì sau một thời gian nó chỉ lặp lại DHCPREQUEST
Bảng cấu trúc gói DHCPACK
Vị trí trong gói
Tên giá trị (phổ biến)
Ví dụ
Giới thiệu
Byte
làm rõ
1
Yêu cầu khởi động
2
Hex
1
Loại tin nhắn. 1 - yêu cầu từ máy khách đến máy chủ, 2 - phản hồi từ máy chủ đến máy khách
2
Loại phần cứng
1
Hex
1
Loại địa chỉ phần cứng, trong giao thức này 1 - MAC
3
Độ dài địa chỉ phần cứng
6
Hex
1
Độ dài địa chỉ MAC của thiết bị
4
Nhảy
1
Hex
1
Số lượng tuyến trung gian
5
ID giao dịch
23:cf:de:1d
Hex
4
Mã định danh giao dịch duy nhất. Được tạo bởi khách hàng khi bắt đầu thao tác yêu cầu
7
Thứ hai trôi qua
0
Hex
4
Thời gian tính bằng giây kể từ khi bắt đầu quá trình lấy địa chỉ
9
Cờ khởi động
8000
Hex
2
Một số cờ nhất định có thể được đặt để biểu thị các tham số giao thức. Trong trường hợp này, "phát sóng" được thiết lập
11
Địa chỉ IP của khách hàng
0.0.0.0
Chuỗi
4
Địa chỉ IP của khách hàng (nếu có)
15
Địa chỉ IP khách hàng của bạn
172.16.134.61
Chuỗi
4
Địa chỉ IP do máy chủ cung cấp (nếu có)
19
Địa chỉ IP máy chủ tiếp theo
0.0.0.0
Chuỗi
4
Địa chỉ IP máy chủ (nếu biết)
23
Địa chỉ IP của đại lý chuyển tiếp
172.16.114.41
Chuỗi
4
Địa chỉ IP của tác nhân chuyển tiếp (ví dụ: bộ chuyển mạch)
27
Địa chỉ MAC của khách hàng
14:d6:4d:a7:c9:55
Hex
6
Địa chỉ MAC của người gửi gói (máy khách)
31
Đệm địa chỉ phần cứng của máy khách
Hex
10
Đã đặt chỗ. Thường chứa đầy số không
41
Tên máy chủ của máy chủ
Chuỗi
64
Tên máy chủ DHCP. Thường không được truyền
105
Tên tập tin khởi động
Chuỗi
128
Tên tệp trên máy chủ được sử dụng bởi các trạm không cần đĩa khi khởi động
235
Bánh quy ma thuật
63: 82: 53: 63
Hex
4
Con số "ma thuật", theo đó, bao gồm. bạn có thể xác định rằng gói này thuộc về giao thức DHCP
Tùy chọn DHCP. Có thể đi theo thứ tự bất kỳ
236
Số tùy chọn
53
Dec
3
Tùy chọn 53, xác định loại gói DHCP 5 - DHCPACK
Độ dài tùy chọn
1
Dec
1
Giá trị tùy chọn
5
Dec
1
Số tùy chọn
1
Dec
1
Tùy chọn cung cấp cho máy khách DHCP một mặt nạ mạng
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
255.255.224.0
Chuỗi
4
Số tùy chọn
3
Dec
1
Tùy chọn cung cấp cho máy khách DHCP một cổng mặc định
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
172.16.12.1
Chuỗi
4
Số tùy chọn
6
Dec
1
Tùy chọn cung cấp DHCP cho máy khách DNS
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
8.8.8.8
Chuỗi
4
Số tùy chọn
51
Dec
1
Thời gian tồn tại của các tham số mạng đã ban hành tính bằng giây, sau đó máy khách DHCP phải yêu cầu lại chúng
Độ dài tùy chọn
4
Dec
1
Giá trị tùy chọn
86400
Dec
4
Số tùy chọn
82
Dec
1
Tùy chọn 82, lặp lại những gì có trong DHCPDISCOVER
Độ dài tùy chọn
18
Dec
1
Giá trị tùy chọn
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4ngày:ec
Dec
18
Kết thúc gói
255
Dec
1
255 tượng trưng cho sự kết thúc của gói
Cài đặt
Quá trình cài đặt thực sự bao gồm việc cài đặt các mô-đun python cần thiết cho công việc. Giả định rằng MySQL đã được cài đặt và cấu hình.
FreeBSD
pkg cài đặt python3 python3 -m đảm bảopip pip3 cài đặt trình kết nối mysql
Ubuntu
sudo apt-get cài đặt python3 sudo apt-get cài đặt pip3 sudo pip3 cài đặt kết nối mysql
Chúng tôi tạo cơ sở dữ liệu MySQL, tải kết xuất pydhcp.sql vào đó và định cấu hình tệp cấu hình.
Cấu hình
Tất cả cài đặt máy chủ đều nằm trong tệp xml. Tệp tham khảo:
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 Bài kiểm tra Bài kiểm tra 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 chọn ip,mask,router,dns từ những người dùng trong đó Upper(mac)=upper('{option_3_AgentRemoteId_hex}') và Upper(port)=upper('{option_1_AgentCircuitId_port_hex}') chọn ip,mask,router,dns từ những người dùng trong đó Upper(mac)=upper('{sw_mac}') và Upper(port)=upper('{sw_port82}') chọn ip,mask,router,dns từ người dùng trong đó Upper(mac)=upper('{ClientMacAddress}') chèn vào các giá trị lịch sử (id,dt,mac,ip,comment) (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')
Bây giờ chi tiết hơn về các thẻ:
Phần dhcpserver mô tả các cài đặt cơ bản để khởi động máy chủ, cụ thể là:
máy chủ - địa chỉ IP mà máy chủ nghe trên cổng 67
phát sóng - ip nào được phát cho DHCPOFFER và DHCPACK
DHCPServer - ip của máy chủ DHCP là gì
LeaseTime Thời gian thuê của địa chỉ IP đã cấp
ThreadLimit - có bao nhiêu luồng đang chạy đồng thời để xử lý các gói UDP đến trên cổng 67. Nó được cho là sẽ trợ giúp cho các dự án có tải trọng cao 😉
defaultMask,defaultRouter,defaultDNS - những gì được cung cấp cho người đăng ký theo mặc định nếu tìm thấy IP trong cơ sở dữ liệu, nhưng các tham số bổ sung không được chỉ định cho nó
phần mysql:
máy chủ, tên người dùng, mật khẩu, tên cơ sở - mọi thứ đều tự nói lên điều đó. Cấu trúc cơ sở dữ liệu gần đúng được đăng trên GitHub
Phần truy vấn: các yêu cầu nhận ƯU ĐÃI/ACK được mô tả tại đây:
Offer_count - số dòng có yêu cầu trả về kết quả như ip,mask,router,dns
Offer_n - chuỗi truy vấn. Nếu trả về trống thì thực hiện yêu cầu ưu đãi sau
history_sql - một truy vấn ghi, ví dụ: vào "lịch sử ủy quyền" cho người đăng ký
Yêu cầu có thể bao gồm bất kỳ biến nào từ phần tùy chọn hoặc tùy chọn từ giao thức DHCP.
Phần tùy chọn. Đây là nơi nó trở nên thú vị hơn. Ở đây chúng ta có thể tạo các biến mà chúng ta có thể sử dụng sau này trong phần truy vấn.
Ví dụ:
option_82_hex:sw_port1:20:22
, dòng lệnh này lấy toàn bộ dòng có trong tùy chọn yêu cầu DHCP 82, ở định dạng hex, trong phạm vi từ 20 đến 22 byte và đặt nó vào biến mới sw_port1 (chuyển cổng từ nơi yêu cầu đến)
option_82_hex:sw_mac:26:40
, xác định biến sw_mac, lấy hex từ phạm vi 26:40
Bạn có thể xem tất cả các tùy chọn có thể được sử dụng trong truy vấn bằng cách khởi động máy chủ bằng khóa chuyển -d. Chúng ta sẽ thấy một cái gì đó giống như nhật ký này:
Theo đó, chúng ta có thể gói bất kỳ biến nào trong {} và biến đó sẽ được sử dụng trong truy vấn SQL.
Hãy để chúng tôi ghi lại lịch sử mà khách hàng đã nhận được địa chỉ IP:
Khởi động máy chủ
./pydhcpdb.py -d -c config.xml
— d chế độ đầu ra của bảng điều khiển DEBUG
- c <filename> file cấu hình
Cuộc phỏng vấn
Và bây giờ là thông tin chi tiết hơn về cách triển khai máy chủ bằng Python. Đó là một nỗi đau. Python đã được học một cách nhanh chóng. Nhiều khoảnh khắc được thực hiện theo kiểu “ôi, bằng cách nào đó tôi đã làm được điều đó”. Không được tối ưu hóa chút nào và ở dạng này chủ yếu là do có ít kinh nghiệm phát triển Python. Tôi sẽ tập trung vào những khía cạnh thú vị nhất của việc triển khai máy chủ trong “mã”.
Trình phân tích cú pháp tệp cấu hình XML
Mô-đun Python tiêu chuẩn xml.dom được sử dụng. Nó có vẻ đơn giản, nhưng trong quá trình triển khai, rõ ràng là thiếu tài liệu và ví dụ rõ ràng trên mạng sử dụng mô-đun này.
tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") cho elem trong mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["mysql_username"]=elem.getElementsByTagName("tên người dùng")[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") cho elem trong dconfig: gconfig["broadcast"]=elem.getElementsByTagName("broadcast")[0]. firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["dhcp_LeaseTime"]=elem.getElementsByTagName("LeaseTime")[0].firstChild.data gconfig[" dhcp_ThreadLimit"]=int(elem.getElementsByTagName("ThreadLimit")[0].firstChild.data) gconfig["dhcp_Server"]=elem.getElementsByTagName("DHCPServer")[0].firstChild.data gconfig["dhcp_defaultMask"] =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultDNS"]=elem.getElementsByTagName(" defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") cho elem trong qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.data cho num trong 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") cho elem trong options: node=elem.getElementsByTagName("option") cho các tùy chọn trong nút : optionsMod.append(options.firstChild.data)
Đa luồng
Thật kỳ lạ, đa luồng trong Python được triển khai rất rõ ràng và đơn giản.
def PacketWork(data,addr): ... # thực hiện phân tích gói tin đến và phản hồi nó ... while True: data, addr = udp_socket.recvfrom(1024) # chờ gói UDP thread = threading.Thread( target=PacketWork , args=(data,addr,)).start() # khi nó xuất hiện - chúng tôi khởi chạy hàm PacketWork được xác định trước đó ở chế độ nền với các tham số trong khi threading.active_count() >gconfig["dhcp_ThreadLimit"]: time. ngủ(1) # nếu số Có nhiều luồng đang chạy hơn trong cài đặt, chúng tôi đợi cho đến khi có ít luồng hơn
Nhận/gửi gói DHCP
Để chặn các gói UDP đi qua card mạng, bạn cần “nâng” socket lên:
AF_INET - nghĩa là định dạng địa chỉ sẽ là IP:port. Cũng có thể có AF_UNIX - nơi địa chỉ được cung cấp theo tên tệp.
SOCK_DGRAM - có nghĩa là chúng tôi không chấp nhận "gói thô", mà là gói đã vượt qua tường lửa và với gói được cắt bớt một phần. Những thứ kia. chúng tôi chỉ nhận được gói UDP mà không có thành phần “vật lý” của trình bao bọc gói UDP. Nếu bạn sử dụng cờ SOCK_RAW thì bạn cũng sẽ cần phải phân tích “trình bao bọc” này.
Việc gửi một gói có thể giống như một chương trình phát sóng:
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #chuyển ổ cắm sang chế độ phát sóng rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))
và đến địa chỉ “nơi gửi gói hàng”:
udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # chuyển socket sang chế độ nhiều người nghe rz=udp_socket.sendto(packetack, addr)
, trong đó SOL_SOCKET có nghĩa là “cấp giao thức” cho các tùy chọn cài đặt,
, tùy chọn SO_BROADCAST rằng gói mũ bảo hiểm được “phát sóng”
Tùy chọn ,SO_REUSEADDR chuyển ổ cắm sang chế độ “nhiều người nghe”. Về lý thuyết, điều này là không cần thiết trong trường hợp này, nhưng trên một trong các máy chủ FreeBSD mà tôi đã kiểm tra, mã không hoạt động nếu không có tùy chọn này.
Phân tích gói DHCP
Đây là nơi tôi thực sự thích Python. Hóa ra nó cho phép bạn khá linh hoạt với mã byte. Cho phép nó được dịch rất dễ dàng sang các giá trị thập phân, chuỗi và hex - tức là. đây là những gì chúng ta thực sự cần để hiểu cấu trúc của gói. Vì vậy, ví dụ: bạn có thể nhận được một phạm vi byte ở dạng HEX và chỉ byte: