Beschleunigung der Datenautobahn mit dem Proxy Squid

Auf der Überholspur

Anmerkung: Dieser Artikel erschien im PC Magazin Spezial 8/98. Die Fassung hier stellt den letzten Draft dar, die Fassung im Heft enthält noch einige kleine redaktionelle Änderungen.

An Staus auf der Datenautobahn gewöhnt man sich nie. Proxies sind gewissermassen virtuelle Parallelstraßen, die den Verkehr flüssig halten. Der Proxy Squid hält vielbesuchte Seiten lokal vor.

Was ist Squid?

Schon bald nachdem wortgewandte Menschen das Internet zur Datenautobahn erklärt hatten, trat auf diesem ein von realen Autobahnen wohlbekanntes Phänomen auf: Der Stau. Hier wie dort tritt dieser auf, wenn viele Menschen gleichzeitig, aber jeder für sich, über den gleichen Weg an den gleichen Ort wollen.

Allerdings ist das Problem bei Daten - zumindest im Prinzip - wesentlich leichter zu entschärfen: Wenn mehrere Leute in der selben Firma, am selben Institut, auf der selben Universität das gleiche Dokument anfordern, dann wäre es doch sinnvoller, es würde sich nicht jeder seinen Wunsch direkt an den Server richten, auf dem Dokument zu finden ist, sondern an einen Server im lokalen Netz. Dieser würde das Dokument bei der ersten Anfrage vom Ursprungsserver (origin server) holen, auf alle weiteren Anfragen könnte er dann antworten, ohne das Dokument über die langsame und teure internationale Leitung holen zu müssen. Damit war die Idee des caching proxy server geboren - caching, weil er die geholten Dokumente zur weiteren Verwendung eine Zeit lang aufbewahrt, proxy, weil er gegenüber den Origin-servern quasi als Stellvertreter oder Bevollmächtigter des eigentlichen Clients auftritt.

Dieses Prinzip läßt sich weiterspinnen. Innerhalb von Städten sind Datenleitungen relativ schnell und billig im Vergleich zu nationalen Leitungen. Es macht also Sinn, z.B. ein Dokument, das ein User auf der TU Wien benötigt, von der Uni Wien zu holen, wenn es dort bereits im Cache liegt, statt es neuerdings über den großen Teich zu holen. Nationale Leitungen sind wiederum billiger und schneller als kontinentale, und kontinentale billiger und schneller als transozeanische. So entsteht eine Hierarchie von Proxy-Servern, die ungefähr der Topologie des Internets nachgebildet ist. Wie es im Internet meist mehrere Routen zwischen zwei Hosts gibt, haben auch hier die meisten Proxies mehrere Nachbarn, so daß Ausfälle einzelner Proxies toleriert werden können. Für die Kommunikation zwischen den Proxies ist das TCP-basierte HTTP, über das normalerweise Webpages übertragen werden, zu schwerfällig, daher wurde ein eigenes "Internet Cache Protokoll" (ICP) entwickelt, das auf UDP aufsetzt.

Das Ergebnis ist eine lockere Hierarchie, in der jeder Server Anfragen an höherrangigere (parents) oder gleichrangige (siblings) stellen kann. Die Spitze der globalen Cache-Hierarchie bilden die 5 Squid-Server des National Laboratory for Applied Network Research (NLANR), die über die USA verstreut sind. Darum gruppieren sich nationale Caching-Proxies bzw. solche von internationalen Providern. Diese sprechen untereinander und mit den NLANR-Proxies. Daran schließen sich dann noch mehrere Levels von kleineren Providern, Universitäten und Firmen an.

Squid ist nicht der einzige Server, der ICP verwendet, und in diese Hierarchie eingebunden werden kann, aber sicher der am weitesten verbreitete. Wie die meisten Programme, die aktiven Anteil an der Weiterentwicklung der Infrastruktur des Internets haben, ist im Source-Code verfügbar und läuft auf den meisten Unix-Plattformen. Er ist skalierbar und flexibel genug, um das gesamte Spektrum vom Einbenutzer-Linux-System bis zum internationalen Cache mit hunderten Gigabytes Plattenplatz und mehreren T3's Netzanbindung abzudecken.

Das weltweite Cache-Netz
Weltkarte mit Squid-Servern Squid-Server (symbolische Darstellung)
Marktanteile der Proxy-Server in Europa
Tortengraphik

Installation

