www.fabiankeil.de/blog-surrogat/2008/02/01/privoxy-3.0.8.html

Neues in Privoxy 3.0.8

Vor nicht ganz zwei Wochen haben wir Privoxy 3.0.8 veröffentlicht, und damit 3.0.6, die letzte stabile Version, abgelöst. Eine weitesgehend vollständige Liste der Änderungen gibt es wie immer im ChangeLog, hier stelle ich daher nur eine Auswahl der Neuerungen vor:

Doch zuerst eine kleine Werbe-Unterbrechung: Bunter Log-Pr0n wird Ihnen präsentiert von ... Privoxy-Log-Parser. Sollte es beim Betrachten der Logs nicht-triviale Darstellungs-Probleme geben, würde ich mich über einen Hinweis freuen.

Tags

Frühere Privoxy-Versionen waren bereits recht flexibel über URL-Muster zu konfigurieren, für manche Dinge reicht das aber nicht aus, also mussten Tags her. Tags sind Zeichenketten, die auf Basis von Header-Inhalten erzeugt werden, und aufgrund derer die Aktionen verändert werden können. Ein naheliegendes Beispiel:

14:19:41.488 283b6000 Header: GET http://www.cigital.com/silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3 HTTP/1.1
14:19:41.488 283b6000 Header: Tagger 'client-ip-address' added tag 'IP-ADDRESS: 10.0.0.1'. No action bits update necessary.
14:19:41.488 283b6000 Header: Tagger 'http-method' added tag 'GET'. No action bits update necessary.
14:19:41.488 283b6000 Header: Tagger 'complete-url' added tag 'http://www.cigital.com/silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3'. No action bits update necessary.
14:19:41.488 283b6000 Header: scan: Host: www.cigital.com
14:19:41.488 283b6000 Header: scan: User-Agent: fetch libfetch/2.0
14:19:41.489 283b6000 Header: Tagger 'user-agent' added tag 'User-Agent: fetch libfetch/2.0'. Action bits updated accordingly.
14:19:41.489 283b6000 Header: scan: Connection: close
14:19:41.489 283b6000 Header: Modified: User-Agent: Mozilla/5.0 (X11; U; NetBSD amd64; no-NO; rv:1.8.1.11) Gecko/20071217 Firefox/2.0.0.11
14:19:41.490 283b6000 Connect: Overriding forwarding settings based on 'forward .'
14:19:41.490 283b6000 Header: New HTTP Request-Line: GET /silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3 HTTP/1.1
14:19:41.490 283b6000 Redirect: Decoding /silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3 if necessary.
14:19:41.490 283b6000 Redirect: Checking /silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3 for redirects.
14:19:41.490 283b6000 Request: www.cigital.com/silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3
14:19:41.490 283b6000 Connect: to www.cigital.com
14:19:42.505 283b6000 Header: scan: HTTP/1.1 302 Found
14:19:42.505 283b6000 Header: scan: Date: Sun, 27 Jan 2008 13:19:42 GMT
14:19:42.506 283b6000 Header: scan: Server: Apache
14:19:42.506 283b6000 Header: scan: X-Powered-By: PHP/4.3.10
14:19:42.506 283b6000 Header: scan: X-Pingback: http://www.cigital.com/silverbullet/xmlrpc.php
14:19:42.506 283b6000 Header: scan: Expires: Wed, 11 Jan 1984 05:00:00 GMT
14:19:42.506 283b6000 Header: scan: Last-Modified: Sun, 27 Jan 2008 13:19:42 GMT
14:19:42.506 283b6000 Header: scan: Cache-Control: no-cache, must-revalidate, max-age=0
14:19:42.506 283b6000 Header: scan: Pragma: no-cache
14:19:42.506 283b6000 Header: scan: X-PodPress-Location: http://www.cigital.com/silverbullet/shows//silverbullet-022.mp3
14:19:42.506 283b6000 Header: scan: Location: http://www.cigital.com/silverbullet/shows//silverbullet-022.mp3
14:19:42.506 283b6000 Header: scan: Content-Length: 0
14:19:42.506 283b6000 Header: scan: Connection: close
14:19:42.506 283b6000 Header: scan: Content-Type: text/html; charset=UTF-8
14:19:42.506 283b6000 Header: Tagger 'content-type' added tag 'text/html'. No action bits update necessary.
10.0.0.1 - - [27/Jan/2008:14:19:42 +0100] "GET http://www.cigital.com/silverbullet/podpress_trac/web/27/0/silverbullet-022.mp3 HTTP/1.1" 200 0
14:19:42.521 283b6500 Header: GET http://www.cigital.com/silverbullet/shows//silverbullet-022.mp3 HTTP/1.1
14:19:42.522 283b6500 Header: Tagger 'client-ip-address' added tag 'IP-ADDRESS: 10.0.0.1'. No action bits update necessary.
14:19:42.523 283b6500 Header: Tagger 'http-method' added tag 'GET'. No action bits update necessary.
14:19:42.523 283b6500 Header: Tagger 'complete-url' added tag 'http://www.cigital.com/silverbullet/shows//silverbullet-022.mp3'. No action bits update necessary.
14:19:42.524 283b6500 Header: scan: Host: www.cigital.com
14:19:42.524 283b6500 Header: scan: User-Agent: fetch libfetch/2.0
14:19:42.525 283b6500 Header: Tagger 'user-agent' added tag 'User-Agent: fetch libfetch/2.0'. Action bits updated accordingly.
14:19:42.526 283b6500 Header: scan: Connection: close
14:19:42.527 283b6500 Header: Modified: User-Agent: Mozilla/5.0 (X11; U; NetBSD amd64; no-NO; rv:1.8.1.11) Gecko/20071217 Firefox/2.0.0.11
14:19:42.528 283b6500 Connect: Overriding forwarding settings based on 'forward .'
14:19:42.528 283b6500 Header: New HTTP Request-Line: GET /silverbullet/shows//silverbullet-022.mp3 HTTP/1.1
14:19:42.528 283b6500 Redirect: Decoding /silverbullet/shows//silverbullet-022.mp3 if necessary.
14:19:42.528 283b6500 Redirect: Checking /silverbullet/shows//silverbullet-022.mp3 for redirects.
14:19:42.528 283b6500 Request: www.cigital.com/silverbullet/shows//silverbullet-022.mp3
14:19:42.528 283b6500 Connect: to www.cigital.com
14:19:42.916 283b6500 Header: scan: HTTP/1.1 200 OK
14:19:42.916 283b6500 Header: scan: Date: Sun, 27 Jan 2008 13:19:42 GMT
14:19:42.917 283b6500 Header: scan: Server: Apache
14:19:42.917 283b6500 Header: scan: Last-Modified: Mon, 21 Jan 2008 21:32:52 GMT
14:19:42.917 283b6500 Header: scan: ETag: "4c0bfe-1dad880-47950f84"
14:19:42.917 283b6500 Header: scan: Accept-Ranges: bytes
14:19:42.917 283b6500 Header: scan: Content-Length: 31119488
14:19:42.917 283b6500 Header: scan: Connection: close
14:19:42.917 283b6500 Header: scan: Content-Type: audio/mpeg
14:19:42.917 283b6500 Header: Tagger 'content-type' added tag 'audio/mpeg'. No action bits update necessary.
10.0.0.1 - - [27/Jan/2008:14:26:43 +0100] "GET http://www.cigital.com/silverbullet/shows//silverbullet-022.mp3 HTTP/1.1" 200 31119488

Im obigen Log-Auszug sind vier Tagger aktiv, die auch alle bereits in der Standard-Filter-Datei vorhanden sind. Lediglich das vom user-agent-Tagger erzeugte Tag ändert die aktiven Aktionen, hier um über die ebenfalls neue forward-override-Aktion für eine direkte Verbindung zu sorgen. Ohne Tags würden die Standard-Forward-Einstellungen gelten, in meinem Fall wäre das Tor.

Wer bereits eigene Filter geschrieben hat, sollte keine Probleme beim Taggen haben: Tagger sind aus Privoxys Sicht nur eine weitere Filterart und die Syntax ist die gleiche. Der user-agent ist wie die meisten Tagger (und Header-Filter) ein Zweizeiler:

CLIENT-HEADER-TAGGER: user-agent Tags the request with the complete User-Agent header.
s@^User-Agent:.*@$0@i

Übersetzt: für alle vom Client gesetzten Header, die mit User-Agent: anfangen, wird der ganze Header vom regulären Ausdruck erfasst und als Tag gespeichert.

Um nun die Aktionen auf Basis des erzeugten Tags zu ändern, wird eine Sektion wie die folgende verwendet:

{+forward-override{forward .} \
 -hide-if-modified-since      \
 -overwrite-last-modified     \
 -filter                      \
 -deanimate-gifs              \
 -inspect-jpegs               \
 -kill-popups                 \
}
TAG:^User-Agent: fetch

Anstelle des altbekannten URL-Musters wird über die TAG:-Zeile ein Tag-Muster angegeben. Eine Sektion kann gleichzeitig Tag- und URL-Muster haben, Tag-Muster werden aber grundsätzlich nach den URL-Mustern ausgewertet.

Annahme abgefangener Anfragen

Privoxy selbst fängt nach wie vor keine Anfragen ab, kann aber zusammen mit einem Paket-Filter genutzt werden, um einen HTTP-Abfang-Proxy zu bauen.

In Privoxy wird dazu die accept-intercepted-requests-Option aktiviert, anschließend werden vom Paket-Filter umgeleitete Anfragen akzeptiert und die Ziel-Adresse aus Host-Header und Pfad zusammen gebastelt:

18:03:18.776 283b6200 Header: Destination extracted from "Host:" header. New request URL: http://config.privoxy.org/show-status
18:03:18.777 283b6200 Header: GET /show-status HTTP/1.1
18:03:18.777 283b6200 Header: Tagger 'client-ip-address' added tag 'IP-ADDRESS: 192.168.0.49'. No action bits update necessary.
18:03:18.778 283b6200 Header: Tagger 'http-method' added tag 'GET'. No action bits update necessary.
18:03:18.778 283b6200 Header: scan: Host: config.privoxy.org
18:03:18.778 283b6200 Header: scan: Accept: */*
18:03:18.778 283b6200 Header: scan: User-Agent: Böser Client mit defekten Proxy-Einstellungen
18:03:18.779 283b6200 Header: Tagger 'user-agent' added tag 'User-Agent: Böser Client mit defekten Proxy-Einstellungen'. No action bits update necessary.
18:03:18.779 283b6200 Header: Modified: User-Agent: Mozilla/5.0 (X11; U; SunOS sun4u; en-CA; rv:1.8.1.11) Gecko/20071218 Firefox/2.0.0.11
18:03:18.783 283b6200 Header: Adding: Connection: close
18:03:18.783 283b6200 Connect: Overriding forwarding settings based on 'forward 10.0.0.1:8123'
18:03:18.783 283b6200 Header: New HTTP Request-Line: GET http://config.privoxy.org/show-status HTTP/1.1
18:03:18.815 283b6200 Request: config.privoxy.org/show-status (CGI Call)
192.168.0.49 - - [27/Jan/2008:18:03:18 +0100] "GET /show-status HTTP/1.1" 200 18903

Der böse Client hat versucht, Privoxy zu umgehen und direkt über das Gateway 192.168.0.1 mit der Außenwelt zu kommunizieren, im Tag IP-ADDRESS: 192.168.0.49 wurde daher die LAN-Adresse meines Rechners gespeichert. Im ersten Log-Auszug hatte sich fetch dagegen direkt an Privoxy gewandt, die Anfrage kam folglich von der lokalen Jail-Adresse 10.0.0.1.

Filterung komprimierter Inhalte

Bis Privoxy 3.0.6 musste prevent-compression genutzt werden, um sicherzustellen, dass keine komprimierten Inhalte verschickt wurden, die Privoxy nicht filtern konnte. Dank eines Patches von Wil Mahan ist das seit Privoxy 3.0.7 nicht mehr notwendig: über zlib werden sowohl gzip- als auch deflate-kodierte Inhalte dekomprimiert und anschließend gefiltert.

Die Einsparungen beim Daten-Transfer sind nicht von schlechten Eltern:

16:47:14.577 283b6500 Re-Filter: Decompression successful. Old size: 1968, new size: 11613. (saved: 83.05%)
16:47:15.376 283b5700 Re-Filter: Decompression successful. Old size: 591, new size: 2624. (saved: 77.48%)
16:47:16.124 283b5f00 Re-Filter: Decompression successful. Old size: 1333, new size: 7553. (saved: 82.35%)
16:47:17.091 283b5c00 Re-Filter: Decompression successful. Old size: 588, new size: 1818. (saved: 67.66%)
16:47:18.016 283b6000 Re-Filter: Decompression successful. Old size: 424, new size: 1260. (saved: 66.35%)
16:47:18.993 283b6900 Re-Filter: Decompression successful. Old size: 403, new size: 1023. (saved: 60.61%)
16:47:20.318 283b6200 Re-Filter: Decompression successful. Old size: 998, new size: 4934. (saved: 79.77%)
16:47:21.462 283b5500 Re-Filter: Decompression successful. Old size: 454, new size: 1554. (saved: 70.79%)
16:47:22.279 28375700 Re-Filter: Decompression successful. Old size: 582, new size: 2445. (saved: 76.20%)
16:47:23.328 283b5600 Re-Filter: Decompression successful. Old size: 698, new size: 2624. (saved: 73.40%)
16:47:25.076 283b6300 Re-Filter: Decompression successful. Old size: 502, new size: 1975. (saved: 74.58%)
16:47:26.033 283b5b00 Re-Filter: Decompression successful. Old size: 339, new size: 1026. (saved: 66.96%)
16:47:27.286 283b5d00 Re-Filter: Decompression successful. Old size: 2343, new size: 12889. (saved: 81.82%)
16:47:28.710 283b6600 Re-Filter: Decompression successful. Old size: 1837, new size: 8742. (saved: 78.99%)
16:47:30.006 283b5900 Re-Filter: Decompression successful. Old size: 209, new size: 368. (saved: 43.21%)
16:47:32.084 283b5800 Re-Filter: Decompression successful. Old size: 5290, new size: 29702. (saved: 82.19%)
16:47:33.300 283b6100 Re-Filter: Decompression successful. Old size: 930, new size: 2503. (saved: 62.84%)
16:47:34.389 283b5e00 Re-Filter: Decompression successful. Old size: 552, new size: 3780. (saved: 85.40%)
16:47:35.407 28375600 Re-Filter: Decompression successful. Old size: 820, new size: 2548. (saved: 67.82%)
16:49:11.345 28375700 Re-Filter: Decompression successful. Old size: 7883, new size: 36685. (saved: 78.51%)

Wie (und ob) sich das bei der Tor-Nutzung auf die Geschwindigkeit auswirkt habe ich noch nicht überprüft, habe allerdings den Eindruck, dass es kaum einen Unterschied ergibt, da die meiste Zeit beim Aufbau des Tunnels verbracht wird. Selbst wenn sich der subjektiv spürbare Nutzen in Grenzen hält, sollte es das Tor-Netzwerk insgesamt entlasten.

Bei einigen Servern scheint es noch Optimierungs-Möglichkeiten zu geben: bei Inhalten mit Größen bis zu wenigen hundert Bytes sind die Einsparungen deutlich kleiner und bei Größen unterhalb von hundert Bytes oft sogar im negativen Bereich.

Und auch wenn es bei kleineren Inhalten nicht so tragisch ist, wenn der Kompressions-Overhead die Datenmenge vergrößert, ist es doch eher albern zu versuchen, ein einzelnes Byte zu komprimieren:

16:32:54.122 28375600 Re-Filter: Decompression successful. Old size: 203, new size: 182. (saved: -11.54%)
16:32:54.370 283b5900 Re-Filter: Decompression successful. Old size: 92, new size: 77. (saved: -19.48%)
16:32:54.386 283b6300 Re-Filter: Decompression successful. Old size: 87, new size: 77. (saved: -12.99%)
16:45:47.461 28375600 Re-Filter: Decompression successful. Old size: 21, new size: 1. (saved: -2000.00%)
16:47:30.006 283b5900 Re-Filter: Decompression successful. Old size: 209, new size: 368. (saved: 43.21%)

Heimliche Zieländerung

Die heimliche Zieländerung ähnelt von der Funktion her Apaches Rewrite-Regeln, läuft aber statt auf dem Zielserver in Privoxy und kann sowohl Pfad als auch Server hinter dem Rücken des Browsers ändern.

Das macht nicht nur Man-In-The-Middle-Attacken weniger offensichtlich, sondern kann auch dazu genutzt werden, trotz verschlüsselter Verbindungen von Tors Exit-Relay-Notation Gebrauch zu machen, Tor also das Letzte Relay in der Kette vorzugeben.

Bei unverschlüsselten Verbindungen geht das problemlos über den Browser, bei verschlüsselten Verbindungen werden aber die Zertifikate nicht mehr akzeptiert, da die Exit-Relay-Notation den Host ändert.

Selbst bei unverschlüsselten Verbindungen kann die Kontrolle des Exit-Relays über Privoxy Vorteile haben; zum Beispiel wenn die Änderung dauerhaft sein soll, Referer- und Host-Header von Anfang an sauber bleiben sollen, oder um die Cookie-Konfiguration im Browser nicht an den neuen Host anpassen zu müssen.

Bei fehlerhafter Anwendung kann man sich mit der heimlichen Zieländerung auch ordentlich in den Fuß schießen, aber diese Möglichkeit besteht bei den meisten Privoxy-Optionen.

Für die heimliche Zieländerung werden normale Server-Header-Filter genutzt, wenn ein Filter die Request-Zeile umschreibt, passt Privoxy das Ziel automatisch an:

17:50:18.758 28376700 Header: CONNECT lists.sourceforge.net:443 HTTP/1.1
17:50:18.759 28376700 Header: Tagger 'client-ip-address' added tag 'IP-ADDRESS: 10.0.0.1'. No action bits update necessary.
17:50:18.759 28376700 Header: Tagger 'http-method' added tag 'CONNECT'. Action bits updated accordingly.
17:50:18.759 28376700 Header: scan: User-Agent: Mozilla/5.0 (X11; U; NetBSD amd64; en-ZW; rv:1.8.1.11) Gecko/20080112 Firefox/2.0.0.11
17:50:18.759 28376700 Header: Tagger 'user-agent' added tag 'User-Agent: Mozilla/5.0 (X11; U; NetBSD amd64; en-ZW; rv:1.8.1.11) Gecko/20080112 Firefox/2.0.0.11'. No action bits update necessary.
17:50:18.759 28376700 Header: scan: Proxy-Connection: keep-alive
17:50:18.759 28376700 Header: scan: Host: lists.sourceforge.net
17:50:18.759 28376700 Header: crumble crunched: Proxy-Connection: keep-alive!
17:50:18.760 28376700 Header: Transforming "CONNECT lists.sourceforge.net:443 HTTP/1.1" to "CONNECT lists.sourceforge.net.ad356ef8e87a89e6c898b74500d58607ac691178.exit:443 HTTP/1.1"
17:50:18.760 28376700 Re-Filter: 'slicklittlegirl-rewrite' hit 1 time, changing size from 42 to 88.
17:50:18.761 28376700 Header: Adding: Connection: close
17:50:18.761 28376700 Info: Rewrite detected: CONNECT lists.sourceforge.net.ad356ef8e87a89e6c898b74500d58607ac691178.exit:443 HTTP/1.1
17:50:18.761 28376700 Connect: Overriding forwarding settings based on 'forward-socks4a tor-jail:9050 .'
17:50:18.761 28376700 Request: lists.sourceforge.net.ad356ef8e87a89e6c898b74500d58607ac691178.exit:443/
17:50:18.761 28376700 Connect: to lists.sourceforge.net.ad356ef8e87a89e6c898b74500d58607ac691178.exit:443
10.0.0.1 - - [31/Jan/2008:17:50:23 +0100] "CONNECT lists.sourceforge.net.ad356ef8e87a89e6c898b74500d58607ac691178.exit:443 HTTP/1.1" 200 2804

Der verwendete Filter ist:

CLIENT-HEADER-FILTER: slicklittlegirl-rewrite Rewrite destination to use Tor server SlickLittleGirl as exit relay.
s@(\w+ http://[^/]*)(?<!\.exit)(/[^\s]* HTTP/\d\.\d)@$1.ad356ef8e87a89e6c898b74500d58607ac691178.exit$2@ig
s@(CONNECT [^:]*)(?<!\.exit)(:?.* HTTP/\d\.\d)@$1.ad356ef8e87a89e6c898b74500d58607ac691178.exit$2@ig

Da SlickLittleGirl bei den Verzeichnis-Servern nicht registriert ist, wird der Fingerabdruck ad356ef8e87a89e6c898b74500d58607ac691178 verwendet, um dafür zu sorgen, dass die Anfragen auch beim richtigen Mädchen rauskommen.

Inkompatible Änderungen

Beim Sprung von Privoxy 3.0.6 auf 3.0.8 sind zwei Syntax-Änderungen zu beachten: Aktions-Dateien müssen mit vollem Namen angeben werden und da jetzt reine Header-Filter verfügbar sind, wurde die Aktionen filter-client-headers und filter-client-headers entfernt.

Eine veraltete Konfigurations-Datei führt zu Fehlermeldungen wie:

19:14:27.747 28301100 Fatal error: can't load actions file 'default': No such file or directory. Note that beginning with Privoxy 3.0.7, actions files have to be specified with their complete file names.

Fehlerursache sind Zeilen wie:

actionsfile default

ab Privoxy 3.0.7 heißt es:

actionsfile default.action

da die Datei-Endung nicht mehr fest vorgegeben ist. Fehlermeldungen wie:

16:55:57.018 28301100 Fatal error: can't load actions file '/usr/local/etc/privoxy/fk.action': invalid line (1313): {+filter-client-headers +filter{hide-tor-exit-notation}}

lassen sich durch Ersatz von:

{+filter-client-headers +filter{hide-tor-exit-notation}}
/

durch:

{+client-header-filter{hide-tor-exit-notation}}
/

beheben. Wer die empfohlene Update-Strategie befolgt, vermeidet derartige Probleme natürlich von Anfang an.