weidner/computer/software/perl/

Ein Pure-Perl-Modul für PCAP-Dateien

Das ist ein Beispiel für Software, die kaum ein Mensch braucht, weil das, was sie macht, auch anders geht und besser.

Ich hab das Modul geschrieben, weil ich am liebsten nichts mache. Am liebsten mache ich nichts, weil ich vorher schon etwas gemacht habe. Wie der Fernsehkoch: "Ich hab da schon mal was vorbereitet." Oder nichts, weil jemand anderes was machen soll. Nach Mentorenart: "Ich hab Dir gezeigt, wie es geht, nun sieh zu, wie Du es hinkriegst."

Doch, worum geht es überhaupt? Es geht um ein Thema, das mich seit einigen Jahren umtreibt: um die Fehlersuche bei IPsec VPN. Konkret hier bei Cisco ASA.

VPN ist ein Netzwerkthema und bei Netzwerken ist für mich schon seit Jahrzehnten ein Paketmitschnitt das Schweizer Offiziers-Analyse-Taschenmesser. In diesem sind alle Antworten enthalten, die das Netzwerk geben kann, es kommt nur darauf an, diese zu interpretieren. Und die passenden Fragen zu stellen.

So ein Paketmitschnitt auf der Cisco ASA ist schnell aufgesetzt und dann brauche ich nur noch warten, dass etwas passiert. Anschließend kann ich nachschauen und sagen, was es war oder eher, wofür ich es halte.

So weit, so gut. Die Analysemöglichkeiten auf der ASA bezüglich Paketmitschnitt sind hervorragend, da ist alles dabei, was ich brauche.

Ich kann mir einen schnellen Überblick verschaffen mit

show capture
show capture $name

Einzelne TCP-Flows kann ich mir auch recht einfach anschauen:

show capture $name | i $address.$port

Ich kann mir mehr Details ausgeben lassen, um zum Beispiel an Hand der TTL zu raten, wieviel Hops der Sender entfernt war:

show capture $name detail

Bei IPsec VPNs kann ich mir zumindest für die ersten unverschlüsselten Datagramme die gesendeten Crypto-Paramter ausgeben lassen:

show capture $name decode

Warum also File::PCAP?

Mir fehlt da nichts, und trotzdem habe ich dieses Perl-Modul geschrieben. Zuerst nur ein Skript, das die Ausgabe von sh capture $name dump hernimmt und daraus eine PCAP-Datei erzeugt, die ich mit Wireshark oder tcpdump einlesen kann.

Zugegeben, ein Capture mit tcpdump anzuschauen statt direkt auf der ASA bringt erstmal nichts, außer zusätzlicher Arbeit. Meine Zielgruppe waren eher die Administratoren, die es schön bunt mögen und sich das ganze mit Wireshark ansehen wollen. Und gerade bei den Statistiken und mit Expert-Info bekommt man sehr bequem Auswertungen, die nur sehr mühsam aus den Textausgaben der ASA zusammenzutragen sind. Dafür war es wert, das Modul zu schreiben und für diesen Zweck verwende ich es selbst.

Mit der Veröffentlichung als Modul auf CPAN habe ich Hunderte von Testern bekommen, die die Modultests unter verschiedenen Softwareumgebungen ausprobieren. Außerdem bekam ich bereits eine Rückmeldung zu einem logischen Fehler bei den Funktionen zum Lesen von PCAP-Dateien. Diese Funktionen hatte ich nur der Vollständigkeit halber hinzugefügt, aber selbst noch nicht benötigt und darum auch weniger getestet.

Was konkret macht es?

Das Skript nutzt die Ausgabe von show capture $name dump, die neben der Uhrzeit jeweils einen kompletten Dump des betreffenden Datagramms ausgibt.

Dazu stellt das Perl-Modul File::PCAP die Funktionen bereit, um eine PCAP-Datei anzulegen und Datagramme anzufügen. Ergänzt wird es von dem Module File::PCAP::ACAP2PCAP, welches die Ausgabe der ASA interpretiert und daraus die passenden Datagramm-Records erzeugt. Diese Module nutzt das Skript und kümmert sich selbst nur um die Kommandozeilenparameter und das Handling der Eingabe.

Wie rufe ich es auf?

Im einfachsten Fall rufe ich das Skript ganz ohne weitere Argumente auf:

$ acap2pcap

Dann muss ich die Textausgabe der ASA über die Standardeingabe bereitstellen, zum Beispiel via Copy&Paste von einer SSH-Sitzung in die andere. Sobald ich die Standardeingabe schließe, beendet sich das Skript. Die erzeugte PCAP-Datei erhält den Namen asa.pcap und liegt in dem Verzeichnis, in dem ich das Skript gestartet hatte.

Habe ich die Textausgabe der ASA bereits in einer Datei vorliegen, kann ich diese über eine Dateiumleitung in die Standardeingabe schicken. Oder ich übergebe den Dateinamen als Argument.

$ acap2pcap asa-capture.txt

Dann bildet das Skript den Namen der PCAP-Datei durch Anhängen von '.pcap' an den übergebenen Namen. Will ich einen anderen Namen, kann ich die Option --output zusammen mit dem gewünschten Namen angeben.

$ acap2pcap --output mein-mitschnitt.pcap

Soweit so gut, das ist alles Kosmetik und dazu gedacht, etwas Tipparbeit zu sparen, um nicht extra Dateien anlegen oder später umbenennen zu müssen.

Eine wichtige Option des Skripts befasst sich mit dem Data Link Type (DLT) der PCAP-Datei. Aus diesem geht hervor, ob der Mitschnitt außer den IP-Datagrammen noch weitere Informationen zu den Headern der OSI-Schicht 2 enthält oder nicht.

Voreingestellt ist der DLT 1 (DLT_EN10MB), der für Ethernetschnittstellen geeignet ist und anzeigt, dass die Informationen über die Ethernet-Header enthalten sind. Dieser DLT ist für viele Mitschnitte der ASA geeignet.

Manchmal jedoch bekomme ich von der ASA nur die reinen IP-Datagramme im Mitschnitt. Dann muss ich am Script den DLT 101 (DLT_RAW) mit der Option --dlt einstellen:

$ acap2pcap --dlt 101 rawip.txt

Woran erkenne ich, ob ein Mitschnitt DLT 101 benötigt

Wenn ich es nicht von vorherigen Mitschnitten weiß, kann ich am Dump selbst erkennen, ob ich einen Mitschnitt mit reinen IP-Datagrammen als Text vorliegen habe:

asa# show capture test dump
522 packets captured
 1: 21:24:38.629087 172.17.35.36 > 192.168.2.187: icmp: echo request
0x0000   4500 003c 12a7 0000 7e01 9781 ac11 2324       E..<....~.....#$
0x0010   c0a8 02bb 0800 35cb 0001 1790 6162 6364       ......5.....abcd
0x0020   6566 6768 696a 6b6c 6d6e 6f70 7172 7374       efghijklmnopqrst
0x0030   7576 7761 6263 6465 6667 6869                 uvwabcdefghi
 2: 21:24:38.630765 192.168.2.187 > 172.17.35.36: icmp: echo reply
0x0000   4500 003c 4656 0000 ff01 e2d1 c0a8 02bb       E..<FV..........
0x0010   ac11 2324 0000 3dcb 0001 1790 6162 6364       ..#$..=.....abcd
0x0020   6566 6768 696a 6b6c 6d6e 6f70 7172 7374       efghijklmnopqrst
0x0030   7576 7761 6263 6465 6667 6869                 uvwabcdefghi

Ein Indiz, das es sich um einen reinen IP-Paketmitschnitt handelt, bietet die Zahl 4 an der allerersten Position des Dumps. Gewissheit verschaffe ich mir, indem ich nach den IP-Adressen im Dump suche. 172.17.35.36 ist ac11 2324 im Dump und 192.168.2.187 ist c0a8 02bb. An der Position der beiden Adressen bezogen auf den Beginn des Dumps sehe ich, dass da kein Platz mehr für einen Ethernet-Header ist. RFC791 gibt in Abschnitt 3.1 Auskunft über das genaue Aussehen eines IPv4-Headers.

Für IPv6 finde ich die Struktur in RFC8200, Abschnitt 3, das erste Halbbyte des IPv6-Headers beginnt mit 6.

Damit wäre das wichtigste zu diesem Perl-Modul gesagt. Viel Spaß damit und bei Änderungswünschen hilft der Request Tracker von CPAN weiter.

P.S: Natürlich kann man mit ASDM von der Cisco ASA den Paketmitschnitt auch direkt als PCAP-Datei bekommen. Aber nicht, wenn der ASDM auf Grund von Sicherheitsbestimmungen (veraltete TLS-Version) deaktiviert ist. Und dann hilft das Skript schon etwas weiter.

Posted 2018-02-25
Tags: