Schrift
[thread]4448[/thread]

Datenstrom in Realtime mitlesen: tcpdump über Pipe an Perlscript übergebn



<< >> 6 Einträge, 1 Seite
Gast Gast
 2007-01-02 14:17
#37427 #37427
Hallo !
Ich habe ein kleine Problem (ich hoffe ein kleines)
Für die Überwachung von LAN-Partys lese ich mit
Code: (dl )
tcpdump -e -q -n -i eth0 ip >/root/logpipe

Daten über einen Monitorport mit und analysiere die
Daten aus der named Pipe mit einem Perl-Script um Statistiken
zu erzeugen und Netzwerkprobleme zu erkennen.

Das lief auf nem älteren SuSE8.2 auch ganz gut. Leider
habe ich jetzt bei nem 10.1 das Problem, das die Daten nur noch
blockweise in der Pipe erscheinen (habe ich mit tail -f getestet).
Identisches geschieht auch bei einer normalen Datei.
Ich erhalte die Daten also erst, wenn einige hundert Bytes
zusammengekommen sind. Dann aber auf einmal. Ich benötige die
Daten aber sofort. Auf der Konsole schreibt tcpdump die Ausgabe
ja sofort. Nur nicht in eine Datei oder Pipe.

Beim Schreiben aus Perl kann ich das über $| verändern
(Flushen von Buffern oder so - Stand im Perl-Kochbuch von OReilly)
Wie mache ich das aber außerhalb von Perl ???? Ich weiß - kein direktes
Problem von Perl. Aber ich weiß nicht mehr weiter :-(
Ich hoffe, mir kann hier einer helfen. Bei linuxforen.de habe ich
noch keine Antwort bekommen.

Schon mal besten Dank für alle Reaktionen.

Gruß
Bernd (bernd@sccweb.de)
sid burn
 2007-01-03 20:43
#37428 #37428
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Hi,
also wenn du etwas als Pipe oder in einer Datei umleitest dann wird das ganze eigentlich sofort geschrieben.

Dein Test mit "tail -f" ist da aber nicht ganz korrekt. Den "tail -f" arbeitet unter GNU/Linux so das es jede Sekunde nur einmal die Datei pollt und dann die änderungen ausgibt die in der Sekunde angefallen sind.

Das kann bei vielen Daten dann so aussehen als wenn es Blockweise oder erst bei paar Hundert Bytes in die Datei geschrieben wird, das sieht aber nur so aus weil tail nicht "richtig" arbeitet.



Ansonsten wenn du vom Perl Skript aus der Pipe liest dann wird normalerweise Zeilenweise gelesen. Wenn du das auch nicht haben möchtest dann kannst du entweder sysread() benutzen oder den Dateihandle wovon du liest auf non-blocking stellen. (IO::Handle am besten anschauen) Ob das aber unbedingt so eine gute Idee ist würde ich mal bezweiflen.

Meistens brauch man ja eine ganze Zeile damit man die Daten auswerten kann.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
dino03
 2007-01-05 08:41
#37429 #37429
User since
2007-01-04
3 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hi sid burn !

Konnte dir leider nicht so schnell antworten. Leichte
Login/Registrierungs-Probleme auf dem Board gehabt.
(Die helfen einem hier echt schnell! Nochmal besten Dank an Renee)

Zu meinem Problem ...

Ne Sekunde Unterschied wär ja vertretbar. Vor allem, weil ich das Lesen
der Log-Dateien auch auf 3sec.-Zyklus (mit File::Tail) gestellt habe.
Das was bei mir auftritt sind aber teilweise 20-30sec oder noch länger
(je nach Datenmenge). Das ist nicht mehr vertretbar.

Identisches Problem hatte ich bei einem Überwachungsscript von nem
FTP-Server. Die Logs, die das Script geschrieben hat sind erst nach
20-30sec in der Datei erschienen (das kann nicht an tail -f liegen).
Das konnte ich dann folgendermassen erzwingen:
Code: (dl )
1
2
3
4
open (LOGDATEI, ">>${logdat}") or die("Dateifehler!");                  # Log-Datei öffnen zum schreiben
$old_fh = select(LOGDATEI); # siehe perlfaq5 (How do I flush/unbuffer an output filehandle? Why must I do this?)
$| = 1; # Perl anweisen, die Schreiboperation auf die Logdatei nicht zu buffern
select($old_fh); # sondern direkt auszufuehren

Das identische Problem tritt beim Schreiben der Daten von tcpdump in die
named Pipe auf, nur das ich so eine Variable und Perl-Code natürlich
bei tcpdump nicht habe. Bei ner älteren SuSE (ich glaube 8.2) lief das
alles ohne Probleme. Irgendwann so zwischen 9.x und 10.1 muß sich da
was geändert haben. Bei ner 9.2 habe ich das mit dem
FTP-Überwachungsscript.

Ich habe schon die gesammte man bash durchgesucht, mit apropos alles
gurchgewühlt was irgendwie mit buffer, file oder flush war und meine
O&´Reilly-Bücher durchgeblätter (Linux in a Nutshell, Perl Kochbuch, Perl
Programmierung, ...) alles nix.

In nem anderen Script lief das bis jetzt so ...
Code: (dl )
1
2
3
4
open (LOGPIPE, $pipename) || print "konnte $pipename nicht oeffnen\n";
while (<LOGPIPE>) # Zeilen lesen
{
my $logline = $_; # Zeile sichern

Einfachste Art, Eingabedaten aus ner Pipe zu lesen.
Mit dem Script habe ich mit tcpdump gelesen und das Transfervolumen
einzelner Rechner Richtung Internet aufsummiert.

Meiner Meinung nach muß das Problem an der Pipe und tcpdump oder
der Shell aus dem das startet liegen. Ich weiß aber nicht mehr weiter.
Ich laß mich aber auch gerne belehren ;-)

Gruß
Bernd
renee
 2007-01-05 11:05
#37430 #37430
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
probier mal
Code: (dl )
tcpdump -l -e -q -n -i eth0 ip >/root/logpipe
(von: http://www.tcpdump.org/lists/workers/2000/msg01217.html)

Noch ein anderer Link: http://www.unixboard.de/vb3/showthread.php?t=19437
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
dino03
 2007-01-05 11:57
#37431 #37431
User since
2007-01-04
3 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hi Renee!

Du hast mir schon wieder weitergeholfen :)
Ich habe aber noch nen weiteren Denkfehler gemacht.
Das mit dem tcpdump -l funktioniert super!!!!!!!!

ich habe also mit tcpdump -l .... >logpipe den Verkehr gesnifft
und mit tail -f logpipe die Pipe ausgelesen.
Da hat das alles nix genutzt. Alles wie vorher. Irgendwann nach
teilweise 1-2 Minuten bei normalem Ping kommt mal ne Ausgabe.
Wenn man jetzt aber mit cat logpipe arbeitet, dann läuft alles
und das -l zeigt seine Wirkung. Ich habe wohl vorher den Fehler
gemacht, die named Pipe wie eine normale Datei anzusehen und
habe immer mit tail gearbeitet. Anscheinend ist das aber nicht so ;)

