Logfile auslesen mit Regexp
C:S
- perl
Tach,
ich will mir ein einfaches Perlskript basteln, dass aus einem Iptables-Log Daten ausließt, und in einer Datenbank abspeichert.
Logausschnitt:
Nov 22 10:35:40 host kernel: [IPTB] RSN="Denied TCP" IN=eth0 OUT= MAC=00:21:85:**** SRC=78.43.213.*** DST=21.46.***.*** LEN=52 TOS=0x00 PREC=0x00 TTL=56 ID=54658 DF PROTO=TCP SPT=29266 DPT=135 WINDOW=60352 RES=0x00 SYN URGP=0
Nov 22 10:41:52 host kernel: [IPTB] RSN="Denied ICMP" IN=eth0 OUT= MAC=00:21:85:62:4c:20:00:02:85:0c:5b:00:08:00 SRC=79.202.235.*** DST=21.47.***.*** LEN=56 TOS=0x00 PREC=0x00 TTL=58 ID=18275 PROTO=ICMP TYPE=3 CODE=13 [SRC=21.47.***.*** DST=79.202.235.*** LEN=40 TOS=0x00 PREC=0x00 TTL=58 ID=18275 DF PROTO=TCP INCOMPLETE [8 bytes] ]
Um die Werte den jeweiligen Variablen zuzuweisen, benutze ich Regexp. Solange dies so ausschaut:
($month,$dom,$hour,$min,$sec,$src,$dst,$ttl,$proto,$spt,$dpt) = ($line =~ /([a-zA-Z]{3}) ([0-9]{1,2}) (\d\d):(\d\d):(\d\d).*SRC=([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*DST=([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*TTL=([0-9]*).*PROTO=([a-zA-Z]{3,4}).*SPT=([0-9]*).*DPT=([0-9]*).*/);
funktionierts einwandfrei, und ich kann mit den Variablen so arbeiten wie ich das brauche. Doch ich kriegs jetzt einfach nicht gebacken, den Wert von RSN rauszubekommen. Hab alles Mögliche probiert. Folgende Lösung:
($month,$dom,$hour,$min,$sec,$rsn,$src,$dst,$ttl,$proto,$spt,$dpt) = ($line =~ /([a-zA-Z]{3}) ([0-9]{1,2}) (\d\d):(\d\d):(\d\d).*RSN="(.*)"[^\[]*SRC=([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*DST=([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*TTL=([0-9]*).*PROTO=([a-zA-Z]{3,4}).*SPT=([0-9]*).*DPT=([0-9]*).*/);
funktioniert nur für Zeilen mit den Protokollen UDP oder TCP (erste Zeile aus Logauszug oben), bei ICMP (zweite Zeile aus Logauszug oben) werden den Variablen kein Wert mehr zugewiesen.
Kann mir jemand helfen, wie ich das hinkriege? Langsam fällt mir nix mehr ein...
Gruß, CS
Schaue, ob es für deine Aufgabe bereits einen Parser gibt.
Wenn nicht verwende m//sub()/ex;
Matche zuerst einen Record entsprechend Anfang und Ende. Übergebe den Teilstring einer sub, die dann die Details für dich rauszieht.
Bilde einen klaren Lexer für dein Problem. Deine Rex bringt dich in einer Woche zur Verzweiflung.
Wenn dir nichts mehr einfällt, dann liess einfach die Perl Docu.
Dort gibts so Dinge beschrieben wie ^ $ \b \n \s \S etc...
mfg Beat
# Würg, das kann ja kein Mensch lesen. Und überhaupt, bei diesen ganzen lückenüberbrückenden .* wird mir ganz schwummerig. Wenn du gewisse Edge cases in deinem Log hast, funktioniert das nicht mehr sauber. Na egal, hellsehen über den Rest des Logs vermag ich nicht und vermutlich bist du sowieso nicht an einer robusten Lösung interessiert. Probier's eben so:
use 5.010;
use English qw(-no_match_vars %LAST_PAREN_MATCH);
# > perl -E'say for 0..255' | assemble
# danke, Regexp::Assemble::Compressed!
my $zero255 = qr/(?:1(?:0\d?|1\d?|2\d?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?)?|2(?:[6789]|5[012345]?|0\d?|1\d?|2\d?|3\d?|4\d?)?|3\d?|4\d?|5\d?|6\d?|7\d?|8\d?|9\d?|0)/;
while (my $line = <DATA>) {
if ($line =~ /
\A
(?<month> [a-zA-Z]{3} ) # Drei Buchstaben sind auch nicht korrekt,
# dito der ganze Rest außer den IP-Nummern,
# aber jetzt hab ich keine Lust mehr auf assemble.
[ ]
(?<day_of_month> [0-9]{1,2} )
[ ]
(?<hour> \d\d ) : (?<minute> \d\d ) : (?<second> \d\d )
.*
RSN="(?<rsn> [^"]* )" # siehe Artikel "Death to dot star!" für die Erklärung
# " ← mit diesem Kommentar biege ich das Syntaxhighlighting im Forum wieder zurecht
.*
SRC=(?<source> $zero255 [.] $zero255 [.] $zero255 [.] $zero255 )
[ ]
DST=(?<destination> $zero255 [.] $zero255 [.] $zero255 [.] $zero255)
.*
TTL=(?<time_to_live> [0-9]* )
.*
PROTO=(?<protocol> [a-zA-Z]{3,4} )
(?:
[ ]
SPT=(?<source_port> [0-9]* )
[ ]
DPT=(?<destination_port> [0-9]* )
)? # diese Gruppe existiert nicht immer
/msx) {
say $LAST_PAREN_MATCH{rsn};
use Data::Dumper; say Dumper \%LAST_PAREN_MATCH;
}
}
# Ausgabe:
##########
##########
# Denied TCP
# $VAR1 = {
# 'protocol' => 'TCP',
# 'source' => '78.43.213.123',
# 'hour' => '10',
# 'destination' => '21.46.123.123',
# 'second' => '40',
# 'month' => 'Nov',
# 'destination_port' => '135',
# 'source_port' => '29266',
# 'minute' => '35',
# 'rsn' => 'Denied TCP',
# 'time_to_live' => '56',
# 'day_of_month' => '22'
# };
#
# Denied ICMP
# $VAR1 = {
# 'protocol' => 'TCP',
# 'source' => '21.47.123.123',
# 'hour' => '10',
# 'destination' => '79.202.235.123',
# 'second' => '52',
# 'month' => 'Nov',
# 'minute' => '41',
# 'rsn' => 'Denied ICMP',
# 'time_to_live' => '58',
# 'day_of_month' => '22'
# };
__DATA__
Nov 22 10:35:40 host kernel: [IPTB] RSN="Denied TCP" IN=eth0 OUT= MAC=00:21:85:62:4c:20:00:02:85:0c:5b:00:08:00 SRC=78.43.213.123 DST=21.46.123.123 LEN=52 TOS=0x00 PREC=0x00 TTL=56 ID=54658 DF PROTO=TCP SPT=29266 DPT=135 WINDOW=60352 RES=0x00 SYN URGP=0
Nov 22 10:41:52 host kernel: [IPTB] RSN="Denied ICMP" IN=eth0 OUT= MAC=00:21:85:62:4c:20:00:02:85:0c:5b:00:08:00 SRC=79.202.235.123 DST=21.47.123.123 LEN=56 TOS=0x00 PREC=0x00 TTL=58 ID=18275 PROTO=ICMP TYPE=3 CODE=13 [SRC=21.47.123.123 DST=79.202.235.123 LEN=40 TOS=0x00 PREC=0x00 TTL=58 ID=18275 DF PROTO=TCP INCOMPLETE [8 bytes] ]
" ← mit diesem Kommentar biege ich das Syntaxhighlighting im Forum wieder zurecht
YMMD :-)
Krasse Aktion übrigens.
" ← mit diesem Kommentar biege ich das Syntaxhighlighting im Forum wieder zurecht
YMMD :-)
Krasse Aktion übrigens.
Jaja, diese REs treiben manches Highlighting mit ihrem Editor zur Rotglut.
Die meisten Highlighter matchen deshalb nur Anfang und Ende der RE-Delimiter.
Man kanns auch vermeiden mit
m/[""]/
mfg Beat