Linux: Beim Netzwerksniffing Programmnamen mitschneiden
Es gibt einige Netzwerksniffer bzw. Programme, die aufzeichnen, welche Daten gerade über ein Netzwerkinterface gesendet oder empfangen werden. Als bekanntestes Beispiel sei da wohl WireShark zu nennen. Die dabei benutze Programmbibliothek (pcap) kann aber auch einzeln in eigenen Programmen verwendet werden. Damit beschäftige ich mich im Moment.
Zum Einen soll es die Aufgabe sein, ein möglichst vollständiges Bild des Netzwerks aus den mitgezeichneten Traces zu erhalten, zum anderen, soll aber auch erkannt werden, welche Anwendung an welchem Port lauscht. Diese Information kann für eine spätere Auswertung der Daten nützlich sein. Bspw. könnte so erkannt werden, ob ein Server mit unsinnigen Nachrichten bombardiert wird, o.Ä.
In erster Näherung ist es mit pcap möglich Nachrichten aufzusammeln, die vom Netzwerkgerät kommen. Dann müssen wir noch den Port herausfinden. Die Funktion, die die Nachrichten verarbeiten kann, sieht etwa so aus:
void _recv_msg_cb ( u_char* usr, const struct pcap_pkthdr *h, const u_char *packet );
Die Funktion erhält unsigned char Daten vom Nutzer, eine Datenstruktur pcap_pkthdr, die die Länge der Nachricht sowie einen Timestamp enthält und das Paket (als unsigned char) selbst. Nun kann man Byteweise aus dem Paket Daten auslesen, also bspw. IP-Adressen und Ports. Dazu muss aber auch beachtet werden, ob das Paket vom Rechner selbst versendet wurde, oder empfangen wurde.
Zur Vereinfachung werden hier nur TCP-Pakete (bei Ethernet und IPv4) betrachtet. Wir wissen, dass ein Paket aus mehreren Layers besteht, die die eigentliche Payload (das was am Ende von der Anwendung verarbeitet wird, bzw. eigentlich versandt wurde) wie eine Art Zwiebelschale einhüllen. Unter [1] ist die Struktur des Ethernet Frames dargestellt. Zu Erkennen ist, dass das Payload (IP-Paket), bei 22 oder 26 Bytes Offset beginnt*. Unter [2] ist das IP-Paket dargestellt, was uns hier auch erstmal wenig interessiert. Es ist aber wichtig, dass dessen Payload (TCP-Paket) wiederum bei 24 Byte Offset beginnt. [3] beschreibt den Aufbau des TCP-Pakets. Source Port sind die ersten 16 Bit, Destination Port die nächsten 16 Bit. Dh. wollen wir die Ports abgreifen nehmen wir einen Versatz von 0 Byte bzgl. des Beginns des TCP-Pakets, bzw. von 2 Byte.
Nun sollten wir den Port abgegriffen haben, was nun folgt ist das Herausfinden, welche Anwendung diesen Port benutzt - das muss natürlich zu der Zeit passieren, wenn das Paket abgegriffen wird. Dazu kann in erster Näherung das Programm lsof verwendet werden. So besteht die Möglichkeit innerhalb des C-Programms das Programm zu rufen, via Pipe aus dessen stdout zu lesen und die jeweiligen Zeilen zu interpretieren. So könnte man zum Anwendungsnamen der Anwendung kommen, die auf den gefunden Port lauscht.
Ich hoffe noch, dass es eine einfachere Möglichkeit unter Linux gibt (bspw. einen Systemcall, der direkt befragt werden kann). Dennoch haben wir nun herausgefunden, wie man Pakete am Netzwerkgerät mitlauscht und sich den Anwendungsnamen der Anwendung holt, mit der gerade gesprochen wird, bzw. die gerade spricht.
* pcap hält sich offenbar nicht an das Ethernet-Framelayout. Die Gesamtlänge des Ethernet Header ist zwar unverändert, allerdings stehen nicht Quell- und Ziel-MAC-Adresse vorn, sondern es stehen 6 Byte Informationen, dann die Quell-MAC-Adresse und dann 2 (offenbar ungenutzte) Byte und 2 Byte, die das darüber liegende Protokoll anzeigen. In den ersten 6 Byte ist offenbar ebenfalls encodiert, ob das Paket von uns geschickt wurde, oder nicht. Für weitere Informationen sollte WireShark angeworfen werden, der entsprechend das Layout anzeigt.**
** Das Verhalten liegt offenbar nicht an pcap, sondern eher an Linux, was beim Schnüffeln an "any"-Geräten, einen anderen Paketaufbau zurückliefert. Schnüffelt man hingegen "nur" an "wlanX" und "ethX", dann erhält man einen normalen Ethernet-Frame zurück, der wie auf Wikipedia beschrieben, aufgebaut ist. Dann gibt es auch zwei MAC-Adressen im Ethernet-Header. Btw. ist zu Beachten, dass auf x64-Maschinen die Netzwerk Byte Order von der Host Byte Order abweicht (siehe Little / Big Endian). Es ist also notwendig bspw. bei IP-Adressen und Ports eine Variante von htons auszuführen.
[1] http://en.wikipedia.org/wiki/Ethernet_frame
[2] http://de.wikipedia.org/wiki/IP-Paket
[3] http://en.wikipedia.org/wiki/Transmission_Control_Protocol