Also:
Code: (dl )
1
2
tcpdump -l -e -q -n -i eth0 icmp >/root/logpipe
cat /root/logpipe

funktioniert!!

Code: (dl )
1
2
tcpdump -l -e -q -n -i eth0 icmp >/root/logpipe
tail -f /root/logpipe

funktioniert NICHT!

Code: (dl )
1
2
tcpdump -l -e -q -n -i eth0 icmp >/root/logfile
tail -f /root/logfile

funktioniert auch. Aber ne Datei ist bei 2-3Tage LAN-Party ziemlicher
Murks (Die arme Platte ;) )

Besten Dank nochmal !!!!!!!!!!!! Manchmal sieht man den Wald
vor Bäumen nicht. In Perl habe ich ja auch mit while<LOGPIPE>
wie cat gearbeitet.

Ich seh das Licht am Ende des Tunnels. Nächstes Wochenende ist die
LAN und ich hoffe, ich kriege bis dahin noch die Mgmt-Scripte fertig.

Gruß
Bernd
dino03
 2007-01-06 17:06
#37432 #37432
User since
2007-01-04
3 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hier das Ergebnis (Super-Quick-And-Durty-Version)

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/perl
# ===== Aktiver ARP-Scanner =====

if ($pid1 = fork)
{ # ===== PARENT-PROZESS =====
print "Parent ($$) hat fork 1 durchgefuehrt \n";

if ($pid2 = fork)
{ # ===== PARENT-PROZESS =====
print "Parent ($$) hat fork 2 durchgefuehrt \n";
# ======================= PARENT-CODE ==============================
print "===== PARENT =====\n";
print "== ARP-Analyser ==\n";
print "==================\n";
print "tcpdump : $pid1 \n";
print "nmap : $pid2 \n";
print "reader : $$ \n";

open (LOGPIPE, "/root/logpipe") || die "konnte logpipe nicht oeffnen\n";
while (<LOGPIPE>) # Zeilen lesen
{
my $logline = $_; # Zeile sichern
print $logline; # Zeile ausgeben
chomp($logline); # Zeilenende entfernen

($layer2,$proto,$layer3) = split(/,/,$logline); # Zeile zerlegen
($tstamp,$smac,$d1,$dmac) = split(/ /,$layer2); # Layer2 zerlegen
($d0,$d1,$bytes,$d2,$d3,$aip,$d4,$amac) = split(/ /,$layer3); # Layer3 zerlegen
$bytes =~ s/://g; # Doppelpunkte vernichten

$angriff = ($smac ne $amac); # ARP-Angriff

print "TStamp : $tstamp #\n"; # Zeitstempel
print "SrcMAC : $smac #\n"; # Sollte identisch mit Answer-MAC sein
print "DstMAC : $dmac #\n"; # Sollte dieser PC sein

print "Bytes : $bytes #\n"; # Paketgroesse
print "AnswIP : $aip #\n"; # Sollte der angefragte PC sein
print "AnsMAC : $amac #\n"; # Sollte die MAC des Angefragten sein

if ($angriff) { print "ARP-Angriff!!\n"; }

}

# ==================================================================
exit;
}
else
{ # ===== CHILD-PROZESS 2 =====
die "fehler bei fork2: $!" unless defined $pid2;
print "Child 2 wurde gestartet : $$\n";
# ======================= CHILD2-CODE ==============================
print "===== CHILD 2 =====\n";
print "====== nmap =======\n";
print "===================\n";

while (1)
{
$d1 = `/usr/bin/nmap -sP 10.10.0.1-254`; # ARP-Scan durchfuehren
sleep (1); # Scan-Zyklus
}
print "nmap gestoppt \n";

# ==================================================================
waitpid($pid2,0);
}

exit;
}
else
{ # ===== CHILD-PROZESS 1 =====
die "fehler bei fork1: $!" unless defined $pid1;
print "Child 1 wurde gestartet : $$\n";
# ======================= CHILD1-CODE ==============================
print "===== CHILD 1 =====\n";
print "===== tcpdump =====\n";
print "===================\n";

$d1 = `/usr/sbin/tcpdump -l -e -q -n -i eth0 arp and not ether dst ff:ff:ff:ff:ff:ff >/root/logpipe`;
print "tcpdump gestoppt \n";

# ==================================================================
waitpid($pid1,0);
}


Ist die erste Testversion. tcpdump und nmap werden später (wenn ich
Zeit dafür habe) durch entsprechende Perl-Module ersetzt. arp-sk hat
leider für die Generierung von ARP-Requests zu lange gebraucht (nur
1er pro Sekunde).

Das ganze soll (ist tlw schon) ne LAN-Party-Überwachung werden.
- Wer steckt mit welcher IP/MAC an welchem Switchport
- Wieviel Traffic hat er auf dem Port und zum/vom Internet generiert
- Macht jemand Angriffe/Scans
- Erkennung von doppelten IPs
- Erkennung von Virus/Wurm-Ausbrüchen

Die ARP-Scans für die MAC-Erkennung haben dabei den Vorteil, das die
PC-Firewalls darauf nicht ansprechen (Nicht wie bei Ping). Der
Traffic wird per SNMP aus den Switchen gelesen .

Naja. So weit so gut :)
Ich weiß - das Script ist verbesserungswürdig ;)

Gruß
<< >> 6 Einträge, 1 Seite



View all threads created 2007-01-02 14:17.