Ich stehe vor der Aufgabe, bestimmte Geräte, deren IPs zusammen mit anderen im LAN (Class C, Subnet 255.255.255.0) "verteilt" sind, schnell zu finden (die IP, die per DHCP verteilt wird).
Eine Reservierung anhand der MAC-Adresse im DHCP-Server oder eine Abfrage von dessen Lease-List sind nicht möglich, weil kein Zugang besteht.
Bisher habe ich einfach alle 254 Adressen (1-254) mit einem HTTP-Request durchgeleiert, denn die gesuchten Geräte antworten auf "http://a.b.c.d/?cmd=ident" mit ihrem Gerätenamen, z.B. "<html>printmanager</html>". Fremde Gerät reagieren darauf nicht oder mit "Unsinn", so dass die Erkennung auf diese Weise kein Problem ist. Zumal sind die erwarteten Antworten bzw. Gerätenamen bekannt.
Das funktioniert sehr zuverlässig, aber eben langsam. Die MAC-Adressen der Subsysteme sind auch bekannt. Ich könnte natürlich auch schnell mal Alles durchpingen und dann den ARP-Cache aus einer Shell laden und darin herumparsen. Hier stört, dass die ARP-Resultate auf jeder Palttform (Win, Mac, Linux) anders formatiert sind ...
Hat jemand eine Idee, die er zum Besten geben möchte?
Auf die Insrallation zusätzlicher Tool soll verzichtet werden (z.B. "macping"), es muss mit Bordmitteln funktionieren.
Ansonsten bleibe ich halt einfach bei der trivialen Scan-Methode ...
Ich stehe vor der Aufgabe, bestimmte Geräte, deren IPs zusammen mit
anderen im LAN (Class C, Subnet 255.255.255.0) "verteilt" sind, schnell
zu finden (die IP, die per DHCP verteilt wird).
Das funktioniert sehr zuverlässig, aber eben langsam.
was ist "schnell" für Dich in einer üblichen SI-Einheit?
Programmausführung ohne Installationpipapo ist ok?
Ich benutze dazu das Programm NetSetMan in der kostenlosen Version.
Dazu einfach bei den Werkzeugen den Netzwerkscanner auswählen
und den zu durchsuchenden Netzwerkbereich eintragen und starten.
Mit dem Tool kann man auch viele verschiedene Netzwerkprofile anlegen
und mit eine Klick aktivieren.
Wenn man z.Bsp. in vielen verschiedenen Netzwerken arbeitet.
NMap mit ZenMAp Gui. Sucht alle offene Ports im Subnet.
Will er ja garnicht. Er will nur die offenen Ports 80 (das kann man nmap noch mitteilen), und davon nur die, die auf seinen GET-Request korrekt antworten.
Sind 253 GET-Requests. Wenn er die parallel startet und nicht sequentiell, hat er in weniger als 0.1 Sekunden seine Liste fertig.
Schneller wird's mit einem externen Port-Scanning tool auch nicht.
Sind 253 GET-Requests. Wenn er die parallel startet und nicht
sequentiell, hat er in weniger als 0.1 Sekunden seine Liste fertig.
Danke, gute Idee - mein Programmierwerkzeug "Xojo" kann tatsächlich Threads, das hatte ich garnicht mehr auf dem Schirm ... naja klar: Der Wald und die Bäume oder ich werd alt :-(
Wenn es statt der bisherigen 30s nur 3 sind bin ich schon zufrieden. Ich werde berichten. Ich muss mal gucken, wieviel RAM so ein Thread braucht, muss auf einem Raspi mit 2GB laufen ... aber auch das könnte ich dynamisch anpassen, weil ich ja jederzeit abfragen kann, wieviel RAM noch frei ist ...
Ich stehe vor der Aufgabe, bestimmte Geräte, deren IPs zusammen mit
anderen im LAN (Class C, Subnet 255.255.255.0) "verteilt" sind, schnell
zu finden (die IP, die per DHCP verteilt wird).
Das funktioniert sehr zuverlässig, aber eben langsam.
was ist "schnell" für Dich in einer üblichen SI-Einheit?
Programmausführung ohne Installationpipapo ist ok?
Als single thread bzw. in einer ganz gewöhnlichen For-Schleife im Hauptprogramm bis zu 30 ... 35 Sekunden.
Danke, gute Idee - mein Programmierwerkzeug "Xojo" kann tatsächlich
Threads,
Threads sind an dieser Stelle overkill und machen es nur langsamer.
Hunderte gleichzeitige TCP-Verbindungen kann Unix seit einem halben Jahrhundert auch ohne Threads problemlos ("select", "poll" &co).
Bei deinem Xojo läuft es darauf hinaus, einfach statt hintereinander jedesmal ein
"connection.SendSync" zu starten, eben "connection.Send" zu verwenden.
Das kannst du ohne Verzögerung 253mal aufrufen, die Verbindungen laufen parallel im Hintergrund, und du bekommst im Erfolgsfall ein "ContentReceived"-Event, sonst ein "Error".
Danke, gute Idee - mein Programmierwerkzeug "Xojo" kann tatsächlich
Threads,
Threads sind an dieser Stelle overkill und machen es nur langsamer.
"connection.SendSync" zu starten, eben "connection.Send" zu verwenden.
Das kannst du ohne Verzögerung 253mal aufrufen, die Verbindungen laufen
parallel im Hintergrund, und du bekommst im Erfolgsfall ein
"ContentReceived"-Event, sonst ein "Error".
Ok, hab ich so noch nicht versucht, klingt einleuchtend.
Die Adressen 127 und 255 sind Multicast adressen. Die werden also von allen empfangen. Du kannst also dort einen algorithmus durchziehen, bei welchem dir schliesslich jeder antwortet. Und zwar schneller wie jeden einzeln abzufragen.
Ping wird ausgeführt für 10.10.10.255 mit 32 Bytes Daten:
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.
Zeitüberschreitung der Anforderung.
"An ICMP Echo Request destined to an IP broadcast or IP multicast
address MAY be silently discarded."
Das ist heutzutage auch der Regelfall, bei mir antwortet gerade mal ein Drucker darauf.
In den 90ern war das noch anders, da wurden Unternehmen auch gerne mal zu unfreiwilligen DoS-Helfern, wenn die Admins "no ip directed-broadcast" nicht kannten.
Ich mach das inzwischen mit einer Kombination aus Ping auf die IP und anschließendem arp mit der IP als Argument. Das ergibt als Antwort die MAC-Adresse für genau diese IP und keine meterlange Liste :-)
Ich mach das inzwischen mit einer Kombination aus Ping auf die IP und
anschließendem arp mit der IP als Argument. Das ergibt als Antwort die
MAC-Adresse für genau diese IP und keine meterlange Liste :-)
So ein Blödsinn. Richtig wäre natürlich einfach ein ARP-WhoHas an die Broadcast-Adresse des interessierenden Netzes für jede IP-Adresse des interessierenden Netzes.
Und asynchron dazu einsammeln, was da an ARP-IsAt-Antworten eintrudelt. Also genau das tun, was ARP halt so tut (wenn eben auch normalerweise nur für gezielte Fragen).
Kein Ahnung, was Ping (also ICMP-Echo) dabei soll. Hat doch mit der Sache garnix zu schaffen. Kein Schwein interessiert sich dafür, ob das Target gewillt ist, auf ICMP-Echo zu antworten. Was interessiert ist: ist es überhaupt gewillt, irgendwie per IP zu kommunizieren.
Aber:
Es gibt Geräte, die ihre Bereitschaft, per IP zu kommunizieren, nicht so einfach verraten. Die wollen vorher erstmal noch einen anderen Broadcast sehen. Oder sogar eine ganz bestimmte Folge solcher Broadcasts. Bis sie die sehen, halten sie sich IP-mäßig bedeckt.
Es gibt sogar Geräte, die überhaupt niemals per IP kommunizieren, aber trotzdem das Netz benutzen. Halt nur auf Layer2.
Ich mach das inzwischen mit einer Kombination aus Ping auf die IP und
anschließendem arp mit der IP als Argument. Das ergibt als Antwort die
MAC-Adresse für genau diese IP und keine meterlange Liste :-)
So ein Blödsinn. Richtig wäre natürlich einfach ein ARP-WhoHas an die
Broadcast-Adresse des interessierenden Netzes für jede IP-Adresse des
interessierenden Netzes.
Mag sein. Und wie starte ich das per CLI? ARP kennt keinen Befehl, mit "who". Aber vielleicht ist es ja das, was ich ohnehin mache?
Kein Ahnung, was Ping (also ICMP-Echo) dabei soll. Hat doch mit der
Sache garnix zu schaffen. Kein Schwein interessiert sich dafür, ob das
Target gewillt ist ...
Doch. Die Targets, um die es MIR geht, abntworten definitiv auf Ping. Ich mache ja keinen allgemeinen Scan, sondern suche genau diese.
Aus Experimenten weiss ich, dass ich eine ARP-Antwort nur dann sicher erhalte, wenn vorher eine Kommuniktion stattfand, z.B. Ping.
Und 253-mal Ping (ggfs sogar auch per Kommandozeilen-Ping-Tool) und dann den arp-cache auslesen (per Kommandozeilen-Tool) soll schneller sein, als einfach aus deinem Programm die 253 IPs per HTTP-Get durchzutesten?
Kann ich mir nicht vorstellen. Und du brauchst den HTTP-Get nach dem ARP sowieso auch noch, für dein ?cmd=ident...
Und das Vorab-Filtern nach bekannter MAC kann dir bei etwas komplexeren Network-Setups auch auf die Füße fallen, Stichwort VPN, ProxyArp, usw...
Und das Vorab-Filtern nach bekannter MAC kann dir bei etwas komplexeren
Network-Setups auch auf die Füße fallen, Stichwort VPN, ProxyArp, usw...
Ich will kein universelles Werkzeug, ich brauche nur die Antwort der Clients im gleichen LAN/24. Und ich weiss, wie viele ich finden muss (4 Stück), kann also aufhören, sobald alle erkannt sind.
Allzuviele Sockets gleichzeitig scheint mir auch keine so gute Idee, weil das Ganze am Raspi 4 mit 2GB laufen muss, keine Ahnung wie viele das Raspian abkann. Vielleicht hat jemand dazu eine Idee.
Es ist ja nicht so, dass die biherige Methode nicht funktioniert, ich hätte sie nur gerne etwas beschleunigt. Deshalb alles komplett umzustellen lohnt sich allerdings auch nur in Grenzen.
Allzuviele Sockets gleichzeitig scheint mir auch keine so gute Idee,
weil das Ganze am Raspi 4 mit 2GB laufen muss
Auf dem Raspi kriegst du locker 10000 gleichzeitige GET-Requests mit deinen Datenmengen hin, bevor der überhaupt auf 1% CPU-Auslastung kommt... Allerdings nicht wenn man das über 10000 gleichzeitig laufende Threads löst.
Ein einziger Aufruf des "arp"-Utilities aus deinem Programm heraus braucht schon mehr Ressourcen als der ganze Scan per TCP/HTTP... Und ist ja scheinbar auch kein Thema, was deinen RasPi irgendwie überfordert.
Kurz getestet: 254 sockets (NONBLOCK) aufgemacht, allen ein "connect" gegeben, alle per epoll_ctl(...EPOLL_ADD zu einem epoll-fd hinzugefügt.
Dann per epoll_wait warten, was auf den einzelnen sockets passiert, mit timeout.
Die Userspace-CPU-Zeit ist mit "time" nicht mehr messbar, system/kernel-Zeit liegt bei ~12millisekunden, "real"-Zeit hängt vom gewählten Timeout ab.
1
> time ./conn_test 192.168.23
2
3
Successful connection to 192.168.23.1
4
Successful connection to 192.168.23.8
5
Successful connection to 192.168.23.17
6
Successful connection to 192.168.23.120
7
Timeout reached. Stopping.
8
9
real 0m0,279s
10
user 0m0,000s
11
sys 0m0,012s
Das wird auch nicht mehr fett, wenn man dann die sowieso schon verbundenen Sockets nimmt um ein "GET /?cmd=ident HTTP/1.0\r\n\r\n" hinterherzuschicken, und die Antwort auszulesen.
Nachtrag: Das mit <1% CPU war etwas übertrieben.
Wenn ich auf die Weise 192.168.0.0/16 scanne (Also ~ 64k gleichzeitig verbindende TCP-Sockets)
dann lastet das für etwas über 2 Sekunden einen CPU-Kern aus.
d.H. da würde es dann langsam Sinn machen das Ganze auf 4 Threads zu verteilen.
Du hast jetzt ernst mal eben einen Scanner zusammengehackt, der in "Nullzeit" alle in einem Netz erreichbaren Geräte findet?
Geilo!
Kannst du das für Windows bauen, gern auch als Kommandozeilendings? Oder kennst du ein "Fertigprodukt" das genau das macht?
Ich wüsste nämlich auch ganz gern mal, welche IPs hier besetzt sind, und diverse Scanner dauern ewig oder melden "7 denied" aber ohne IP bei Geräten die kein HTTP können/wollen, das nutzt mir nix, ich weiß das die da sind aber eben die Adresse nicht.
So, ich hab mal was gebastelt (Xojo), das scannt ein /24-Netz in 3,5s. Was momentan fehlt, ist der Filter auf die speziell formatierte Antwort, weil ich die dazu nötigen Geräte (Automaten-Komponenten) gerade nicht im Zugriff habe. Was man hier sieht, sind die IPs und MACs, der Geräte, die in meinem privaten Netz auf einen schnöden HTTP-Request, auch ohne Parameter, antworten. Das genügt mir hinsichtlich der Geschwindigkeit vollkommen. Danke für die hilfreichen Tips.
1
Public Sub find_mac(ip_base as string) // ip_base like "192.168.10."
2
3
var uc(255) as URLConnection //List of HTTP-Sockets
4
var ff(255) as FolderItem //List of temporary files
5
var path as string = SpecialFolder.Temporary.NativePath+"/uc." //path in tmp folder
Oh, das ist eine Handvoll Jahre her das ich das gemacht hatte.
Mit dem Browser ( oder wget ) eine HTML Seite aufrufen die alle 253 IP Adressen hat und dann den ARP Cache auslesen.
Ja klar, das tut jeder Versuch einer IP-Kommunikation (wenn die MAC der Zieladresse nicht schon im ARP-Cache ist).
Genau dafür ist ARP halt da. Und für den Fall, dass man sich dafür interessiert, welche Geräte im Netz sind, die gewillt sind, per IP zu kommunizieren, reicht es also logischerweise aus, für jede Adresse des Netzes eine ARP-Anfrage zu senden.
Das ist die kleinstmögliche und damit logischerweise auch schnellstmögliche Kommunikation zu diesem Thema. Genau dafür wurde ARP schließlich geschaffen.
Bei allen anderen hier genannten Ansätzen wird der Kanal mit Bullshit höherer Protokolle zugespammt, die mit der eigentlichen Aufgabe rein garnix zu tun haben.
Bei allen anderen hier genannten Ansätzen wird der Kanal mit Bullshit
höherer Protokolle zugespammt, die mit der eigentlichen Aufgabe rein
garnix zu tun haben.
Die eigentliche Aufgabe aus dem Eröffnungs-Beitrag war ein HTTP GET an alle Geräte im Subnetz, die Port 80 offen haben.
Der "Bullshit höherer Protokolle" wird also so oder so benötigt.
Und das "zuspammen" verhindert schon der Kernel. Wenn der beim TCP-Connect-Versuch keine ARP-Antwort erhält oder im Cache hat, dann wandert auch kein TCP-SYN über die Leitung. Wie auch.
Klar, man kann anfangen Teile des Kernel-Netzwerkstacks nachzuimplementieren, in der Hoffnung da etwas Zeit für einen speziellen Anwendungsfall rauszuholen. NMap macht das m.W. bei manchen Scan-Arten per Raw-Sockets. Aber will man sich das bei so einer kleinen Anzahl von möglichen Ziel-IPs antun?
Du hast jetzt ernst mal eben einen Scanner zusammengehackt, der in
"Nullzeit" alle in einem Netz erreichbaren Geräte findet?
Geilo!
Das ist komplett Boiler-Plate-Code, den hat mir ChatGPT so fast korrekt zusammengestöpselt.
Für den TE bringt das nix. Die zentrale "epoll"-Event-Loop hat sein Xojo sowieso schon, Xojo packt auch die Sockets da von selber rein, und wandelt die epoll-events auf seine eigenen events am Connection-Objekt um.
d.H. mindestens 75% vom Code ist sowieso schon von seinem Framework erschlagen, das muss nicht als low-level C-Code implementiert werden...
Die eigentliche Aufgabe aus dem Eröffnungs-Beitrag war ein HTTP GET an
alle Geräte im Subnetz, die Port 80 offen haben.
Nein, das war nur, was der TO getan hat, weil er es nicht besser wusste oder konnte.
Wenn man das ganze Posting liest (und denken kann), stellt sich heraus: Er kennt das Netz und er kennt die die MACs der Geräte, nach denen er sucht.
Also: er benötigt genau nur eins: ARP. Kein IP und schon gar kein HTTP.
Das Zeug kommt dann erst zum Zuge, wenn er seine Ziele gefunden hat. Und dann eben auch nur für die.
Der "Bullshit höherer Protokolle" wird also so oder so benötigt.
Aber doch nicht für jede verfickte Adresse im Netz, auf der irgendein Gerät bereit ist, IP zu sprechen...
Und das "zuspammen" verhindert schon der Kernel. Wenn der beim
TCP-Connect-Versuch keine ARP-Antwort erhält oder im Cache hat, dann
wandert auch kein TCP-SYN über die Leitung. Wie auch.
Ja, aber wenn da ein Gerät ist, welches IP sprechen mag, aber eben NICHT mit der erwarteten MAC ausgestattet ist, dann geht der ganze Bullshit übers Netz. Natürlich mehr oder weniger erfolglos, aber er kostet Bandbreite und damit Zeit. Dein Argumunt passt als allerhöchstens dann, wenn das gesamte Netz bis auf die gesuchten Geräte unbenutzt ist...
Klar, man kann anfangen Teile des Kernel-Netzwerkstacks
nachzuimplementieren
Das braucht man sicher nicht, um ein Sack voll simple ARP-Abfragen rauszuschicken und nach einiger Zeit einen Blick auf den Bestand des ARP-Cache zu werfen...
DU kannst es nur nicht so. Das ist eigentlich schon alles.
Ne. Genau das braucht er nicht.
ARP findet zu einer bekannten IP-Adresse die unbekannte MAC-Adresse.
Genau. Einen umgekehrten Weg gibt es nicht und kann es auch nicht geben. Das liegt in der Natur der Sache.
Genau deswegen ist es ja auch nötig, nach sämtlichen in Frage kommenden IP-Adressen zu fragen. Und das können bei größeren Netzen schon mal eine ganze Menge sein. Bei einem 10.x.x.x/8-Netz sind es eben mal so 16.777.214 nötige Anfragen. Gerade dann zählt jedes gesparte Byte Traffic pro Anfrage...
Natürlich werden sich wenigsten so ein 8er-Netz anhängen. Aber 10.x.x.x/16 oder 172.16..31.x.x/16 kommt durchaus häufiger mal vor. Da sind dann auch noch 65.534 Adressen zu befragen.
Genau deswegen ist es ja auch nötig, nach sämtlichen in Frage kommenden
IP-Adressen zu fragen.
Nein, ist es nicht, wenn er seine Hosts richtig gebaut hätte. Nämlich so, dass sie ein Service-Discovery unterstützen. SSDP, WS-Discovery, etc. Gibt genug Protokolle.
So muss er ein ganzes Subnet scannen. Was in kommerziellen Installation schnell mal richtig Ärger mit den Admins einbringt. Zumindest wenn die entsprechende Überwachungsmechanismen im LAN haben.
Das Scannen ist weder toll noch clever, sondern Pfusch. Kein Grund sich zu feiern.
Nein, ist es nicht, wenn er seine Hosts richtig gebaut hätte. Nämlich
so, dass sie ein Service-Discovery unterstützen. SSDP, WS-Discovery,
etc. Gibt genug Protokolle.
Ja klar. Und woher weißt du bei der Geräteentwicklung, welches dieser Protokolle im Zielnetz der Geräte "zugelassen" ist? Typisch weiß man ja bei der Geräteentwicklung noch nicht, wohin der Kram mal verkauft werden wird. Allenfalls hat man zu diesem Zeitpunkt gewisse Hoffnungen, an wen man das verkaufen könnte, aber man hat wohl kaum Detailinformationen zu den Netzen der gewünschten Kunden...
So muss er ein ganzes Subnet scannen. Was in kommerziellen Installation
schnell mal richtig Ärger mit den Admins einbringt. Zumindest wenn die
entsprechende Überwachungsmechanismen im LAN haben.
Wenn das Netz derart restriktiv konfiguriert ist, dass es sogar ARP-Requests limitiert (ganz ausschalten kann man die heute wohl aus praktischen Gründen nicht mehr, fast alles spricht IP und braucht dementsprechend ARP), dann kannst du GANZ sicher davon ausgehen, dass auch nicht übermässig viele Discovery-Protokolle darin zugelassen und die zugelassenen im Detail auch wieder nur restriktiv zugelassen sind. Sprich: selbst wenn es z.B. WS-Discovery prinzipiell gibt (weil z.B. bestimmte Drucker verwendet werden sollen), dann wird trotzdem nicht jedes Gerät die Vollmacht haben, sich in das entsprechende Verzeichnis einzutragen. Wäre ja noch schöner...
Sprich: dieser Ansatz hilft dem TO in stark reglementierten Netzen auch nicht weiter. Sehr wahrscheinlich tut das dann aber überhaupt kein Ansatz. Typisch ist in solchen Netzen nämlich auch Port-Security durchgesetzt. D.h.: du kannst deine Geräte zwar an irgendwelche Dosen dranstöpseln, sie werden dort aber nichts weiter tun können als einen Alarm für den Admin auszulösen...
Wenn das Netz derart restriktiv konfiguriert ist, dass es sogar
ARP-Requests limitiert (ganz ausschalten kann man die heute wohl aus
praktischen Gründen nicht mehr, fast alles spricht IP und braucht
dementsprechend ARP)
Kann man (z.B. ifconfig <if> -arp), dann braucht man halt statische Einträge. Ist aber nur in seltenen Fällen sinnvoll.
Was mir hingegen schon in der Praxis begegnet ist, sind Geräte, die nicht auf ARP-Requests antworten, sondern ausschliesslich in festen Intervallen Gratuitous ARP (also unaufgeforderte Replies) verschicken. Da das Smartwatches waren, wohl aus Energiespargründen.
Was mir hingegen schon in der Praxis begegnet ist, sind Geräte, die
nicht auf ARP-Requests antworten, sondern ausschliesslich in festen
Intervallen Gratuitous ARP (also unaufgeforderte Replies) verschicken.
Huch...
Gibt es tatsächlich noch Geräte, die solche ARP-"Antworten" in ihren ARP-Cache aufnehmen?
Das sollte doch wegen des zeitweise sehr beliebten Angriffszenarios des ARP-Spoofing inzischen praktisch überall geblockt werden.
OK, ARP-Spoofing funktioniert auch mit Unicast-Antworten. Aber eben nur bei einem Peer, nicht gleich bei allen.
Multicast-DNS wurde genau für sowas gemacht, müssen deine Geräte im
Netzwerk aber natürlich unterstützen.
Das ist keine Option? Da kannst du einfach jedem Gerät einen Namen geben, über den du es dann unabhängig von seiner IP ansprechen kannst, genau wie mit klassischem DNS, nur dass man keinen Server braucht.
Sind 253 GET-Requests. Wenn er die parallel startet und nicht
sequentiell, hat er in weniger als 0.1 Sekunden seine Liste fertig.
Wie kann ich über eine Serielle Leitung Parallel scannen? :P
Ich vermute, es bezog sich auf die Software, nicht auf die Leitung selbst. Wenn man einen GET-Request versucht, muss man ja so lange warten, bis eine Antwort kommt oder der Timeout abläuft. Also macht man mehrere Requests parallel, damit die alle gleichzeitig warten können statt nacheinander.