IP Scanner

Code-Stücke können hier veröffentlicht werden.
Antworten
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Ich habe hier mal ein Lan Scanner gebastelt :D
Was haltet ihr davon und wie "sauber" ist der Code? :)

Code: Alles auswählen


import socket


def is_up(addr):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(0.1)
    if not s.connect_ex((addr, 135)):
        s.close()
        return False
    else:
        return True

def main():
	liste = []
	for ip in range(1, 256):
		addr = "192.168.0." + str(ip)
		check = is_up(addr)
		if check == False:
			print(addr, "Belegt")
			liste.append(addr)
		elif check == True:
			print(addr, "Frei")
		else:
			print("Fehler")
	print()
	print("********************************")
	print()
	anzahl = len(liste)
	for ips in range(anzahl):
		print("Belegt : ", liste[ips])

if __name__ == "__main__":
	main()

Übrigends wurde dazwischen ein Switch geschaltet, ist halt für LAN-Feten gedacht. :)

mfg
Trayser
BlackJack

@TrayserCassa: `is_up()` verwendet `connect_ex()` statt `connect()` kümmert sich aber nicht um eventuelle Ausnahmen die ja trotzdem noch auftreten können. `connect()` und eine entsprechende Ausnahmebehandlung wäre also einfacher.

Der Rückgabewert von `is_up()` ist falsch, denn wenn die Verbindung da ist, dann wird `False` zurückgegeben. Das macht keinen Sinn. Das die Zahl die zurückgegeben wird ”Falsch” bedeutet wenn die Verbindung zustande kommt, macht das ganze auch nicht wirklich gut lesbar wenn man einfach mit ``not`` arbeitet statt explizit mit ``== 0`` auf den ”guten” Fall zu testen. Bei `connect()` hätte man das Problem nicht.

`s` ist kein guter Name. Genau so wenig ist `liste` ein guter Name. `check` ist schon besser als Name an sich, aber eher für eine Funktion oder Methode, da er eine Tätigkeit beschreibt. Eigentlich wäre für diesen Wert `is_up` ein passender Name, wenn die Funktion nicht schon so heissen würde. Bei `ips` hätte ich keine ganzen Zahlen erwartet sondern zum Beispiel eine Liste mit IPs.

Die `main()`-Funktion ist nicht vier Leerzeichen pro Ebene eingerückt.

Das explizite Prüfen auf literale `True`- und `False`-Werte ist schlechter Stil. Bei dem Vergleich kommt doch nur wieder ein Wahrheitswert heraus, da hätte man auch gleich den nehmen können mit dem man das Literal vergleicht, beziehungsweise das gegebenfalls negieren.

Die drei Zweige für `True`, `False`, und anderes sind überflüssig weil die Funktion nur `True` oder `False` zurück gibt.

``for index in range(len(sequence)):`` ist ein „anti pattern”. Man kann stattdessen direkt über die Elemente der Liste iterieren.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

zusätzlich: um Strings zusammen zu bauen, ist Stringformatierung einem »+ str(x)« vorzuziehen.
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Danke für die Verbesserungsvorschläge :D

Ich hab versucht aus der Docu über "connect" schlauer zu werden, aber versteh die exceptions nicht genau wie ich die abfangen kann :K Daher habe ich noch "connect_ex" drin. Vielleicht mag mir da jemand weiterhelfen? :)

Die Namensgebung bei mir ist wirklich bescheiden :roll:
(Hier bin ich mit connection allerdings nicht zufrieden. Ihr?)

str() habe ich ausgetauscht :wink:

hier der Code:

Code: Alles auswählen

import socket


def check(addr):
	connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	connection.settimeout(0.1)
	if connection.connect_ex((addr, 135)) == 0:
		connection.close()
		return True
	else:
		return False

def main():
	check_liste = []
	for ip in range(1, 25):
		addr = "%s%d" % ("192.168.0.", ip)
		is_up = check(addr)
		if is_up == True:
			print(addr, "Belegt")
			check_liste.append(addr)
		elif is_up == False:
			print(addr, "Frei")
	print()
	print("********************************")
	print()
	for item in check_liste:
		print("Belegt : ", item)

if __name__ == "__main__":
	main()


Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@TrayserCassa: Du hast die expliziten Vergleiche auf »True« und »False« immer noch drin, wobei die “False”-Bedingung durch ein einfaches »else« ersetzt werden kann.

Gemeint war

Code: Alles auswählen

addr = "192.168.0.%d" % ip
BlackJack

Ungetestet:

Code: Alles auswählen

import socket as socketlib
from contextlib import closing
from itertools import islice

from ipaddress import ip_network


def check_if_up(ip_address):
    socket = socketlib.socket(socketlib.AF_INET, socketlib.SOCK_STREAM)
    socket.settimeout(0.1)
    try:
        with closing(socket.connect((str(ip_address), 135))):
            return True
    except socketlib.error:
        return False


def main():
    used_ips = list()
    for address in islice(ip_network('192.168.0.0/27').hosts(), 25):
        if check_if_up(address):
            used_ips.append(address)
            print(address, 'ist belegt.')
        else:
            print(address, 'ist frei.')
    print()
    print('*' * 70)
    print()
    for address in used_ips:
        print('Belegt:', address)


if __name__ == '__main__':
    main()
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

@BlackJack Da kommt ein Fehler falls es die IP gibt.

Code: Alles auswählen

192.168.0.1 ist frei.
192.168.0.2 ist frei.
192.168.0.3 ist frei.
192.168.0.4 ist frei.
192.168.0.5 ist frei.
192.168.0.6 ist frei.
192.168.0.7 ist frei.
192.168.0.8 ist frei.
192.168.0.9 ist frei.
192.168.0.10 ist frei.
192.168.0.11 ist frei.
192.168.0.12 ist frei.
192.168.0.13 ist frei.
192.168.0.14 ist frei.
192.168.0.15 ist frei.
192.168.0.16 ist frei.
192.168.0.17 ist frei.
192.168.0.18 ist frei.
192.168.0.19 ist frei.
Traceback (most recent call last):
  File "test2.py", line 34, in <module>
    main()
  File "test2.py", line 21, in main
    if check_if_up(address):
  File "test2.py", line 13, in check_if_up
    return True
  File "C:\Python34\lib\contextlib.py", line 152, in __exit_
    self.thing.close()
AttributeError: 'NoneType' object has no attribute 'close'
Habe zurzeit leider wenig Zeit deshalb vergebt mir, wenn ich mal ne Woche nicht da bin. ;)

mfg
Trayser
BlackJack

Ebenfalls ungetestet:

Code: Alles auswählen

def check_if_up(ip_address):
    socket = socketlib.socket(socketlib.AF_INET, socketlib.SOCK_STREAM)
    socket.settimeout(0.1)
    try:
        with closing(socket):
            socket.connect((str(ip_address), 135))
            return True
    except socketlib.error:
        return False
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Jap so Funktioniert es :)

Danke für die mühen BlackJack

mfg
Trayser
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Ich weiss das thema ist schon alt aber der code sagt bei jeder IP das sie frei ist und wie kann ich angeben welche er scannen soll? bei mir scannt er nur die ersten 30.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Schau mal auf die for-Schleife. Das erklaert die Limitierung. Und das ganze ist nur eine Heuristik, Port 135 ist wenn ich mich recht erinnere ein Windows port - da muss aber nix laufen, und ggf. haben neuere Versionen das auch dicht gemacht.
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Wenn du diese

Code: Alles auswählen

for address in islice(ip_network('192.168.178.0/27').hosts(), 255):
meinst, da wo jetzt 255 steht zeigt immer noch nur 30 und was währe zb. ein plattformunabhängiger port?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Fire Spike: Warum erwartest Du denn mehr als 30? Das Netzwerk das Du da angibst hat ja ganz offensichtlich 30, da wäre es sehr komisch wenn er mehr als 30 prüfen würde, oder?

Code: Alles auswählen

In [8]: 2 ** (32 - 27) - 2                                                      
Out[8]: 30
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

Oder mal andersrum gefragt: Hast du das /27 bewusst gesetzt, oder einfach aus dem Code oben übernommen? Wenn du das gesamte Class-C Netzwerk scannen möchtest, wäre /24 korrekt (s. CIDR-Notation).
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

@nezzcarth danke du hast mir geholfen. ist port 80 eine gute idee?
info: das ist mein eigenes wlan
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein. Port 80 ist ne doofe Idee, denn die wenigsten Systeme lassen einen eigenen Webserver laufen. Es gibt Tools die deutlich komplexere Heuristiken fahren, die kannst du dir mal anschauen. mmap zB. Oder das einfach benutzen 🤷‍♂️
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

Fire Spike hat geschrieben: Donnerstag 24. Oktober 2019, 11:51 @nezzcarth danke du hast mir geholfen. ist port 80 eine gute idee?
info: das ist mein eigenes wlan
Die Frage wäre halt, was du genau herausfinden möchtest. Aktuell prüft das Skript, ob unter unter einer IP ein System existiert, das eine TCP Verbindung auf Port 80 zulässt. Das ist eine viel spezifischere Frage, als die, ob ein Rechner verfügbar ist. Wenn die Prüfung klappt, ist das System offensichtlich verfügbar, aber wenn die Prüfung misslingt, kann man daraus nicht schließen, dass das System nicht verfügbar ist. Wie __deets__ angedeutet hat, prüft man am besten mehrere Sachen und wenn man es mit einiger Genauigkeit sagen möchte, ist das keine so unkomplizierte Frage. Neben nmap ist zum Beispiel auch arping (ARP) oder fping (ICMP) hilfreich, um sich dem zu nähern.
Antworten