Linux^2

Proxies mit Perl, LWP und SSL nutzenLinux

Posted by Jochen Wed, September 07, 2011 17:05:25

Das Problem:
Für ein kleines Projekt habe ich kürzlich eine Website abrufen und analysieren wollen. In Perl wahrlich kein Problem, die LWP-Module nehmen einem fast alle Arbeit ab. Allerdings hatte die einfache Aufgabe zwei kleine Haken, die sich in Summe zu einem Nachmittag "Recherchieren & Ausprobieren" ergänzten. Welche?

  • Die Kommunikation muss durch einen Proxy gehen
  • Die Website ist zwar per http zu erreichen, leitet aber direkt per Refresh auf die https-Version der Site weiter.

Grundsätzlich muss LWP erstmal mit SSL (dem "s" von "https") umgehen können. Dazu muss das Modul Crypt::SSLeay installiert sein. Liest man nun die Dokumentation zu LWP, sollte die folgende Vorgehensweise funktioneren:

Entweder die Umgebungsvariablen

http_proxy
ftp_proxy
https_proxy


(kleingeschrieben!) setzen und (wenn $ua unser LWP-Useragent ist)

$ua->env_proxy;

aufrufen. Oder direkt innerhalb von Perl

$ua->proxy( [ 'http', 'ftp', 'https' ], 'http://mein.proxy.de/3128');

aufrufen. Danach sollte jeder Request durch den Proxy geleitet werden. Das funktioniert sogar - aber leider nur mit Proxies, die wie mod_proxy des Apache Webservers funktionieren.

Andere Proxies wie der weit verbreitete Squid oder auch der MS-ISA verstehen die Methode von LWP aber nicht. Dummerweise gibt es keine Fehlermeldung, sondern ein "200 OK" für die Verbindung, aber mit leerem Body. Gemeint ist damit das Ergebnis für's GET zum Proxy, welches aber im Falle einer HTTPS-Verbindung ein CONNECT sein müsste...

Die Lösung:
Damit LWP::UserAgent für HTTPS-Verbindungen nicht seine fehlerhafte bzw. unpassende Art des Verbindungsaufbaus verwendet, darf für LWP kein Proxy für https gesetzt werden. Für http/ftp-Verbindungen jedoch muss der Proxy wie gewohnt gesetzt sein! Das Proxying für die HTTPS-Verbindungen übernimmt statt dessen Crypt::SSLeay, was für LWP::UserAgent vollkommen transparent ist.

Wie stellt man nun das Proxying für Crypt::SSLeay ein? Hier hilft die Dokumentation zum Modul weiter. Crypt::SSLeay beachtet einige Umgebungsvariablen, wobei hier HTTPS_PROXY (*Großschreibung beachten*) zum Zuge kommt. Auch hier eine kleine Falle, die es zu umgehen gilt: Die Schreibweise

HTTPS_PROXY=http://mein.proxy.de:3128/

funktioniert nicht, da Crypt::SSLeay vom abschließenden "/" irritiert wird. Die korrekte Schreibweise lautet also

HTTPS_PROXY=http://mein.proxy.de:3128

In der Praxis würde man entweder komplett auf Umgebungsvariablen zurückgreifen oder direkt im Perlskript alle notwendigen Werte setzen. Daher skizziere ich hier mal beide Herangehensweisen.

Proxying per Umgebungsvariablen:
In der Shell

PROXY=http://mein.proxy.de:3128 # Kein / am Ende!
http_proxy=$PROXY # Fuer LWP, kleingeschrieben
ftp_proxy=$PROXY # Fuer LWP, kleingeschrieben
HTTPS_PROXY=$PROXY # Fuer Crypt:SSLeay, großgeschrieben
export http_proxy ftp_proxy HTTPS_PROXY


und dann im Skript

use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
$ua->env_proxy;


Proxying komplett im Skript:

use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $proxy = 'http://mein.proxy.de:3128'; # Kein / am Ende!
$ua->proxy( [ 'http', 'ftp' ], $proxy); # Fuer LWP
$ENV{'HTTPS_PROXY'} = $proxy; # Fuer Crypt::SSLeay


In einigen Forumthreads im Web fand ich Diskussionen über den Zeitpunkt, an dem die Umgebungsvariable HTTPS_PROXY im Perlskript zu setzen sei. Die oben aufgeführte Variante funktioniert hier bei mir unter Perl 5.10.1 (Kubuntu 11.04), andere hatten scheinbar mehr Erfolg, wenn HTTPS_PROXY vor dem Laden der Module gesetzt wurde:

BEGIN { $ENV{'HTTPS_PROXY'} = $proxy; }
use LWP::UserAgent;


Damit sollte das Problem endgültig erschlagen sein. Die gleiche Vorgehensweise ist übrigens auch bei allen anderen Modulen nötig, die auf LWP zum Herunterladen von Daten per HTTP/HTTPS zurückgreifen, wie zum Beispiel WWW::Mechanize oder WWW::Mechanize::Shell.

Ich hoffe, der Tipp spart irgendjemand da draußen ein paar Stunden Herumbasteln...

bash: read unterstützt Zeilen mit NULL-EndeLinux

Posted by Jochen Mon, June 27, 2011 10:29:44

Folgendes Problem: In einem bash-Skript sollen Eingabezeilen verarbeitet werden. Die Eingabezeilen sind aber nicht mit Newlines beendet, sondern mit Nullbytes (ASCII-NUL, \0). Außerdem können Newlines und anderer Whitespace korrekter und zu erhaltender Inhalt der Zeilen sein.

Das Whitespace-Problem ist schnell gelöst: Einfach die shellinterne Variable IFS (internal field separator) setzen. Aber wie liest man NULL-terminierte Zeilen ein?

Dieses sehr informative, aber englische Blogeintrag zum Thema bash und read bietet die Lösung. Das Shell-Builtin read versteht unter anderem die Option "-d <delim>". Darüber kann man den Trenner für Eingabezeilen festlegen. Auch Nullbytes kann man festlegen - wenn man weiß, wie, denn der erste Anlauf '\0' funktioniert nicht!

Korrekte Lösung: Einfach einen Leerstring als Delimiter übergeben.

read -d '' LINE

Im Zusammenhang sähe eine Lösung dann so aus:

# Ursprünglichen IFS sichern
OLD_IFS="$IFS"

# IFS leeren, damit Whitespace nicht verändert wird
IFS=""

find . -print0 | while read -d '' LINE; do
# In LINE befindet sich nun eine unveränderte Ausgabezeile von find(1)
done

#Alten IFS restaurieren
IFS="$OLD_IFS"

ich hoffe, das hilft mal irgendwem weiter.

Jochen

Re-Hi... (en)gsm-ussd

Posted by Jochen Fri, June 03, 2011 13:04:49

Hi everyone,


as I've been quiet for a long time now, here's a little update. Version 0.4.0-25 is now available on the download page in deb-, rpm-, and tar.gz-flavors.


In short, this version should work as well (or not) as the previous version 0.3.3. I just added two more modems which require PDU mode to work. All the rest ist "just" a redesign of the whole thing. That is done and OK, IMHO. All I need now is the motivation to go on with all the other plans I have... smiley


My plans for version 4.1 include getting rid of that modem list for PDU mode modems. I'll simply try a cleartext USSD query first. If that fails, I'll simply repeat the query, this time PDU encoded. I hope that'll work out OK.


Best regards,

Jochen

Re-Hi... (de)gsm-ussd

Posted by Jochen Fri, June 03, 2011 12:56:54

Hi allerseits,


da ich ja nun sehr lange nichts mehr von mir habe hören lassen, hier ein kleines Update. Auf der Download-Seite steht die Version 0.4.0-25 zum Download parat, sowohl als tar-Archiv als auch als deb- und als rpm-Paket.


Im Großen & Ganzen sollte es diese Version genauso gut tun die 0.3.3. Hinzugekommen sind lediglich zwei weitere Huawei-Modems, die den PDU-Mode brauchen. Der ganze Rest ist "lediglich" ein Redesign, s. ein paar Posts früher. Der ist m.E. gelungen. Alles, was ist jetzt noch brauche, ist etwas mehr Motivation, meine anderen Pläne umzusetzen... smiley


Für die 4.1er Version möchte ich die Liste der Modems, die den PDU-Mode brauchen, rausschmeissen. Dazu werde ich im Falle eines fehlgeschlagenen ersten Versuchs (weil das Modem die USSD-Anfrage im Klartext nicht verstanden hat) einfach ein zweites Mal die Abfrage absetzen, dann aber PDU-kodiert. Mal sehen, ob das besser funktioniert.


Grüße an alle da draußen,

Jochen

Noch leichter... Even easier...gsm-ussd

Posted by Jochen Tue, June 15, 2010 22:29:37


Interessiert an der Entwicklungsversion von gsm-ussd, aber nicht an git? Einfach

http://linux.zum-quadrat.de/downloads

besuchen und das tar-Archiv herunterladen!


Interested in testing, but not willing to use the git repository? Just visit

http://linux.zum-quadrat.de/downloads

and download the tar archive of the development version!



Fortschritt! Progress!gsm-ussd

Posted by Jochen Tue, June 15, 2010 21:33:37

(English text follows further below.)

Hi da draußen,

gsm-ussd 0.4 macht Fortschritte! Am besten dabei: Es funktioniert immer noch. smiley
Zugegebenermaßen sieht man von außen nicht viel, aber der innere Aufbau hat sich schon recht stark verändert. Aus einem einzelnen Skript von 1500 Zeilen ist ein Skript von 250 Zeilen geworden, welches sich aber auf 8 Module von insgesamt 1900 Zeilen Perl-Code stützt! Damit ist der Umbau aber noch nicht abgeschlossen. Einige Methoden liefern noch Datenstrukturen zurück - ein Erbe ihrer Geburt als schlichte Funktionen. Diese Methoden werden nun aufgedröselt und ihre Rückgabewerte als einzelne Attribute ihrer Objekte zur Verfügung stellen.

Die interne Doku lässt momentan leider zu wünschen übrig. Das werde ich aber angehen, wenn ich die o.a. Methoden umgeschrieben habe.

Also, wenn ihr schon gsm-ussd anwendet, hier meine Bitte an Euch:
Bitte testet die Entwicklungsversion!

Es ist einfach:
$ git clone http://github.com/JochenHoch2/gsm-ussd
$ cd gsm-ussd
$ git checkout dev
$ ./bin/gsm-ussd.pl -d -m ... # Und was ihr sonst noch an Optionen benötigt.

Feedback wird sehr erwünscht unf geschätzt - Dankeschön!

Tschö & lasst von Euch hören,
Jochen


(English text starts here.)

Hi out there,

gsm-ussd 0.4 comes along nicely! And what's more: It even still works! smiley
Admittedly, there's not much to see from the outside. But the inner workings changed a lot. The single script of 1500 lines became a script of merely 250 lines, supported by 8 modules of 1900 lines of Perl code. But the reorganisation doesn't stop there. Some methods return data structures, a heritage of their birth as mere functions. These methods will be chopped up and provide their return values as attributes of their objects.

Internal documentation leaves a lot to be desired at the moment, but won't be tackled after the rewrite.

So, if you're already using gsm-ussd, here's my plea to you:
Please test the development version!

It's easy:
$ git clone http://github.com/JochenHoch2/gsm-ussd
$ cd gsm-ussd
$ git checkout dev
$ ./bin/gsm-ussd.pl -d -m ... # And whatever options you need

Feedback is strongly encouraged and appreciated - Thanks!

Bye & waiting to hear from you,
Jochen



gsm-ussd 0.3.3: Bugs away!gsm-ussd

Posted by Jochen Tue, June 08, 2010 19:30:55


v0.3.3 is out.

If my redesign of gsm-ussd is good for only one thing, it's ironing out the (last?) bugs in the stable version of gsm-ussd...

Singled out:
The options --cleartext/--no-cleartext didn't work (any more?).
A newline was missing in an error message.
A (seldom used) funtion had a typo in its name.

Reason enough for a bugfix release. Here it is:

http://linux.zum-quadrat.de/downloads/gsm-ussd_0.3.3-0.tar.gz
http://linux.zum-quadrat.de/downloads/gsm-ussd-0.3.3-0.noarch.rpm
http://linux.zum-quadrat.de/downloads/gsm-ussd_0.3.3-0_all.deb

Every download of gsm-ussd is here:
http://linux.zum-quadrat.de/downloads/index.html.

And the complete repository of gsm-ussd kan be found at
http://github.com/JochenHoch2/gsm-ussd.git
or
git://github.com/JochenHoch2/gsm-ussd.git

Have fun, it's working better now!
Jochen

gsm-ussd 0.3.3: Fehler weg!gsm-ussd

Posted by Jochen Tue, June 08, 2010 19:22:36

v0.3.3 ist raus.

Und wenn mein Redesign der Innereien von gsm-ussd nur einen einzigen Sinn hat, dann ist es der, aus der jetzigen stabilen Version weitere Fehler zu beheben...

Im Einzelnen:
Die Option --cleartext/--no-cleartext funktionierte nicht (mehr?).
Eine Fehlermeldung wurde ohne Newline am Ende der Zeile ausgegeben.
Eine Funktion hatte einen Buchstabendreher im Namen (wird aber so selten aufgerufen, dass es bis dato nicht entdeckt wurde).

In Summe also Grund für die neue Version. Hier ist sie:

http://linux.zum-quadrat.de/downloads/gsm-ussd_0.3.3-0.tar.gz
http://linux.zum-quadrat.de/downloads/gsm-ussd-0.3.3-0.noarch.rpm
http://linux.zum-quadrat.de/downloads/gsm-ussd_0.3.3-0_all.deb

Einen Überblick über alle gsm-ussd bezogenen Downloads sind hier:
http://linux.zum-quadrat.de/downloads/index.html.

Und das komplette git-Repository findet sich unter
http://github.com/JochenHoch2/gsm-ussd.git
oder
git://github.com/JochenHoch2/gsm-ussd.git

Viel Spaß damit, denn jetzt funktioniert's ein bisschen besser!
Jochen