RedHat 5.1 enthält bereits zwei Squid-Versionen als Binary RPMs. Da die Standard-Squid-RPMs nur einen minimalen Satz an Features eincompiliert haben, ich in diesem Artikel aber auch auf einige andere Features eingehen möchte, ist auf der CD ein drittes RPM enthalten. Es enthält die derzeit (d.h., als dieser Artikel geschrieben wurde) aktuelle Version 1.2.22, wobei fast alle optionalen Features mit eincompiliert wurden.

Das RPM installieren Sie am einfachsten mit "rpm -Uvh /mnt/cdrom/.../squid-1.2.22-1hjp.rpm".

Grundkonfiguration

Die im RPM enthaltene Konfiguration entspricht der RedHat-Philosophie, daß die Software unmittelbar nach der Installation halbwegs funktionieren soll, und daß man sich um Dinge wie Performance, Stabilität und Sicherheit später kümmern kann. Daher sollten die ersten Maßnahmen darin bestehen, dafür zu sorgen, daß der Squid genügend Platz zum Arbeiten hat, daß er nur für die arbeitet, für die er arbeiten soll, und daß er nicht zuviel arbeitet. Dazu sollten Sie sich folgende Fragen überlegen:

Die Platzfrage hängt hauptsächlich von der Anzahl der Benutzer und deren Surfverhalten ab. Für den Heimanwender, der seine Modemleitung mit Ehegespons, Kindern und Hund teilt, sind 50-100 MB wahrscheinlich mehr als ausreichend. Für kleinere und mittlere Firmen oder wissenschaftliche Institute wird sich die sinnvolle Cache-Größe wahrscheinlich irgendwo in der Größenordnung von einem Gigabyte bewegen, bei sehr großen Firmen oder Institutionen oder gar überregionalen Caches sind zig Gigabyte keine Seltenheit. In der Default-Konfiguration legt Squid die gecachten Files unter /var/spool/squid ab. Dies kann man mit der Direktive cache_dir ändern. Die Größe läßt sich mit cache_swap einstellen, der Teil des Caches, der im RAM gehalten wird, mit cache_mem.

Die zweite Frage läßt sich meist durch Nachfrage beim Provider klären. Die meisten Provider verwenden Proxies, um ihre Leitungen zu entlasten und empfehlen Ihren Kunden auch, diese zu benutzen, allerdings sind diese Informationen meist nur für Browser-User gedacht, es gibt also keine Information darüber, ob der Proxy ICP spricht, und wenn ja, auf welchem Port. Eine Nachfrage beim Provider sollte dies klären.

Außerdem gibt es einige Registrationsservices, bei denen man nach potentiellen Nachbarn suchen kann. Auf jeden Fall sollte man den Administrator eines Caches vorher um Erlaubnis fragen, bevor man ihn als Sibling oder gar als Parent einträgt.

Die letzte Frage hängt teilweise von der zweiten ab. Natürlich will man seinen lokalen Usern Zugriff auf den Proxy gewähren, sonst wäre die Sache relativ sinnlos. Zusätzlich sollte man allen Squid-Servern, die man als Siblings eingetragen hat, ebenfalls Zugriff gewähren, sonst sind deren Administratoren beleidigt und drehen einem ebenfalls den Zugriff ab. Allerdings gibt es hier einem gewichtigen Unterschied: Während ein lokaler User Dokumente immer über den Proxy Server anfordern sollte, damit dieser Gelegenheit hat, diese zu cachen, sollte ein Sibling von einem anderen nur dann ein Dokument anfordern, wenn dieser es auch tatsächlich hat. Um zu verhindern, daß ein Sibling auch Dokumente anfordert, die man gar nicht hat, sollten Sie die Direktive miss_access verwenden.

Grundkonfiguration.
Annahme: Squid läuft auf Firewall. Internes Netz 192.168.0.0, Externe Anbindung über Modem oder Standleitung.
    http_port 3128	# default
    icp_port  3130 	# default

    cache_host proxy.provider.net parent 3128 3130 # parent kann ICP
    						   #   oder
    cache_host proxy.provider.net parent 8080    7 # parent kann nicht ICP

    cache_host proxy.nachbar.net sibling 3128 3130 # Ein Sibling,
    						   # IP adresse ist
						   # 192.1.2.3

    local_domain mein.netz

    cache_mem 32	# 32 MB RAM für cache
    cache_swap 512	# 0.5 Gig Disk-Space

    acl localnet 192.168.0.0/16

    acl nachbar 192.1.2.3/32

    http_access allow localnet 
    http_access allow nachbar 
    http_access deny all

    icp_access allow nachbar
    icp_access deny all

    miss_access allow localnet 
    miss_access deny all 	# nachbar darf nicht!
    

Performance-Tuning

Nachdem einmal alles läuft, wie es soll, kann man beginnen, sich Gedanken darüber zu machen, wie man die Performance verbessern kann. Die Performance eines Proxy-Servers ist naturgemäß dann am besten, wenn er ein Dokument aus seinem eigenen Cache liefert, ohne einen Parent oder gar den Origin-Server befragen zu müssen. Andererseits muß der Proxy wenigstens hin und wieder nachfragen, ob sich das Dokument geändert hat, damit er dem Client kein veraltetes Dokument liefert. Mit den hier beschriebenen Optionen kann man also einen den eigenen Ansprüchen angemessenen Kompromiss zwischen Aktualität und Performance finden.

Da die meisten Dokumente im WWW kein explizites Ablaufdatum besitzen, verwendet Squid eine Heuristik, um eines zu errechnen: Es gibt eine Mindestzeit, innerhalb der ein Dokument nicht ablaufen kann, und eine Maximalzeit, nach der es auf jeden Fall als abgelaufen betrachtet wird. Defaultmäßig sind diese Zeiten auf 0 Sekunden bzw. drei Tage gesetzt. Innerhalb dieser Zeit wird ein gewisser Prozentsatz des Alters (default 20%) zum Datum, an dem das Dokument geholt wurde, dazugezählt, um das Ablaufdatum zu berechnen.

Alle drei Parameter lassen sich mit dem Parameter refresh_pattern in Abhängigkeit vom URL ändern. Wenn Sie z.B. wissen, daß die Seiten einer Tageszeitung nur einmal am Tag upgedated werden, aber deren Webserver keine Last-Modified-Header mitschickt, könnten Sie z.B. mit

refresh_pattern/i ^http://www.tageszeitung.de 360 20% 4320

dafür sorgen, daß Pages von dieser Webseite nur maximal einmal in 6 Stunden (360 Minuten) geholt werden. Wenn Ihnen die Maximalzeit von 3 Tagen zu kurz erscheint, können Sie sie generell für alle Seiten auf 14 Tage (20160 Minuten) erhöhen:

refresh_pattern . 0 20% 20160

(Der Punkt matcht alle URLs, die mindestens 1 Zeichen lang sind, also alle). Wichtig ist hier, daß Die die refresh_pattern-Direktiven in der richtigen Reihenfolge angegeben werden, gültig ist immer die erste, die auf den entsprechenden URL passt.

Ein wunder Punkt bei Caching Servern sind immer dynamisch generierte Seiten. Zwar bietet HTTP einige Möglichkeiten, solche Seiten als nicht cachebar zu markieren, aber nicht alle Server halten sich daran. Daher bietet Squid die Möglichkeit, bestimmte URLs (durch Substring (cache_stoplist) oder Regular Expression (cache_stoplist_pattern) identifiziert) nicht zu cachen. Defaultmäßig sind hier die Strings "cgi-bin" und "?" eingetragen. Diese Liste können Sie bei Bedarf erweitern (".cgi", ".shtml" und ".asp" wären gute Kandidaten), oder völlig löschen, wenn Sie sich darauf verlassen, daß sich die Server an die Spielregeln halten (was die meisten ohnehin tun), und so möglicherweise etwas Performance gewinnen wollen.

Ein weiterer Punkt, wo Tuning not tut, ist die Kommunikation der Caching Server untereinander. Wenn ein Squid seine Nachbarn fragt, ob sie ein bestimmtes Dokument haben, muß er deren Antwort abwarten, Die Wartezeit muß lange genug sein, um zu gewährleisten, daß die Anfrage bis zum Nachbarn durchdringt und dieser Zeit hat, seinen Cache zu durchsuchen, und eine Antwort zurückzuschicken, aber darf nicht so lange sein, daß Transfers unzumutbar verlängert werden. Der default beträgt hier 2 Sekunden, bei langsamen bzw. überlasteten Leitungen oder Nachbarn kann es sinnvoll sein, den Wert von neighbor_timeout zu erhöhen.

Mit der Option source_ping kann man auch den Origin-Server wie einen Nachbarn behandeln. In diesem Fall wird die Seite direkt vom Origin-Server geholt, wenn er am schnellsten antwortet. Da ein Webserver im allgemeinen nicht ICP spricht, wird dazu der Echo-Port mißbraucht, was den Unmut der betroffenen Systemadministratoren nach sich ziehen könnte, ganz abgesehen davon, daß die Effektivität dieser Maßnahme durch die immer größere Verbreitung von Firewalls eher zweifelhaft ist.

Schließlich stellt sich die Frage, woher ein Dokument geholt werden soll, wenn keiner der Nachbarn es hat. Direkt vom Origin Server oder von einem der Parents, und wenn letzteres, von welchem? Mit der Option cache_host_domain kann man für jeden Nachbarn mit angeben, für welche Domains er (nicht) befragt werden soll. Mit "query_icmp on" wird diese Auswahl automatisiert. In diesem Fall werden ICMP echo requests (wie in ping) verwendet, um die Entfernung eines Servers festzustellen. Wenn dies auch die Nachbarn tun, kann derjenige Nachbar ausgewählt werden, der dem gesuchten Server am nächsten ist.

Der letzte Punkt in unserer Tuning-Liste betrifft die Option quick_abort, mit der festgelegt wird, ob ein Download, der vom Client abgebrochen wurde, zu Ende geführt wird. Dies ist hauptsächlich für Sites mit wenigen Usern und langsamer Anbindung ans Internet (z.B. Modem) interessant, da hier einzelne Transfers mehr ins Gewicht fallen, und die Wahrscheinlichkeit, daß ein abgebrochener Transfer (eventuell von einem anderen User) wiederholt wird, geringer ist. Ähnlich wie die Option refresh_pattern hat auch quick_abort drei Parameter: Wenn von einem Transfer noch weniger alsals der erste Parameter fehlt, wird er fortgesetzt, wenn mehr als der letzte Parameter fehlt, wird er abgebrochen. Dazwischen entscheidet der mittlere. Wurde bereits mehr als der angegebene Prozentsatz des Files geladen, dann wird der Transfer fortgesetzt. Per default werden alle Transfers zu Ende geführt.

Log-Files

Squid legt drei Log-Files an, das cache.log, das store.log und das access.log (alle drei per default unter /var/log/squid). Das erste enthält informative und Fehlermeldungen, und ist hauptsächlich für menschliche Leser gedacht. Die anderen beiden sind zur Auswertung durch Statistik-Scripts gedacht, und enthalten jeweils eine Zeile mit mehreren Feldern für jedes relevante Ereignis. Wie die Namen vermuten lassen, enthält store.log Informationen über Ereignisse, die das Lesen, Schreiben und Löschen von Files im Diskcache betreffen, access.log hingegen Zugriffe von Clients (User-Agents oder andere Caching-Server).

Eine weitere Quelle von Informationen bildet das CGI-Script cache_mgr.cgi. Dieses fragt etliche Statistiken direkt vom laufenden Squid ab und stellt sie in menschenlesbarer Form dar. Viele davon (z.B. Verbrauch an RAM oder Filedescriptoren) werden sonst nirgends mitgeschrieben, speziell in der Anfangsphase sollte man also dieses Script öfters anwerfen, um ein Gefühl für den Ressourcenhunger des Tintenfischchens zu bekommen.

Der große Nachteil davon ist, daß diese Statistiken immer nur für die Zeit seit dem letzten Start des Servers gelten und keinerlei Trends aufzeigen. Dazu müsste man die Informationen regelmäßig abfragen und die Änderungen auswerten.

Dieses Problem (braucht das keiner außer mir?) scheinen auch die meisten der Scripts zu haben, die zur Auswertung der Access-Logs geschrieben wurden. Auf der Squid-Homepage findet man einige, von denen vor allem die NLANR-Scripts und Calamaris erwähnenswert sind. Erstere vor allem, weil sie Summaries erzeugen, die man leicht in eigenen Scripts weiterverarbeiten kann, letzteres weil es einen sehr umfassenden Report (wahlweise ASCII oder HTML) ausgibt.

Für die Graphikfreunde schaut es eher traurig aus. Hier finden Programmierer, die mit kleinen Programmen große Freude machen wollen, noch ein Feld, wo sie sich austoben können!

Außer den Default-Informationen können über spezielle Optionen noch etliche weitere Informationen mitgeloggt werden. So können z.B. mit "log_mime_hdrs" die vollen HTTP-Header der Requests und Antworten mitgeloggt werden. Bei einem normalen Caching Server ist diese Option eher sinnlos, sie kann aber z.B. sehr gut dazu eingesetzt werden, das Verhalten von verschiedenen Clients und Servern mitzuprotokollieren. Mit "useragent_log" kann man die verwendeten Browser mitprotokollieren. Die Optionen ident_lookup und log_fqdn sind normalerweise aus Performance-Gründen deaktiviert. Die erste fragt bei jedem Request den Client nach einer User-ID, die zweite trägt statt der numerischen IP-Adresse den Domainnamen ein, was bei einer großen Anzahl an Clients ebenfalls ein Bottleneck werden kann.

Squid ist auch in der Lage, Logfiles bei Empfang des Signals SIGUSR1 zu switchen. Die Option "logfile_rotate" gibt dabei an, wieviele Generationen an Logfiles aufbewahrt werden sollen. Wird 0 angegeben, dann benennt Squid die Logfiles nicht selbst um, sondern öffnet das aktuelle Logfile nur neu. Der Administrator kann dann selbst ein ihm sinnvoll erscheinendes Namensschema für alte Logfiles (z.B. access.log.YYYY-MM-DD) vergeben.

Tarnen und Täuschen

Das Jahr 1984 ist zwar schon einige Zeit vergangen, aber eifrige Datensammler und -Auswerter sind überall im Internet und an seinen Rändern am Werk. Um diesen das Leben ein bißchen schwerer zu machen, hat Squid einige Optionen, mit denen man seine Mitteilsamkeit einschränken kann.

Da ist zunächst "forwarded_for". Normalerweise fügt jeder Squid in den Request eine Header Zeile "X-Forwarded-For: IP-Adresse" ein. Wenn Sie der Meinung sind, daß die IP-Adressen der Rechner in Ihrem privaten Netz einen Webserver nichts angehen, können Sie diese Option abschalten.

Wenn Sie außerdem der Meinung sind, daß Ihre Browser den Servern viel zu viel über sich erzählen, dann können Sie mittels http_anonymizer dafür sorgen, daß der Squid entweder gewisse Header herausfiltert, oder nur gewisse Header durchlässt. Schließlich können Sie noch mittels "fake_user_agent" einen anderen Browser vortäuschen.

Noch sensibler als die Daten, die irgendwelche Server jenseits des Atlantik mitbekommen könnten, sind aber die Daten, die sich in den eigenen Logfiles ansammeln. Diese Spuren lassen sich mittels client_netmask etwas verwischen. Wenn Sie z.B. im internen Netz Adressen der Form 192.168.x.y verwenden, wobei x für jede Abteilung anders ist, können Sie mittels client_netmask 255.255.255.0 erreichen, daß in allen Logfiles de facto nur mehr die Abteilung, aber nicht der einzelne PC aufscheint.

Schließlich und endlich gibt es noch die Möglichkeit, Zugriffe auf bestimmte URLs durch ein redirect_programs umzulenken. Beispielsweise lenke ich bei mir zu Hause alle URLs, die offensichtlich Bannerpages referenzieren, auf ein kleines schwarzes GIF am lokalen Server um. Das macht zum Beispiel Alta Vista oder die Internet Movie Database über Modem gleich um einiges brauchbarer.

Ausblick auf 1.2

Version 1.2 befindet sich bereits im fortgeschrittenen Beta-Stadium, wenn Sie sich nicht scheuen, die Software selbst zu holen und zu kompilieren, dann können Sie schon einen Blick auf einige neue Features werfen, darunter:

Cache-Digests:
Diese stellen sozusagen ein Inhaltsverzeichnis eines Cache-Servers dar, das dieser in regelmäßigen Abständen mit seinen Nachbarn austauscht. Dadurch weiß jeder Caching-Server ungefähr, welche URLs auf welchem Nachbarn zu finden sind, und muß nicht für jeden Request nachfragen.
URNs, also "Universal Resource Names":
Ein URN ist ein Serverunabhängiger Name für eine (möglicherweise gespiegelte) Resource. Im Squid ist dies so implementiert, daß nach einer fixen Konvention aus dem URN ein URL gebildet wird, der eine Liste weiterer URLs liefert. Aus dieser Liste sucht sich der Squid dann den nächsten aus.
URLs:
Squid-Homepage:
http://squid.nlanr.net/Squid
Registraturen:
http://ircache.nlanr.net/Cache/Tracker/
http://www.terena.nl/task-forces/tf-cache/cache-register/