Reguläre Ausdrücke aus Datei laden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
PNS-Richi
User
Beiträge: 68
Registriert: Donnerstag 17. Januar 2008, 01:48

Reguläre Ausdrücke aus Datei laden

Beitragvon PNS-Richi » Samstag 13. Dezember 2008, 19:36

Hallo,

ich hab zwar immer wieder in Python Programmiert, aber immer nur kleiner Sachen und dazwischen größere Pausen mit anderen Sprachen verbracht.

Nun will ich mich wieder mehr mit Python beschäftigen. FUSE und Netfilter.

Mein Problem nun:
Ich will Reguläre Ausdrücke Zeilenweise aus einer Textdatei Laden. Dies klappt auch so weit. Nur wenn ich die Reguläre Ausdrücke aus dieser Datei verwenden will gibts kein "matching" mehr. Also keiner der Ausdrücke ist passend. Wenn ich diese als String einfüge, also direkt in den Quellcode, dann funktioniert es.

Code: Alles auswählen

#! /usr/bin/env python
# -*- UTF8 -*-

import re
import ipqueue

f = open('/etc/l7-filter.reg', 'r')
regex = f.readlines()
f.close();

q = ipqueue.IPQ(ipqueue.IPQ_COPY_PACKET)
print "fileno is", q.fileno()
while 1:
   ipqueue_send=False
   
   t = q.read()

   for reg in regex:
      p = re.compile(reg.replace("\n", ""), re.IGNORECASE)
      m = p.match(t[9])
      if m:
         print "Drop returned:", q.set_verdict(t[0], ipqueue.NF_DROP)
         ipqueue_send=True
         break

   if ipqueue_send==False:
      print "Accept returned:", q.set_verdict(t[0], ipqueue.NF_ACCEPT)


Danke für eure Hilfe.

lg Richi
joshi
User
Beiträge: 8
Registriert: Sonntag 30. November 2008, 17:26

Beitragvon joshi » Samstag 13. Dezember 2008, 19:56

Ich denke, du musst die Datei im Modus 'rb' öffnen, da in deinen patterns wahrscheinlich backslashes sind, oder?
lunar

Beitragvon lunar » Samstag 13. Dezember 2008, 20:20

Und was hat der Backslash jetzt mit Binärdateien zu tun?

Dein Problem ist wohl – ohne das ich die Ausdrücke kennen – die Tatsache, dass ".match()" nur am Anfang der Zeichenkette, nicht aber an beliebigen Stellen sucht. Ich denke, du suchst ".search()".

Zu deinem Code noch ein paar Anmerkungen. Statt ".replace('\n', '')" besser ".rstrip('\n')". Desweiteren kannst du statt ".readlines()" auch über das Dateiobjekt iterieren. Zuguterletzt hat Python auch bool'sche Literale: "while True" ist die bessere Variante einer unbedingten Schleife.
PNS-Richi
User
Beiträge: 68
Registriert: Donnerstag 17. Januar 2008, 01:48

Beitragvon PNS-Richi » Samstag 13. Dezember 2008, 20:21

Hallo,

ist mir schon aufgefallen, ich hab es mit

Code: Alles auswählen

reg = reg.encode('utf-8').decode('string_escape').decode('utf-8')

gelöst.

Du meinst also so was wie:

Code: Alles auswählen

f = open('/etc/l7-filter.reg', 'r')
for reg in f:
   ...
f.close();


Ich wollte es direkt am Anfang in eine Variable laden. Ansonsten würde er doch bei jedem Schleifndurchgang die Datei erneut laden, oder?

"match" müsste reichen, ich will ja immer nur die ersten Teile einer Verbindung überprüfen, aber danke für den Hinweis. Theoretisch sollte man aber mit Regulären Ausdrücken das so flexibel gestallten das ich auch mit match einen treffer landen kann, wenn der Teil den ich brauche irgendwo in der mitte auftaucht, oder ich irre mich jetzt.

Falls du noch einen Hinweis/Tipp für mich hast nur raus damit, damit ich schnell in Python rein komme :)

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import re
import ipqueue

f = open('/etc/l7-filter.reg', 'r')
regex = f.readlines()
f.close();

q = ipqueue.IPQ(ipqueue.IPQ_COPY_PACKET)
print "fileno is", q.fileno()
while True:
   ipqueue_send=False
   
   t = q.read()
   print "I read a packet:", t
   #print "Accept returned:", q.set_verdict(t[0], ipqueue.NF_ACCEPT)

   for reg in regex:
      
      reg = reg.rstrip('\n')

      reg = reg.encode('utf-8').decode('string_escape').decode('utf-8')

      p = re.compile(reg, re.IGNORECASE)
      m = p.match(t[9])
      if m:
         print "Drop returned:", q.set_verdict(t[0], ipqueue.NF_DROP)
         ipqueue_send=True
         break

   if ipqueue_send==False:
      print "Accept returned:", q.set_verdict(t[0], ipqueue.NF_ACCEPT)
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Beitragvon str1442 » Samstag 13. Dezember 2008, 20:49

Die Datei wird einmal geladen und ist dann ein "iterable", wie eine Liste.
BlackJack

Beitragvon BlackJack » Samstag 13. Dezember 2008, 21:15

Nein nicht wie eine Liste. PNS-Richi macht das schon richtig. Über eine Datei kann mal nur einmal iterieren, über eine Liste beliebig oft. Natürlich könnte man die Datei erneut öffnen oder mit `seek()` wieder an den Anfang springen, aber ich denke eine Liste ist hier der bessere Weg.

