Máy chủ DHCP+Mysql bằng Python

Máy chủ DHCP+Mysql bằng Python

Mục đích của dự án này là:

  • Tìm hiểu về DHCP trên mạng IPv4
  • Học Python (nhiều hơn một chút so với từ đầu 😉)
  • 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:

  1. 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.
  2. 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.
  3. 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ể.
  4. 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

Máy chủ DHCP+Mysql bằng Python

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:

Máy chủ DHCP+Mysql bằng Python

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

1 - DHCP KHÁM PHÁ
3 - DHCP YÊU CẦU
2 - DHCPƯU ĐÃI
5 - DHCPACK
8 - DHCPINFORM

 
Độ dài tùy chọn
1
Dec
1

 
Giá trị tùy chọn
1
Dec
1

 
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:

--a gói DHCPINFORM đã đến trên cổng 67, từ 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': '0025224ad764', 'ClientMacAddressByte': b'x00% "Jxd7d', ' HType': 'Ethernet', 'HostName': b'x91xa5xe0xa3xa5xa9-x8fx8a', 'ReqListDNS': True, 'ReqListDomainName': True, 'ReqListPerfowmRouterDiscover': True, 'ReqListRouter': True, 'ReqListStaticRoute': True, ' ReqListSubnetMask ': True, 'ReqListVendorSpecInfo': 43, 'RequestedIpAddress': '0.0.0.0', 'Nhà cung cấp': b'MSFT 5.0', 'chaddr': '0025224ad764', 'ciaddr': '172.30.128.13', ' flags ': b'x00x00', 'giaddr': '172.30.114.25', 'gpoz': 308, 'hlen': 6, 'hops': 1, 'htype': 'MAC', 'magic_cookie': b' cx82Sc ', 'op': 'DHCPINFORM', 'option12': 12, 'option53': 53, 'option55': 55, 'option60': 60, 'option61': 61, 'option82': 82, 'option_82_byte' : b'x12x01x06x00x04x00x01x00x06x02x08x00' b'x06x00x1eXx9exb2xad', 'option_82_hex': '12010600040001000602080006001e589eb2ad', 'option_82_len': 18, 'option_82_str': "b'x12x01x06x00x04x00x01x00x06x02x08x00x06x00x1eXx9exb2xad'", 'kết quả': Sai, 'giây': 768, 'siaddr' : '0.0.0.0', 'sw_mac': '001e589eb2ad', 'sw_port1': '06', 'xidbyte': b'

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:

Máy chủ DHCP+Mysql bằng Python

Máy chủ DHCP+Mysql bằng Python

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:

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

, nơi có các lá cờ:

  • 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:

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

, đóng gói các byte thành một cấu trúc:

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

Nhận IP từ cấu trúc:

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

Và ngược lại:

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

Bây giờ chỉ vậy thôi 😉

Nguồn: www.habr.com

Thêm một lời nhận xét