Giới thiệu về mô-đun ipaddress¶
- tác giả:
Peter Moody
- tác giả:
Nick Coghlan
Tạo các đối tượng Địa chỉ/Mạng/Giao diện¶
Vì ipaddress là một mô-đun để kiểm tra và thao tác địa chỉ IP, điều đầu tiên bạn muốn làm là tạo một số đối tượng. Bạn có thể sử dụng ipaddress để tạo đối tượng từ chuỗi và số nguyên.
Lưu ý về phiên bản IP¶
Đối với những độc giả chưa đặc biệt quen thuộc với địa chỉ IP, điều quan trọng cần biết là Giao thức Internet (IP) hiện đang trong quá trình chuyển từ phiên bản 4 của giao thức sang phiên bản 6. Quá trình chuyển đổi này diễn ra phần lớn là do phiên bản 4 của giao thức không cung cấp đủ địa chỉ để đáp ứng nhu cầu của toàn thế giới, đặc biệt là khi số lượng thiết bị kết nối trực tiếp với Internet ngày càng tăng.
Việc giải thích chi tiết về sự khác biệt giữa hai phiên bản của giao thức nằm ngoài phạm vi của phần giới thiệu này, nhưng ít nhất người đọc cần biết rằng hai phiên bản này tồn tại và đôi khi sẽ cần phải buộc sử dụng phiên bản này hoặc phiên bản kia.
Địa chỉ máy chủ IP¶
Địa chỉ, thường được gọi là "địa chỉ máy chủ" là đơn vị cơ bản nhất khi làm việc với địa chỉ IP. Cách đơn giản nhất để tạo địa chỉ là sử dụng chức năng xuất xưởng của ipaddress.ip_address(), chức năng này tự động xác định xem nên tạo địa chỉ IPv4 hay IPv6 dựa trên giá trị được truyền vào:
>>> ipaddress.ip_address('192.0.2.1')
IPv4Address('192.0.2.1')
>>> ipaddress.ip_address('2001:DB8::1')
IPv6Address('2001:db8::1')
Địa chỉ cũng có thể được tạo trực tiếp từ số nguyên. Các giá trị phù hợp trong phạm vi 32 bit được coi là địa chỉ IPv4:
>>> ipaddress.ip_address(3221225985)
Địa chỉ IPv4('192.0.2.1')
>>> ipaddress.ip_address(42540766411282592856903984951653826561)
Địa chỉ IPv6('2001:db8::1')
Để buộc sử dụng địa chỉ IPv4 hoặc IPv6, các lớp liên quan có thể được gọi trực tiếp. Điều này đặc biệt hữu ích để buộc tạo địa chỉ IPv6 cho các số nguyên nhỏ:
>>> ipaddress.ip_address(1)
Địa chỉ IPv4('0.0.0.1')
>>> ipaddress.IPv4Address(1)
Địa chỉ IPv4('0.0.0.1')
>>> ipaddress.IPv6Address(1)
Địa chỉ IPv6('::1')
Xác định mạng¶
Địa chỉ máy chủ thường được nhóm lại với nhau thành mạng IP, vì vậy ipaddress cung cấp cách tạo, kiểm tra và thao tác các định nghĩa mạng. Các đối tượng mạng IP được xây dựng từ các chuỗi xác định phạm vi địa chỉ máy chủ là một phần của mạng đó. Hình thức đơn giản nhất cho thông tin đó là cặp "địa chỉ mạng/tiền tố mạng", trong đó tiền tố xác định số lượng bit dẫn đầu được so sánh để xác định xem một địa chỉ có phải là một phần của mạng hay không và địa chỉ mạng xác định giá trị mong đợi của những bit đó.
Đối với địa chỉ, chức năng xuất xưởng được cung cấp để tự động xác định phiên bản IP chính xác:
>>> ipaddress.ip_network('192.0.2.0/24')
Mạng IPv4('192.0.2.0/24')
>>> ipaddress.ip_network('2001:db8::0/96')
Mạng IPv6('2001:db8::/96')
Các đối tượng mạng không thể có bất kỳ tập bit máy chủ nào. Hiệu quả thực tế của việc này là 192.0.2.1/24 không mô tả mạng. Các định nghĩa như vậy được gọi là đối tượng giao diện vì ký hiệu ip-on-a-network thường được sử dụng để mô tả giao diện mạng của máy tính trên một mạng nhất định và được mô tả thêm trong phần tiếp theo.
Theo mặc định, việc cố gắng tạo một đối tượng mạng với các bit máy chủ được đặt sẽ dẫn đến việc ValueError được nâng lên. Để yêu cầu các bit bổ sung thay vào đó bị ép về 0, cờ strict=False có thể được chuyển tới hàm tạo
>>> ipaddress.ip_network('192.0.2.1/24')
Traceback (cuộc gọi gần đây nhất):
...
ValueError: 192.0.2.1/24 đã đặt bit máy chủ
>>> ipaddress.ip_network('192.0.2.1/24', strict=False)
Mạng IPv4('192.0.2.0/24')
Mặc dù dạng chuỗi cung cấp tính linh hoạt cao hơn đáng kể nhưng mạng cũng có thể được xác định bằng số nguyên, giống như địa chỉ máy chủ. Trong trường hợp này, mạng được coi là chỉ chứa một địa chỉ duy nhất được xác định bằng số nguyên, do đó tiền tố mạng bao gồm toàn bộ địa chỉ mạng:
>>> ipaddress.ip_network(3221225984)
Mạng IPv4('192.0.2.0/32')
>>> ipaddress.ip_network(42540766411282592856903984951653826560)
Mạng IPv6('2001:db8::/128')
Giống như các địa chỉ, việc tạo một loại mạng cụ thể có thể bị ép buộc bằng cách gọi trực tiếp hàm tạo của lớp thay vì sử dụng hàm xuất xưởng.
Giao diện máy chủ¶
Như đã đề cập ở trên, nếu bạn cần mô tả một địa chỉ trên một mạng cụ thể thì cả địa chỉ và các lớp mạng đều không đủ. Ký hiệu như 192.0.2.1/24 thường được sử dụng bởi các kỹ sư mạng và những người viết công cụ cho tường lửa và bộ định tuyến như cách viết tắt của "máy chủ 192.0.2.1 trên mạng 192.0.2.0/24", Theo đó, ipaddress cung cấp một tập hợp các lớp kết hợp liên kết một địa chỉ với một mạng cụ thể. Giao diện để tạo giống hệt với giao diện xác định các đối tượng mạng, ngoại trừ phần địa chỉ không bị hạn chế là địa chỉ mạng.
>>> ipaddress.ip_interface('192.0.2.1/24')
IPv4Interface('192.0.2.1/24')
>>> ipaddress.ip_interface('2001:db8::1/96')
IPv6Interface('2001:db8::1/96')
Đầu vào số nguyên được chấp nhận (như với mạng) và có thể buộc phải sử dụng một phiên bản IP cụ thể bằng cách gọi trực tiếp hàm tạo có liên quan.
Kiểm tra các đối tượng địa chỉ/mạng/giao diện¶
Bạn gặp khó khăn khi tạo một đối tượng IPv(4|6)(Address|Network|Interface), vì vậy bạn có thể muốn lấy thông tin về nó. ipaddress cố gắng làm cho việc này trở nên dễ dàng và trực quan.
Giải nén phiên bản IP:
>>> addr4 = ipaddress.ip_address('192.0.2.1')
>>> addr6 = ipaddress.ip_address('2001:db8::1')
>>> addr6.version
6
>>> addr4.version
4
Lấy mạng từ một giao diện:
>>> Host4 = ipaddress.ip_interface('192.0.2.1/24')
>>> Host4.network
Mạng IPv4('192.0.2.0/24')
>>> Host6 = ipaddress.ip_interface('2001:db8::1/96')
>>> máy chủ6.mạng
Mạng IPv6('2001:db8::/96')
Tìm hiểu xem có bao nhiêu địa chỉ riêng lẻ trong một mạng
>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> net4.num_address
256
>>> net6 = ipaddress.ip_network('2001:db8::0/96')
>>> net6.num_address
4294967296
Lặp lại các địa chỉ "có thể sử dụng" trên mạng
>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> for x in net4.hosts():
... print(x)
192.0.2.1
192.0.2.2
192.0.2.3
192.0.2.4
...
192.0.2.252
192.0.2.253
192.0.2.254
Lấy mặt nạ mạng (tức là đặt các bit tương ứng với tiền tố mạng) hoặc mặt nạ máy chủ (bất kỳ bit nào không phải là một phần của mặt nạ mạng):
>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> net4.netmask
IPv4Address('255.255.255.0')
>>> net4.hostmask
IPv4Address('0.0.0.255')
>>> net6 = ipaddress.ip_network('2001:db8::0/96')
>>> net6.netmask
IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::')
>>> net6.hostmask
IPv6Address('::ffff:ffff')
Nổ hoặc nén địa chỉ:
>>> addr6.exploded
'2001:0db8:0000:0000:0000:0000:0000:0001'
>>> addr6.compression
'2001:db8::1'
>>> net6.exploded
'2001:0db8:0000:0000:0000:0000:0000:0000/96'
>>> net6.compression
'2001:db8::/96'
Mặc dù IPv4 không hỗ trợ bùng nổ hoặc nén nhưng các đối tượng liên quan vẫn cung cấp các thuộc tính liên quan để mã trung lập phiên bản có thể dễ dàng đảm bảo sử dụng dạng ngắn gọn nhất hoặc dài dòng nhất cho địa chỉ IPv6 trong khi vẫn xử lý chính xác địa chỉ IPv4.
Mạng dưới dạng danh sách Địa chỉ¶
Đôi khi việc coi mạng là danh sách sẽ rất hữu ích. Điều này có nghĩa là có thể lập chỉ mục cho chúng như thế này:
>>> mạng4[1]
Địa chỉ IPv4('192.0.2.1')
>>> net4[-1]
Địa chỉ IPv4('192.0.2.255')
>>> mạng6[1]
Địa chỉ IPv6('2001:db8::1')
>>> net6[-1]
Địa chỉ IPv6('2001:db8::ffff:ffff')
Điều đó cũng có nghĩa là các đối tượng mạng tự sử dụng cú pháp kiểm tra tư cách thành viên danh sách như thế này
nếu địa chỉ trong mạng:
# do gì đó
Kiểm tra ngăn chặn được thực hiện hiệu quả dựa trên tiền tố mạng:
>>> addr4 = ipaddress.ip_address('192.0.2.1')
>>> addr4 trong ipaddress.ip_network('192.0.2.0/24')
đúng
>>> addr4 trong ipaddress.ip_network('192.0.3.0/24')
sai
So sánh¶
ipaddress cung cấp một số cách đơn giản, hy vọng trực quan để so sánh các đối tượng, nếu có ý nghĩa:
>>> ipaddress.ip_address('192.0.2.1') < ipaddress.ip_address('192.0.2.2')
đúng
Ngoại lệ TypeError sẽ xuất hiện nếu bạn cố so sánh các đối tượng thuộc các phiên bản khác nhau hoặc các loại khác nhau.
Sử dụng địa chỉ IP với các mô-đun khác¶
Các mô-đun khác sử dụng địa chỉ IP (chẳng hạn như socket) thường không chấp nhận trực tiếp các đối tượng từ mô-đun này. Thay vào đó, chúng phải bị ép buộc thành một số nguyên hoặc chuỗi mà mô-đun khác sẽ chấp nhận
>>> addr4 = ipaddress.ip_address('192.0.2.1')
>>> str(addr4)
'192.0.2.1'
>>> int(addr4)
3221225985
Nhận thêm chi tiết khi tạo phiên bản không thành công¶
Khi tạo các đối tượng địa chỉ/mạng/giao diện bằng cách sử dụng các hàm xuất xưởng không phân biệt phiên bản, mọi lỗi sẽ được báo cáo là ValueError kèm theo thông báo lỗi chung chỉ cho biết giá trị được truyền vào không được nhận dạng là đối tượng thuộc loại đó. Việc thiếu một lỗi cụ thể là do cần phải biết giá trị supposed là IPv4 hay IPv6 để cung cấp thêm chi tiết về lý do tại sao nó bị từ chối.
Để hỗ trợ các trường hợp sử dụng hữu ích khi có quyền truy cập vào chi tiết bổ sung này, các hàm tạo của lớp riêng lẻ thực sự nâng cao các lớp con ValueError ipaddress.AddressValueError và ipaddress.NetmaskValueError để chỉ ra chính xác phần nào của định nghĩa không phân tích cú pháp chính xác.
Các thông báo lỗi chi tiết hơn đáng kể khi sử dụng trực tiếp các hàm tạo của lớp. Ví dụ:
>>> ipaddress.ip_address("192.168.0.256")
Traceback (cuộc gọi gần đây nhất):
...
ValueError: '192.168.0.256' dường như không phải là địa chỉ IPv4 hoặc IPv6
>>> ipaddress.IPv4Address("192.168.0.256")
Traceback (cuộc gọi gần đây nhất):
...
ipaddress.AddressValueError: Octet 256 (> 255) không được phép trong '192.168.0.256'
>>> ipaddress.ip_network("192.168.0.1/64")
Traceback (cuộc gọi gần đây nhất):
...
ValueError: '192.168.0.1/64' dường như không phải là mạng IPv4 hoặc IPv6
>>> ipaddress.IPv4Network("192.168.0.1/64")
Traceback (cuộc gọi gần đây nhất):
...
ipaddress.NetmaskValueError: '64' không phải là mặt nạ mạng hợp lệ
Tuy nhiên, cả hai ngoại lệ cụ thể của mô-đun đều có ValueError là lớp cha, vì vậy nếu không lo lắng về loại lỗi cụ thể, bạn vẫn có thể viết mã như sau:
thử:
mạng = ipaddress.IPv4Network(địa chỉ)
ngoại trừ ValueError:
print('địa chỉ/netmask không hợp lệ đối với IPv4:', địa chỉ)