IDEA I/O home  | about  | cheat sheets  | github

Verbesserungen Fortigate Log Parser

Seit der ersten Version habe ich mehrere Verbesserungen am Fortigate Log Parser vorgenommen. Das Python Skript ist auf Github: http://github.com/oelu/fg_log_parser/.

Performance

Eines der Hauptprobleme war die Performance. Ich habe festgestellt, dass die erste Version viel RAM benötigt um Logfiles grösser als 100MB zu parsen. Zudem dauerte es ca. 25 Minuten, bis ein 600MB Logfile komplett geparst war. In mehreren Schritten wurde die Performance optimiert. Die wichtigste Änderung dabei ist, dass der Log Parser nicht mehr die komplette Datei in den RAM liest, sondern diese Zeile für Zeile bearbeitet. So benötigt er auch bei grösseren Dateien mit einer umfangreichen Matrix nicht mehr als 10MB RAM.

Zudem verwendet die Funktion, welche eine Logzeile in key und value Paare umwandelt nun nicht mehr das Python Modul shlex, sondern einen Regex. Damit dauert die Bearbeitung eines 600MB Logfiles ca. 2 Minuten.

Command Line Optionen

Mehrere CLI Optionen wurden angepasst oder erweitert.

-b --countbytes:

Die Option countbytes summiert die Bytes pro Verbindung auf.

-v --verbose:

Verbose gibt nun mehr Informationen zur Programmausführung aus. So werden z.B. neu gefundene srcip und dstip Tupel ausgegeben.

-n --noipcheck:

Es wird nicht getestet, ob das srcipfield und das dstipfield im Logfile vorhanden sind.

Log Format Optionen

Mit neuen Log Format Optionen, kann das Log Format flexibel angepasst werden. Es ist damit auch möglich Logfiles von anderen Herstellern zu lesen. Voraussetzung dafür ist, dass diese ein key=value Format aufweisen.

Im Folgenden sind die Log Format Optionen kurz beschrieben:

--srcipfield=<srcipfield>:

Feld für die Source IP Adresse.

--dstipfield=<dstipfield>:`

Feld für die Destination IP Adresse.

--dstportfield=<dstportfield>:

Feld für den Destination Port.

--protofield=<protofield>:

Feld für das Protokoll.

Wird die Option --countbytes gewählt, müssen zusätzlich noch die folgenden Felder angegeben werden.

--sentbytesfield=<sentbytesfield>:

Feld für die gesendeten Bytes.

--rcvdbytesfield=<rcvdbytesfield>:

Feld für die empfangenen Bytes.

Damit kann nun z.B. auch ein Iptables Log geparst werden:

$ fg_log_parser.py -f filter --srcipfield=SRC \
--dstipfield=DST --dstportfield=DPT --protofield=PROTO

Fehlende Felder ignorieren

Die Zuordnung der Felder aus der Logzeile wird nun über die Python Dictionary Funktion logline.get(key) vorgenommen und nicht mehr über logline[key]. Die get() Funktion hat den Default Rückgabewert None. Es ist nun möglich, Dateien ohne dstportfield und protofield zu parsen. Die fehlenden Werte werden mit None ergänzt.

Achtung:

Mit der Option --noipcheck ist es theoretisch möglich eine beliebige Datei zu parsen, und folgende Ausgabe zu erhalten:

None
    None
        None
            None
                count: Anzahl Zeilen in der Datei.

Help

Die Hilfe Funktion wurde angepasst und um Beispiele erweitert.

» python fg_log_parser.py -h
Fortigate Log Parser
Parses a Fortigate logfile and presents a 
communication matrix.

Usage: fg_log_parser.py
  fg_log_parser.py (-f <logfile> | 
                    --file <logfile>) [options]

Options:
    -b --countbytes         Count bytes for each
                            communication quartet
    -h --help               Show this message
    -v --verbose            activate verbose messages
    --version               Shows version information
    -n --noipcheck          Do not check if src and dst
                            ip are present

    Log Format Options (case sensitive):
    --srcipfield=<srcipfield>       Src ip address 
                                    field [default: srcip]
    --dstipfield=<dstipfield>       Dst ip address
                                    field [default: dstip]
    --dstportfield=<dstportfield>   Dst port field
                                    [default: dstport]
    --protofield=<protofield>       Protocol field
                                    [default: proto]

    If countbytes options is set you may have to specify:
    --sentbytesfield=<sentbytesfield>  Field for sent bytes
                                       [default: sentbyte]
    --rcvdbytesfield=<rcvdbytesfield>  Field for rcvd bytes
                                       [default: rcvdbyte]

Examples:
    Parse Fortigate Log:
        fg_log_parser.py -f fg.log
    Parse Iptables Log:
        $ fg_log_parser.py -f filter --srcipfield=SRC \
        --dstipfield=DST --dstportfield=DPT --protofield=PROTO

    Parse Fortianalyzer Log:
        $ fg_log_parser.py -f faz.log \
        --srcipfield=src --dstipfield=dst

Tests

Mit dem Doctest Modul wurden mehrere Testfälle erstellt, welche die einzelnen Funktionen und das Parsen von verschiedenen Logfiles testen.