Diberikan alamat ip (katakanlah 192.168.0.1), bagaimana cara memeriksa apakah itu dalam jaringan (katakanlah 192.168.0.0/24) dengan Python?
Apakah ada alat umum di Python untuk manipulasi alamat ip? Hal-hal seperti pencarian host, alamat ip ke int, alamat jaringan dengan netmask ke int dan sebagainya? Semoga di perpustakaan Python standar untuk 2.5.
python
networking
ip-address
cidr
Staale
sumber
sumber
Jawaban:
Artikel ini menunjukkan Anda dapat melakukannya dengan modul
socket
danstruct
tanpa terlalu banyak usaha ekstra. Saya menambahkan sedikit ke artikel sebagai berikut:Output ini:
Jika Anda hanya menginginkan satu fungsi yang mengambil string, maka akan terlihat seperti ini:
sumber
return struct.unpack('<L',socket.inet_aton(ip))[0]
addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
(Saya mengonversi 'L' ke '<L' di os 64bit saya)addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
Saya suka menggunakan netaddr untuk itu:
Seperti yang ditunjukkan arno_v di komentar, versi baru netaddr melakukannya seperti ini:
sumber
Menggunakan ipaddress ( di stdlib sejak 3.3 , di PyPi untuk 2.6 / 2.7 ):
Jika Anda ingin mengevaluasi banyak alamat IP dengan cara ini, Anda mungkin ingin menghitung netmask dimuka, seperti
Kemudian, untuk setiap alamat, hitung representasi biner dengan salah satu
Terakhir, Anda cukup memeriksa:
sumber
ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
.__contains__
metode untuk melakukannya dengan cara yang efisien dengan membandingkan representasi integer dari jaringan dan alamat siaran, jadi yakinlah jika itu kekhawatiran Anda .Untuk python3
Keluaran:
sumber
Kode ini berfungsi untuk saya di Linux x86. Saya belum benar-benar memikirkan masalah endianess, tetapi saya telah mengujinya terhadap modul "ipaddr" menggunakan lebih dari 200K alamat IP yang diuji terhadap 8 string jaringan yang berbeda, dan hasil ipaddr sama dengan kode ini.
Contoh:
sumber
Menggunakan Python3 ipaddress :
Penjelasan
Anda dapat menganggap Alamat IP sebagai Jaringan dengan kemungkinan netmask terbesar (
/32
untuk IPv4,/128
untuk IPv6)Memeriksa apakah
192.168.0.1
masuk pada192.168.0.0/16
dasarnya sama dengan memeriksa apakah192.168.0.1/32
itu subnet dari192.168.0.0/16
sumber
Saya mencoba solusi Dave Webb tetapi mengalami beberapa masalah:
Yang paling mendasar - kecocokan harus diperiksa dengan MENGANDALKAN alamat IP dengan mask, kemudian memeriksa hasilnya cocok dengan alamat Jaringan secara tepat. Bukan ANDing alamat IP dengan alamat Jaringan seperti yang telah dilakukan.
Saya juga memperhatikan bahwa mengabaikan perilaku Endian dengan asumsi bahwa konsistensi akan menyelamatkan Anda hanya akan berfungsi untuk topeng pada batas oktet (/ 24, / 16). Agar topeng lain (/ 23, / 21) bekerja dengan benar, saya menambahkan "lebih besar dari" ke perintah struct dan mengubah kode untuk membuat topeng biner untuk memulai dengan semua "1" dan menggeser ke kiri oleh (32-mask ).
Akhirnya, saya menambahkan pemeriksaan sederhana bahwa alamat jaringan valid untuk mask dan hanya mencetak peringatan jika tidak.
Inilah hasilnya:
sumber
Saya bukan penggemar menggunakan modul saat tidak diperlukan. Pekerjaan ini hanya membutuhkan matematika sederhana, jadi inilah fungsi sederhana saya untuk melakukan pekerjaan itu:
Kemudian untuk menggunakannya:
Itu saja, ini jauh lebih cepat daripada solusi di atas dengan modul yang disertakan.
sumber
{TypeError}'map' object is not subscriptable
. Anda membutuhkano = list(o)
setelaho = map(int, ip.split('.'))
Tidak ada di perpustakaan Standar untuk 2.5, tetapi ipaddr membuat ini sangat mudah. Saya percaya itu ada di 3.3 dengan nama ipaddress.
sumber
Jawaban yang diterima tidak berhasil ... yang membuatku marah. Mask mundur dan tidak bekerja dengan bit apa pun yang bukan blok 8 bit sederhana (mis. / 24). Saya menyesuaikan jawabannya, dan berhasil dengan baik.
di sini adalah fungsi yang mengembalikan string biner bertitik untuk membantu memvisualisasikan masking .. jenis
ipcalc
keluaran serupa .misalnya:
sumber
Kode Marc hampir benar. Versi lengkap dari kode ini adalah -
Jelas dari sumber yang sama seperti di atas ...
Catatan yang sangat penting adalah bahwa kode pertama memiliki kesalahan kecil - Alamat IP 255.255.255.255 juga muncul sebagai IP yang Valid untuk subnet apa pun. Saya memiliki banyak waktu untuk membuat kode ini berfungsi dan terima kasih kepada Marc untuk jawaban yang benar.
sumber
Mengandalkan modul "struct" dapat menyebabkan masalah dengan endian-ness dan ukuran tipe, dan tidak diperlukan. Juga bukan socket.inet_aton (). Python bekerja sangat baik dengan alamat IP dotted-quad:
Saya perlu melakukan pencocokan IP pada setiap panggilan socket accept (), terhadap seluruh rangkaian jaringan sumber yang diizinkan, jadi saya menghitung sebelumnya topeng dan jaringan, sebagai bilangan bulat:
Kemudian saya dapat dengan cepat melihat apakah IP yang diberikan ada dalam salah satu jaringan tersebut:
Tidak perlu impor modul, dan kodenya sangat cepat dalam mencocokkan.
sumber
dari netaddr import all_matching_cidrs
Berikut adalah penggunaan metode ini:
Pada dasarnya Anda memberikan alamat ip sebagai argumen pertama dan daftar cidrs sebagai argumen kedua. Daftar klik dikembalikan.
sumber
sumber
netmask
nilai yang salah . Saya telah mengambil kebebasan untuk memperbaikinya.solusi sebelumnya memiliki bug di ip & net == net. Pencarian ip yang benar adalah ip & netmask = net
kode perbaikan bug:
sumber
Jawaban yang dipilih memiliki bug.
Berikut adalah kode yang benar:
Catatan:
ipaddr & netmask == netaddr & netmask
alih-alihipaddr & netmask == netmask
.Saya juga mengganti
((2L<<int(bits)-1) - 1)
dengan((1L << int(bits)) - 1)
, karena yang terakhir tampaknya lebih bisa dimengerti.sumber
((2L<<int(bits)-1) - 1)
sudah benar. misal, jika topengnya 16, seharusnya "255.255.0.0" atau 65535L, tetapi((1L << int(bits)) - 1)
akan mendapatkan 32767L, yang mana tidak benar.((1L << int(bits)) - 1)
memberikan 65535L pada sistem saya, denganbits
set ke 16 !!bits
set ke0
,((2L<<int(bits)-1) - 1)
meningkatkan kesalahan.Berikut adalah kelas yang saya tulis untuk pencocokan awalan terpanjang:
Dan ini program tesnya:
sumber
Terima kasih atas naskah Anda!
Saya memiliki pekerjaan yang cukup lama untuk membuat semuanya bekerja ... Jadi saya membagikannya di sini
Fungsi makeMask tidak berfungsi! Hanya bekerja untuk / 8, / 16, / 24
Ex:
Jadi saya telah menggunakan fungsi lain calcDottedNetmask (mask) dari http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
Ex:
Misal: untuk saat ini fungsinya salah
Jadi fungsi addressInNetwork baru saya terlihat seperti:
Dan sekarang, jawabannya benar !!
Saya berharap ini akan membantu orang lain, menghemat waktu untuk mereka!
sumber
Berkaitan dengan semua hal di atas, saya pikir socket.inet_aton () mengembalikan byte dalam urutan jaringan, jadi cara yang benar untuk membukanya mungkin adalah
sumber
$ python check-subnet.py
False
True
False
sumber
>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
Saya tidak tahu apa-apa di perpustakaan standar, tetapi PySubnetTree adalah perpustakaan Python yang akan melakukan pencocokan subnet.
sumber
Dari berbagai sumber di atas, dan dari penelitian saya sendiri, inilah cara saya mendapatkan subnet dan penghitungan alamat. Potongan-potongan ini cukup untuk menjawab pertanyaan dan pertanyaan terkait lainnya.
sumber
Ada API yang disebut SubnetTree tersedia dalam python yang melakukan pekerjaan ini dengan sangat baik. Ini adalah contoh sederhana:
Ini tautannya
sumber
Ini kode saya
sumber
Jika Anda tidak ingin mengimpor modul lain, Anda dapat menggunakan:
sumber
Saya mencoba satu subset dari solusi yang diusulkan dalam jawaban ini .. tanpa hasil, saya akhirnya menyesuaikan dan memperbaiki kode yang diusulkan dan menulis fungsi tetap saya.
Saya mengujinya dan bekerja setidaknya pada arsitektur little endian - egx86 - jika ada yang suka mencoba arsitektur big endian, tolong beri saya umpan balik.
IP2Int
kode berasal dari posting ini , metode lainnya adalah sepenuhnya (untuk kasus uji saya) perbaikan yang berfungsi dari proposal sebelumnya dalam pertanyaan ini.Kode:
Semoga bermanfaat,
sumber
Berikut adalah solusi menggunakan paket netaddr
sumber