Biorąc pod uwagę adres IP (powiedzmy 192.168.0.1), jak sprawdzić, czy znajduje się on w sieci (powiedzmy 192.168.0.0/24) w Pythonie?
Czy w Pythonie istnieją ogólne narzędzia do manipulacji adresami IP? Rzeczy takie jak wyszukiwanie hostów, adres IP do int, adres sieciowy z maską sieci do int i tak dalej? Mam nadzieję, że w standardowej bibliotece Pythona dla 2.5.
python
networking
ip-address
cidr
Staale
źródło
źródło
Odpowiedzi:
Ten artykuł pokazuje, że możesz to zrobić z modułami
socket
istruct
bez większego wysiłku. Dodałem trochę do artykułu w następujący sposób:To daje:
Jeśli potrzebujesz tylko jednej funkcji, która pobiera ciągi, wyglądałaby tak:
źródło
return struct.unpack('<L',socket.inet_aton(ip))[0]
addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
(przekonwertowałem „L” na „<L” w moim 64-bitowym systemie operacyjnym)addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
Lubię używać do tego netaddr :
Jak zauważył arno_v w komentarzach, nowa wersja netaddr robi to tak:
źródło
Używając ipaddress ( w standardowym libie od wersji 3.3 , w PyPi dla wersji 2.6 / 2.7 ):
Jeśli chcesz w ten sposób ocenić wiele adresów IP, prawdopodobnie będziesz chciał z góry obliczyć maskę sieci, na przykład
Następnie dla każdego adresu oblicz reprezentację binarną za pomocą jednego z nich
Na koniec możesz po prostu sprawdzić:
źródło
ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
.__contains__
metodę, aby zrobić to w efektywny sposób, porównując całkowite reprezentacje sieci i adresów rozgłoszeniowych, więc możesz być spokojny, jeśli to był twój zmartwienie .W przypadku python3
Wynik :
źródło
Ten kod działa dla mnie na Linux x86. Tak naprawdę nie zastanawiałem się nad problemami endianess, ale przetestowałem go z modułem „ipaddr” przy użyciu ponad 200 000 adresów IP przetestowanych na 8 różnych ciągach sieciowych, a wyniki działania ipaddr są takie same jak w tym kodzie.
Przykład:
źródło
Korzystanie z ipaddress Python3 :
Wyjaśnienie
Możesz myśleć o adresie IP jako o sieci z największą możliwą maską sieci (
/32
dla IPv4,/128
dla IPv6)Sprawdzanie, czy
192.168.0.1
jest w,192.168.0.0/16
jest zasadniczo tym samym, co sprawdzanie, czy192.168.0.1/32
jest to podsieć192.168.0.0/16
źródło
Wypróbowałem rozwiązanie Dave'a Webba, ale napotkałem kilka problemów:
Przede wszystkim - dopasowanie należy sprawdzić, łącząc adres IP z maską, a następnie sprawdzając, czy wynik dokładnie pasuje do adresu sieciowego. Nie łączenie adresu IP z adresem sieciowym, tak jak zostało to zrobione.
Zauważyłem również, że ignorowanie zachowania Endian przy założeniu, że spójność cię uratuje, będzie działać tylko dla masek na granicach oktetów (/ 24, / 16). Aby inne maski (/ 23, / 21) działały poprawnie, dodałem "większe niż" do poleceń struct i zmieniłem kod do tworzenia maski binarnej, aby zaczynała się od wszystkich "1" i przesuwała się w lewo o (maska 32 ).
Na koniec dodałem proste sprawdzenie, czy adres sieciowy jest prawidłowy dla maski i po prostu wydrukowałem ostrzeżenie, jeśli nie jest.
Oto wynik:
źródło
Nie jestem fanem używania modułów, gdy nie są potrzebne. Ta praca wymaga tylko prostej matematyki, więc oto moja prosta funkcja do wykonania tej pracy:
Następnie, aby go użyć:
To wszystko, jest to znacznie szybsze niż rozwiązania powyżej z dołączonymi modułami.
źródło
{TypeError}'map' object is not subscriptable
. Potrzebujeszo = list(o)
poo = map(int, ip.split('.'))
Nie ma go w standardowej bibliotece 2.5, ale ipaddr bardzo to ułatwia. Uważam, że jest w wersji 3.3 pod nazwą ipaddress.
źródło
Przyjęta odpowiedź nie działa ... co mnie złości. Maska jest odwrócona i nie działa z żadnymi bitami, które nie są prostym 8-bitowym blokiem (np. / 24). Dostosowałem odpowiedź i ładnie działa.
tutaj jest funkcja, która zwraca ciąg binarny z kropkami, aby pomóc w wizualizacji maskowania ... coś w rodzaju
ipcalc
wyjścia.na przykład:
źródło
Kod Marca jest prawie poprawny. Pełna wersja kodu to -
Oczywiście z tych samych źródeł, co powyżej ...
Bardzo ważną uwagą jest to, że pierwszy kod ma małą usterkę - adres IP 255.255.255.255 pojawia się również jako prawidłowy adres IP dla dowolnej podsieci. Miałem mnóstwo czasu, aby uruchomić ten kod i dziękuję Markowi za poprawną odpowiedź.
źródło
Poleganie na module „struct” może powodować problemy z endian-ness i rozmiarami typów i po prostu nie jest potrzebne. Ani gniazdo.inet_aton (). Python działa bardzo dobrze z adresami IP z kropkami:
Muszę dopasować IP dla każdego wywołania funkcji accept () w gnieździe, w odniesieniu do całego zestawu dopuszczalnych sieci źródłowych, więc obliczam wstępnie maski i sieci jako liczby całkowite:
Wtedy szybko mogę sprawdzić, czy podany adres IP znajduje się w jednej z tych sieci:
Nie jest potrzebny żaden import modułów, a dopasowanie kodu jest bardzo szybkie.
źródło
z netaddr importuj all_matching_cidrs
Oto użycie tej metody:
Zasadniczo podajesz adres IP jako pierwszy argument i listę numerów CIDR jako drugi argument. Lista trafień jest zwracana.
źródło
źródło
netmask
wartości. Pozwoliłem sobie to naprawić.poprzednie rozwiązanie ma błąd w ip & net == net. Prawidłowe wyszukiwanie adresu IP to ip & netmask = net
naprawiony kod:
źródło
Wybrana odpowiedź zawiera błąd.
Poniżej znajduje się poprawny kod:
Uwaga:
ipaddr & netmask == netaddr & netmask
zamiastipaddr & netmask == netmask
.Ja też wymienić
((2L<<int(bits)-1) - 1)
z((1L << int(bits)) - 1)
, jak ten ostatni wydaje się bardziej zrozumiałe.źródło
((2L<<int(bits)-1) - 1)
jest poprawna. np. jeśli maska ma wartość 16, powinna mieć wartość „255.255.0.0” lub 65535L, ale((1L << int(bits)) - 1)
otrzyma 32767L, co nie jest poprawne.((1L << int(bits)) - 1)
daje 65535L w moim systemie, zbits
ustawieniem na 16 !!bits
zestawu do0
,((2L<<int(bits)-1) - 1)
jest podnoszenie błąd.Oto klasa, którą napisałem dla najdłuższego dopasowywania prefiksów:
A oto program testowy:
źródło
Dziękuję za scenariusz!
Pracuję nad tym dość długo, żeby wszystko działało ... Więc udostępniam to tutaj
Funkcja makeMask nie działa! Działa tylko dla / 8, / 16, / 24
Ex:
Więc użyłem innej funkcji calcDottedNetmask (maska) z http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
Ex:
Np. Na razie funkcja jest nieprawidłowa
Tak więc moja nowa funkcja addressInNetwork wygląda następująco:
A teraz odpowiedź jest prawidłowa !!
Mam nadzieję, że pomoże to innym ludziom, oszczędzając im czas!
źródło
Odnosząc się do wszystkich powyższych, myślę, że socket.inet_aton () zwraca bajty w kolejności sieciowej, więc prawidłowym sposobem ich rozpakowania jest prawdopodobnie
źródło
$ python check-subnet.py
False
True
False
źródło
>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
Nie wiem nic o standardowej bibliotece, ale PySubnetTree to biblioteka Pythona, która dopasowuje podsieci.
źródło
Z różnych źródeł powyżej iz moich własnych badań wynika, w jaki sposób działa obliczanie podsieci i adresu. Te fragmenty wystarczą, aby rozwiązać pytanie i inne powiązane pytania.
źródło
W Pythonie dostępny jest interfejs API o nazwie SubnetTree, który bardzo dobrze wykonuje tę pracę. Oto prosty przykład:
To jest link
źródło
Oto mój kod
źródło
Jeśli nie chcesz importować innych modułów, możesz skorzystać z:
źródło
Wypróbowałem jeden podzbiór proponowanych rozwiązań w tych odpowiedziach ... bez powodzenia, w końcu dostosowałem i poprawiłem proponowany kod i napisałem moją stałą funkcję.
Przetestowałem to i działa przynajmniej na architekturach little endian - egx86 - jeśli ktoś lubi wypróbować architekturę big endian, proszę o informację zwrotną.
IP2Int
kod pochodzi z tego posta , druga metoda to w pełni (dla moich przypadków testowych) działająca poprawka poprzednich propozycji w tym pytaniu.Kod:
Mam nadzieję, że przydatne,
źródło
Oto rozwiązanie wykorzystujące pakiet netaddr
źródło