@PNS-Richi: Dieses Tänzchen mit dem Kodieren habe ich nicht so recht verstanden? Was soll das mit UTF-8? Vor allem das Du am Anfang *enkodierst*!? Das ist Unsinn und fällt sofort auf die Nase wenn `reg` mal etwas ausserhalb von ASCII enthalten sollte.

Kannst Du die Ausdrücke nicht gleich richtig in die Datei schreiben, so dass sie nicht noch einmal nachbearbeitet werden müssen?

Ausserdem würde ich das vor der Endlosschleife machen und dann auch gleich in `re`-Objekte kompilieren, denn das Ergebnis ist ja immer das gleiche.
BlackJack

Beitragvon BlackJack » Samstag 13. Dezember 2008, 21:29

Ungetestet:

Code: Alles auswählen

import re
import ipqueue


def main():
    regex_file = open('/etc/l7-filter.reg', 'r')
    regexes = [re.compile(r.rstrip('\n'), re.IGNORECASE) for r in regex_file]
    regex_file.close()
   
    queue = ipqueue.IPQ(ipqueue.IPQ_COPY_PACKET)
    print "fileno is", queue.fileno()
   
    while True:
        packet = queue.read()
        print "I read a packet:", packet
       
        if any(r.match(packet[9]) for r in regexes):
            text, verdict = 'Drop', ipqueue.NF_DROP
        else:
            text, verdict = 'Accept', ipqueue.NF_ACCEPT
       
        print text, 'returned:', queue.set_verdict(packet[0], verdict)


if __name__ == "__main__":
    main()
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Beitragvon str1442 » Samstag 13. Dezember 2008, 22:48

Nein nicht wie eine Liste. PNS-Richi macht das schon richtig. Über eine Datei kann mal nur einmal iterieren, über eine Liste beliebig oft. Natürlich könnte man die Datei erneut öffnen oder mit `seek()` wieder an den Anfang springen, aber ich denke eine Liste ist hier der bessere Weg.


Natürlich. Ich hätte auch Generator sagen können, und wäre damit der Wahrheit doch näher gekommen. Aberwieviele Anfänger verstehen sofort das Konzept eines Generators und / oder kennen dieses? Wichtig war nur, das das Dateiobjekt genau einmal geladen wird und es sich dann (im Gebrauch mit einer einfachen Forschleife) wie eine Liste (die nunmal das Objekt ist, mit dem Forschleifen eingeführt werden) verhält.
lunar

Beitragvon lunar » Samstag 13. Dezember 2008, 23:08

Das ist so trotzdem irreführend. Ein fundamentaler Unterschied zwischen einer Iteration über einer Liste und der über einem Dateiobjekt ist, dass ersteres den Status der Liste selbst nicht ändert, letzteres dagegen den Dateizeiger verschiebt. Das kann bei geschachtelten Schleifen oder erneuter Iteration lustige Effekte haben ;)
PNS-Richi
User
Beiträge: 68
Registriert: Donnerstag 17. Januar 2008, 01:48

Beitragvon PNS-Richi » Sonntag 14. Dezember 2008, 00:21

Auszug aus der Datei mit den Regulären Ausdrücken:
[code=](E|E )(\\x00|\\xc5|\\xd4)
^(gnd[\x01\x02]?.?.?\x01|gnutella connect/[012]\.[0-9]\x0d\x0a|get /uri-res/n2r\?urn:sha1:|get /.*user-agent: (gtk-gnutella|bearshare|mactella|gnucleus|gnotella|limewire|imesh)|get /.*content-type: application/x-gnutella-packets|giv [0-9]*:[0-9a-f]*/|queue [0-9a-f]* [1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?:[1-9][0-9]?[0-9]?[0-9]?|gnutella.*content-type: application/x-gnutella|...................?lime)[/code]

Ein Paket von aMule:
[code=]
E\x00\x00\x86LR@\x00@\x06\x8bG\xc0\xa8\x00\x01H\xacY\x83\x96\x06\x125y#\xe9\xb9\xae\x96\xf53\x80\x18\x00\\\xd4\x01\x00\x00\x01\x01\x08\n\x01\x13\xa6A\x00\x00\x00\x00\xe3M\x00\x00\x00\x01\xf9\x19\xdde\x03\x0e\xf7\xa5\xd90N)\x1e\xc0o\x1a\x00\xd2\x00\x006\x12\x04\x00\x00\x00\x02\x01\x00\x01\x14\x00http://www.aMule.org\x03\x01\x00\x11<\x00\x00\x00\x03\x01\x00 \x1d\x07\x00\x00\x03\x01\x00\xfb\x80\x08\x04\x03[/code]

Also muss ich das ja escapen, oder kennt wer eine andere Lösung? DasProblem ist das ich von ähnlichen Lösungen die Regulären Aussdrücke übernehmen will und die unterschiedlich vorliegen.

Wenn ich nun
[code=](E|E )(\\x00|\\xc5|\\xd4)[/code]
in
[code=](E|E )(\x00|\xc5|\xd4)[/code]
ändere, muss ich nicht mehr escapen.

Das Script ist derzeit etwas unschön, soll ja auch nurmal zum testen reichen.

Im Endeffekt soll es die Firewall erweitern, da z.B.: Tauschbörsen auf verschiedenen Ports anzutreffen sind und irgendwie muss ich das ja unterbinden.

Danke für eure Hilfe.

@BlackJack: Danke für die schönere Strukturierung - hat mir einiges von der Python Syntax näher gebracht.

lg Richi

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder