Die gefühlte Internet-Geschwindigkeit mithilfe eines Raspberry Pi, Squid und pdnsd beschleunigen
Ich habe eine sehr langsame Internet-Verbindung (zwei MBit) und am Nachmittag wird es oft noch schnarchiger – vor allen Dingen die Latenz ist ein echtes Problem. Unter anderem sind auch die DNS-Anfragen langsam. Hat man ein Raspberry Pi zur Hand, kann man den stromsparenden Winzling als Cache einsetzen – sowohl für den Browser oder HTTP-Inhalte als auch für DNS-Anfragen. Das Raspbian bekanntlich auf Debian GNU/Linux basiert, geht das natürlich letzterem auch – oder mit jeder anderen Linux-Distribution, wobei sich Teile der Konfiguration unterscheiden können.
Ich setze das Ganze nun schon eine Weile ein. Allerdings ist das mit der Zeit gewachsen. Aus diesem Grund wurde auf eine separate SD-Karte ein komplett frisches Raspbian gespielt, damit ich das schrittweise zeigen kann.
Ich selbst stelle den Proxy-Server manuell am Browser ein. Der Grund ist ganz einfach, dass ich das Raspberry Pi auch anderweitig verwende. Würde ich einen transparenten Proxy für das Netzwerk aufsetzen, müsste das Raspberry Pi immer im Betrieb sein – oder ich müsste dauern am Router etwas ändern.
Die Schritte für einen transparenten Proxy sind anfangs aber gleich. Ich weise darauf hin, an welcher Stelle ich mein Raspberry Pi nicht weiter konfiguriert habe. Allerdings beschreibe ich mehr oder weniger den kompletten Weg, damit das Raspberry Pi zum Proxy-Server, DNS-Cache, Gateway und DHCP-Server.
Wichtiger Hinweis: Das Raspberry Pi ist bekanntlich ein sehr langsamer Computer. Mit zwei bis vier Rechnern gleichzeitig kann der Winzling ganz gut umgehen. Wird die Anzahl der Clients größer, ist das Raspberry Pi sicher nicht mehr schnell genug und das Setup ist kontraproduktiv. Somit müsste man in diesem Fall einen anderen Rechner nehmen, wie zum Beispiel eine ZBOX oder eben dem Netzwerk angemessen. Die Konfiguration ist allerdings äquivalent.
1. Schritt: Raspbian installieren und konfigurieren
Das gehört dazu, ich mache es aber kurz. Einfach das aktuelle Raspbian-Abbild holen (NOOBS oder vollständiges Image) und dann entsprechend installieren. Bei mir hat der Befehl so ausgesehen (ohne NOOBS):
sudo dd if=./2014-01-07-wheezy-raspbian.img of=/dev/sdc bs=1M
Wenn Du nun die SD-Karte in das Raspberry Pi steckst und startest, erscheint erst einmal die Grundkonfiguration. Diese lässt sich jederzeit via Konsole mit dem Befehl sudo raspi-config
aufrufen.
Ich habe dort erst einmal die Tastatur auf Deutsch umgestellt, OpenSSH aktiviert (da später headless – also ohne Monitor betrieben) und das Gerät so eingestellt, dass es im grafischen Modus startet.
Headless und grafischer Modus? Zunächst nicht headless und den grafischen Modus verwende ich deswegen, weil sich damit WLAN einfacher einrichten lässt. Mir ist es einfach zu blöd, mich mit der Datei /etc/wpa_supplicant/wpa_supplicant.conf plagen zu müssen, wenn es mit dem WiFi-Tool (WiFi Config) viel einfacher geht. Alternativ könnte man auch wicd-curses auf der Kommandozeile verwenden.
2. Schritt: Netzwerk fit machen
Wie bereits erwähnt, verwende ich eine WLAN-Karte (EDIMAX) und habe diese mit meinem WLAN verbunden. Ich hantiere in so einem Fall gerne mit festen IP-Adressen.
Diese könnte man im Raspberry Pi festlegen oder vom DHCP-Server zuweisen lassen (sofern der Heim-Router das kann). Sollte das Raspberry Pi später DHCP-Server werden, kommt man um die IP-Adresse im Raspberry Pi nicht herum. Das ist aber nun einfach, weil mir durch die Verwendung des grafischen WiFi-Tools die Arbeit mit der Datei /etc/wpa_supplicant/wpa_supplicant.conf bereits abgenommen wurde. Ich muss also nur noch die Datei /etc/network/interfaces editieren. Diese sieht bei mir nun so aus:
auto lo iface lo inet loopback iface eth0 inet dhcp allow-hotplug wlan0 iface wlan0 inet manual wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf iface wlan0 inet static address 192.168.100.50 netmask 255.255.255.0 gateway 192.168.100.1 # iface default inet dhcp
Entweder startet man nun das Netzwerk (ifup / ifdown) oder einfach das ganze Raspberry Pi neu. Nun überprüfst Du am besten, ob das Netzwerk sauber funktioniert. Ist das der Fall, kannst Du raspi-config aufrufen und ein Booten ohne grafische Oberfläche konfigurieren – gegebenenfalls nochmals Neustart. Wir brauchen das GUI nicht mehr, da das Netzwerk und OpenSSH läuft.
Es ginge auch mit Zeroconf
Wer nicht mit IP-Adressen hantieren möchte, könnte es auch mit Zeroconf lösen. Dazu musst Du lediglich das eintippen:
sudo apt-get install libnss-mdns
Danach wäre das Raspberry Pi per Standard unter raspberrypi.local erreichbar. Das geht aber nur dann, wenn die andere Stelle ebenfalls mit Zeroconf umgehen kann. Ubuntu und Linux Mint kann das zum Beispiel per Standard. Auch Mac OS X kann es (Zeroconf stammt schließlich von Apple). Windows kann es nur dann, wenn man die Treiber von Apple herunterlädt und installiert.
3. Per SSH auf das Raspberry Pi zugreifen und aktualisieren
Nun solltest Du von Deinem Linux-Rechner mittels ssh pi@192.168.100.50
auf das kopflose Raspberry Pi zugreifen können. Das Standard-Passwort, sofern nicht unter raspi-config geändert, ist raspberry.
Bevor wir nun irgendetwas machen, aktualisieren wir die Kiste erst einmal. Unter Debian / Raspbian geht das so.
sudo apt-get update sudo apt-get upgrade
4. tmpfs anlegen
Ich hatte hier schon einmal über tmpfs geschrieben und genau das verwenden wir später für Squid. Zuvor müssen wir das Mount-Verzeichnis allerdings noch kreiren: sudo mkdir /mnt/ramdisk
. Danach bearbeiten wir als root die Datei /etc/fstab (mit vi oder nano oder was weiß ich) und legen 150 MByte (also mir erschien das eine gute Zahl, da ich das locker frei habe) Ramdisk an:
tmpfs /mnt/ramdisk tmpfs nodev,nosuid,noexec,nodiratime,size=150M 0 0
Ich weiß, tmpfs würde im Gegensatz zu ramfs swap benutzen, ich brauche die Funktion aber nicht, da ich den Speicher in Squid limitiere. Warum ich die Squid-Daten überhaupt in eine Ramdisk lege? Erstens ist es schneller und zweitens schreibt mir das System nicht dauern etwas auf die SD-Karte. Sollte der Strom ausfallen, sind mir Cache-Dateien egal.
Nach dem Eintrag dieser Zeile entweder sudo mount -a
oder Neustart.
5. Squid installieren und konfigurieren
Ab nun geht es ans Eingemachte und wir installieren und konfigurieren den Proxy-Server Squid.
Anmerkung: Squid legt nur Seiten in den Cache, die mit http oder eben nicht verschlüsselt abgerufen wurden. Man kann es anders konfigurieren, bekäme dann aber Meldungen wegen ungültigen Zertifikaten und das Prinzip einer verschlüsselten Verbindung wäre außerdem über den Haufen geworfen. Es käme einem “Man in the Middle”-Angriff gleich.
sudo apt-get install squid3
Das lädt zirka zwei MByte herunter und die Installation dauert ein klein wenig. Nachdem diese abgeschlossen ist, kümmern wir uns um die Konfiguration – obwohl Squid bereits funktionieren würde (allerdings nur lokal – also auf dem Raspberry Pi). Probieren wir es trotzdem. Damit sehen wir, ob Squid überhaupt läuft. Ich konfigurieren den Proxy in Firefox manuell und setze diesen auf 192.168.100.5 mit dem Standard-Port 3128. Bei den Netzwerken schließe ich unten noch mein eigenes aus und trage ein: 192.168.100.0/24. Das Ganze sieht dann inklusive Fehlermeldung von Squid so aus.
Squid ist ein absolutes Monster und entsprechend groß ist auch die Konfigurations-Datei. Deswegen gehe ich nur auf die Parameter ein, die ich geändert oder angefasst habe. Zunächst einmal öffnen wir die Konfigurations-Datei als root. Sie liegt unter /etc/squid3/squid.conf.
Kümmern wir uns zunächst darum, dass unser Client oder Netzwerk Squid überhaupt benutzen darf. Dazu suchst Du die Sektio mit acl localnet src … oder die Überschrift Recommended minimum configuration. Für mein Netzwerk habe ich die Zeile eingefügt: acl localnet src 192.168.100.0/24. Das alleine reicht aber noch nicht, da ich localnet auch noch erlauben muss. Suche in der Konfigurations-Datei nach http_access allow localnet, das per Standard auskommentiert ist. Einfach das Kommentarzeichen wegnehmen und die Datei speichern.
Nun starten wir Squid neu und sehen uns das Ergebnis an -> Ok, kein Fehler mehr -> Squid funktioniert.
Squid auf tmpfs legen und andere Einstellungen
Da wird extra die Ramdisk angelegt haben, verschieben wir das Cache-Verzeichnis von Squid auch dort hin. Das erledigt der Parameter: cache_dir ufs /mnt/ramdisk 140 16 256, wobei die 140 für die MByte stehen. Die beiden anderen Zahlen sind für Verzeichnisse und Unterverzeichnisse für den Cache.
Starten wir Squid nun neu, bekommen wir eine Warnung: WARNING cache_mem is larger than total disk cache space. Wir sehen aber, dass die Verzeichnisse in der Ramdisk abgelegt werden.
Die Warnung bekommst Du weg, indem Du nach cache_mem suchst und diesen Parameter auch einfach auf 140 MB setzt.
Was mich nun noch persönlich stört, ist das Access-Log. Dieses hält sämtliche Zugriffe fest und Du kannst das auch überwachen: sudo tail -f /var/log/squid3/access.log
Ich weiß aber selbst, was ich aufrufe beziehungsweise interessiert mich das nicht. Das sind nur dauernde Schreibzugriffe auf der SD-Karte und deswegen stelle ich das Access-Log komplett ab. Suche nach dem Parameter access_log und setze diesen auf none.
Wenn Du nun Squid neu startest, sollte kein Zugriffs-Log mehr geschrieben werden und wir sind an dieser Stelle mit Squid zunächst durch. Einen Parameter möchte ich aber noch erwähnen, weil wir diesen später brauchen: dns_nameservers. Du könntest an dieser Stelle aufhören und Squid sogar die DNS-Server vorgeben. Da ich aber einen eigenen DNS-Server aufsetze, ändere ich diesen Parameter später auf: dns_nameservers 192.168.100.50. Er zeigt damit also auf sich selbst. Im Moment funktioniert das natürlich noch nicht.
Tipp – Squid zurücksetzen: Wer Squid komplett zurücksetzen möchte, muss den Daemon stoppen, die Verzeichnisse neu anlegen und den Service wieder starten
- sudo service squid3 stop
- sudo squid3 -z
- sudo service squid3 start
Persistent DNS-Cache / Proxy: pdnsd
pdnsd ist deswegen interessant, weil die Software DNS-Informationen auch nach einen Neustart vorhält. Normalerweise braucht meine Internet-Verbindung hier zwischen 200 und 500 ms, um eine DNS-Anfrage aufzulösen. Installiere ich pdnsd auf dem Raspberry Pi und verwende es, fallen diese Anfragen auf zirka zehn Millisekunden. Installieren wir das kleine Helferlein: sudo apt-get install pdnsd
Danach folgt die Frage der Software, wie sie sich denn verhalten soll. Im Endeffekt ist egal, was man verwendet, da man die Konfiguration anpassen kann. Allerdings liegt die Konfigurations-Datei je nach Wahl an anderer Stelle – was ein bisschen verwirrend sein kann und mir anfangs tatsächlich Kopfschmerzen bereitet hat. Ich habe mich für Option 1 – Resolvconf verwenden – entschieden.
Nach der Konfiguration stellen wir zunächst ein, dass sich der Daemon automatisch starten soll. Das passiert über die Datei /etc/default/pdnsd und hier setzen wir den Parameter START_DAEMON von no auf yes. Bevor wir den Daemon nun manuell starten, kümmern wir uns um die Konfiguration: /etc/pdnsd.conf (die je nach bei der Installation gewählten Voreinstellung auch wo anders liegen könnte).
Zunächst einmal vervierfache ich den Cache von 2048 auf 8192. Dann möchte ich, dass auch andere Rechner in meinem Netzerk den DNS-Cache verwenden können. Deswegen ändere ich server_ip = 127.0.0.1 in server_ip = 192.168.100.50. Die minimale Cache-Dauer ändere ich von 15 Minuten auf 23 Stunden: mint_ttl=23h. Ich gehe nun nicht auf alle einzelnen Optionen ein. Meine Konfigurations-Datei sieht wie folgt aus:
global { neg_rrs_pol=on; par_queries=1; perm_cache=8192; cache_dir = "/var/cache/pdnsd"; run_as = "pdnsd"; server_ip = 192.168.100.50; // Use eth0 here if you want to allow other machines on your network to query pdnsd. status_ctl = on; paranoid = on; min_ttl = 23h; // Retain cached entries at least 23 hours max_ttl = 1w; // One week. timeout = 10; // Global timeout option (10 seconds). query_method=tcp_only; } server { label = "resolvconf"; proxy_only = on; } server { label=OpenDNS; ip=208.67.220.220; ip=8.8.8.8; timeout=30; uptest=ping; interval=30; ping_timeout=300; proxy_only=on; purge_cache=off; caching=on; preset=off; } source { owner = localhost; file = "/etc/hosts"; } rr { name = localhost; reverse = on; a = 127.0.0.1; owner = localhost; soa = localhost,root.localhost,42,86400,900,86400,86400; }
Bemühe ich nun den Befehl dig auf der Kommandozeile (nicht per Standard installiert -> sudo apt-get install dnsutils
), bekomme ich beim ersten Aufruf eine Query Time von 212 ms. Wiederhole ich das Ganze, kommt die DNS-Auflösung aus dem Cache und ich bin bei 11 ms.
Nun können wir die DNS-Einträge in Squid auch ändern. Rufst Du nun mit dem Browser eine Internet-Seite auf, geht das über Squid, dieser fragt wiederum pdnsd und die DNS-Adresse ist gespeichert. Beim nächsten mal dauert die DNS-Anfrage dann also nur wenige Millisekunden.
Die Konfiguration würde erlauben, dass Du die DNS-Anfragen Deines kompletten Rechners über das Raspberry Pi laufen lassen kannst. Das geht aber nur so lange gut, wie das Raspberry Pi auch läuft. Mir reicht es an dieser Stelle, da mein RasPi eben auch anderweitig zum Einsatz kommt und ich dann lediglich den Browser umstellen muss.
Hinweis: Man könnte in der Konfigurations-Datei auch komplette Domains (inklusive Sub-Domains) sperren. Da ich das nicht brauche, ist das aus meiner conf-Datei verschwunden. Wer mehr dazu wissen möchte, kann sich die Dokumentation von pdnsd zu Gemüte führen. Relevant dazu ist Kaiptel 2.1.4 neg Section.
Tipp: Wenn Du herausfinden möchtest, welche Konfigurations-Datei denn nun wirklich im Einsatz ist, kannst Du das so realisieren: ps -aef | grep pdnsd
. Da kommt bei mir auf einer Test-Box (andere Option bei der Installation und Ubuntu Server) so etwas heraus:
Weitere Gedanken und Squid transparent machen
In meinem Home-Netzwerk geht das, den Proxy des Browsers schnell umzustellen – das muss man allerdings wissen. Angenehmer ist es natürlich, wenn die komplette Geschichte transparent laufen würde.
Dazu brauchst Du aber zwei getrennte Netzwerke. Im Prinzip läuft im inneren Netzwerk ein DHCP-Server, der die Linux-Box als Router und DNS-Server angibt. Sämtlicher Traffic geht von der einen Netzwerk-Schnittstelle zur anderen. Traffic auf Port 80 würde man dann auf die zweite Netzwerk-Schnittstelle Port 3128 (Squid) umleiten und bei Squid den Parameter http_port 3128 transparent setzen.
Dazu ist aber einiges an weiterer Konfiguration notwendig – das geht auch mit nur einer Netzwerkkarte, der man eine Pseudo-Schnittstelle aufs Auge drückt – wie zum Beispiel eth0:0. Um Linux als Router zu konfigurieren gibt es etliche Anleitungen im Internet. Hier ein paar Stichworte: IP-Forwarding, NAT, iptables (iptables -t nat -A PREROUTING -i eth1 -p tcp –dport 80 -j DNAT –to 192.168.100.50:3128).
Ein DHCP-Server ist mithilfe von isc-dhcp-server recht einfach aufzusetzen: sudo apt-get install isc-dhcp-server
Die Konfigurations-Datei davon ist sehr verständlich und der DHCP-Server läuft in weniger als fünf Minuten. Das durchrouten von einer Netzwerk-Schnittstelle zur anderen kann da schon eher eine Kopfnuss sein – vor allen Dingen, wenn die Firewall noch ein bisschen zickig ist.
Wenn jemand vorhat, so ein Szenario aufzusetzen – für den hätte ich folgende Ratschläge:
- nicht alles auf einmal versuchen und alles schön Schritt für Schritt
- Es ist im Prinzip egal, ob Du mit Squid, pdnsd, DHCP-Server oder Routing anfängst. Ich persönlich würde mit Squid oder pdnsd anfangen.
- Bleib so lange bei einer Komponente, bis diese 100 Prozent läuft und mach Dir eventuell Notizen, wenn Du später zurück musst (DNS-Server bei Squid umstellen, zum Beispiel).
- Somit ist nicht nur die Konfiguration übersichtlicher und das Gesamtbild bleibt durchschaubarer, sondern die Erfolgserlebnisse sind größer. Funktioniert eine Sache, kann man erst einmal durchatmen, etwas anderes tun und sich später mit ein paar frischen Augen wieder an die Sache machen.
- Backup: Sobald eine Sache funktioniert, sichere die entsprechenden Konfigurations-Dateien. Es reicht oft schon, eine Kopie im selben Verzeichnis:
cp squid.con squid-funktioniert-2014-03-10-11-04.conf
(Datum und Uhrzeit). Geht etwas gar nicht mehr, kann man einfach die alte und funktionierende Konfiguration wieder einsetzen.
Fazit
Wie gesagt bringen diese Maßnahmen wohl nur dann einen merklichen Geschwindigkeits-Vorteil, wenn das Internet recht schnarchig ist. Wer mobiles Breitband (Router) einsetzt, kann mit dieser Methode möglicherweise auch ziemlich Bandbreite sparen.
In unserem Netzwerk hier lesen wir täglich die selben News-Seiten (Zeit, Süddeutsche, Tagesschau und so weiter). Hat einer die Seite bereits aufgerufen, bekommt der andere große Teile davon aus dem Squid-Cache. Außerdem wird das Netzwerk weniger strapaziert, da nun ein Großteil der DNS-Anfragen aus dem lokalen Netzwerk kommen.
Ich werde das nun noch ein bisschen testen und bin jetzt schon am überlegen, ob ich meine ZBOX nicht für diese Zwecke opfere – die liegt meist eh nur im Schrank. Diese würde dann aber die volle Bandbreite bekommen und Squid läuft dann komplett transparent.
Alleine die Geschichte mit pdnsd ist schon ein ziemlicher und spürbarer Vorteil. Die Software könnte man natürlich auch auf einem Linux-Desktop installieren. Dann profitiert aber nur ein Rechner davon.
Nette Pi-Konstellation
Suchst Du ein VPN für den Raspberry Pi? NordVPN* bietet einen Client, der mit Raspberry Pi OS (32-Bit / 64-Bit) und Ubuntu für Raspberry Pi (64-Bit) funktioniert.
Polipo ist vielleicht auch ganz interessant, wurde ursprünglich entwickelt, um TOR zu beschleunigen.
Hi,
du hast da einen kleinen Fehler: tmpfs swapt (wenn swap vorhanden ist).
Außerdem wäre für dich evl auch das Interessant:
http://thomas-leister.de/internet/internet-traffic-komprimieren-mit-ziproxy-http-proxyserver/
Ich hatte das so, als ich nur langsames Internet hatte, eingerichtet das ich im Internet meinen Server mit ziproxy zu stehen hatte und local nochmal ein squid. So wurden die Inhalte erst komprimiert und dann nochmal gecacht.
So und Danke: ich hatte schonmal nach sowas wie pdnsd gesucht, ohne das ich wirklich zufrieden mit der Lösung war. Aber der ist wirklich einfach. Danke nochmal.
MfG ich
Du hast Recht. Ramfs swapt nicht ... danke für den Hinweis, ist korrigiert.
Das mit Ziproxy hatte ich mir auch schon angesehen. Das bringt in meinem Fall aber wenig, da ich irgendwo noch einen Server dafür bräuchte.
Das in Deinem Artikel beschriebene Problem mit Android lässt sich ganz gut mit Opera und dem Offroad-Modus adressieren.
Hm auf was für einen Server läuft dann diese Seite?
Ein reiner Webserver ohne Rootzugriff?
Is nicht mein Artikel, nur mein Link zu dem Artikel :).
Und auf dem Handy/ Smartphone hab ich das auch nie verwendet.
Wiegesagt so eine Proxykette kann schon lustig sein (schon rein von der Theorie xD).
zB "Browser -> Squid -> Ziproxy -> Tor -> Internet" (Warum? Weil es geht!)
MfG ich
Ja, die Seite läuft auf einem ganz normalen Hosting-Paket.
Sehr coole und da so ausführlich und präzise auch für Anfänger geeignete Anleitung, danke hierfür. 🙂
Habe so ein ähnliches Setup einmal ausprobiert: https://www.kadder.de/2014/01/raspberry-pi-dns-caching-server/
In meinem Fall gab es eher mehr Probleme als weniger, allerdings habe ich auch kein ramfs verwendet - da ist wahrscheinlich etliches an Geschwindigkeit verloren gegangen. Dafür praktischerweise direkt an den USB-Ports der Fritz!Box.