Ein eigenes kleines CDN für meine Mastodon-Instanz metalhead.club

Seit der großen Twitter-Welle, die das Mastodon-Netzwerk bzw. das Fediverse im weiteren Sinne im Herbst und Winter 2022 geflutet hat, spielen internationale User für den metalhead.club eine größere Rolle. Der Service ist vollständig in Deutschland gehostet und das war bis vor kurzem auch noch so. Doch mit der steigenden Zahl von internationalen Mitgliedern kommen auch neue Herausforderungen: Beispielsweise die der zügigen Content-Auslieferung.

Solange sich die Nutzer hauptsächlich in Deutschland und Europa befinden, sind die Latenzzeiten zum “Full Metal Server” in Frankfurt gering. Anders sieht es aber beispielsweise für die Nutzer aus Kanada, aus den USA und aus Australien aus, von denen es eine nicht zu unterschätzende Zahl im metalhead.club gibt. Für diese Nutzer war die Nutzung von metalhead.club manchmal ein kleines Geduldsspiel, denn vor allem Videos und größere Bilder erschienen nur mit einer kleinen Verzögerung auf der Website. Ich kann die Situation nur im Browser simulieren, doch bereits ein Ping von mehr als 200 ms verdirbt einem an so mancher Stelle den Spaß am Durchscrollen der Timeline.

Vor kurzem hat mich ein US-Nutzer auf ein konkretes Problem beim Abspielen eines Videos innerhalb der USA aufmerksam gemacht. Das iFixit Video konnte von ihm nur mit ständigen Unterbrechungen gestreamt werden. Grund für mich, mir endlich einmal Gedanken zu einem CDN zu machen - einem Content Delivery Network.

Sinn und Zweck eines solchen Netzwerks ist, die Inhalte, die einem Nutzer einer Plattform oder Website zur Verfügung stehen, gewissermaßen näher an den Nutzer zu rücken. Das ist nicht nur metaphorisch gemeint, sondern tatsächlich auch eine physische Angelegenheit: Selbst wenn man annimmt, dass durch Internetknotenpunkte, Signalrepeater und sonstiges Equipment keine zusätzlichen Latenzen auf der Strecke von hier in die USA ins System eingebracht werden, ist das Licht in den Meereskabeln bekanntermaßen nicht unendlich schnell. Allein dieser Umstand führt dazu, dass man die Webinhalte tatsächlich (physisch) näher am Kunden anbieten muss. Ein CDN besteht also aus vielen Datacenter-Standorten bzw. Servern, die in der Nähe der Nutzer installiert werden - idealerweise in Ballungsräumen, wo man zusätzlich von einer gut ausgebauten Netzinfrastruktur profitieren kann. Je nach Use Case in gewissen Weltregionen oder sogar auf der ganzen Welt. Die Inhalte werden auf alle (oder einige) der Server gespiegelt - je nach Bedarf. Ein US-Nutzer wird beim Anfordern der Inhalte nicht an einen EU-Server weitergeleitet, sondern ruft die Inhalte automatisch von einem Server in seiner Nähe (einem US-Datacenter) ab. Dieser Vorgang bleibt vor dem Nutzer idR transparent. Um zu erkennen, von welchem Standort aus ein Inhalt abgerufen wird (und welcher der zuständige Server ist), gibt es zwei Verfahren, die sich etabliert haben:

  • Anycast-basierte CDNs
  • “GeoIP”-basierte CDNs

Anycast-basierte CDNs

Ersterer CDN-Typ ist der “Goldstandard” und ermöglicht ein sehr elegantes (und genaues) Routing: Im Prinzip wird mehreren weltweit verstreuten Servern dieselbe öffentliche IP-Adresse zugeordnet. Welcher Server dann bei einer Anfrage tatsächlich angesprochen wird, wird durch das Routingprotokoll BGP entschieden. Dieses legt gewissermaßen die Pfade fest, die ein IP-Paket nehmen muss, um ans Ziel zu gelangen. Meistens gibt es mehrere Wege, ans Ziel zu kommen. Welcher mit den geringsten Kosten (oder der geringsten Latenz!) verbunden ist, weiß das Routingsystem. Insofern gibt man die Arbeit an das Routingsystem ab und verlässt sich darauf, dass es den schnellsten Weg durch’s Internet findet. Denn dafür ist es da - dafür wurde es entwickelt. Der Weg muss nicht immer der geografisch kürzeste sein. Wenn die Latenz auf Strecke A zu Server A kleiner ist als Strecke B zu Server B, werden die IP-Pakete automatisch zu Server A geleitet. Dieser antwortet dann. Die übrigen Server, die unter derselben IP-Adresse erreichbar sind, bekommen von der Anfrage nichts mit. So ein Anycast steckt übrigens auch hinter allen global verfügbaren DNS-Resolvern wie z.B. Google DNS, Quad9 oder Cloudflare DNS. Die IP-Adresse ist immer dieselbe - doch im Hintergrund wird man zum nächstgelegenen Server weitergeleitet, ohne etwas davon mitzubekommen.

GeoIP-basierte CDNs

Hinter dem Begriff GeoIP versteckt sich eine große Datenbank - eine GeoIP-Datenbank, wie sie beispielsweise von Unternehmen wie MaxMind angeboten werden (und wie sie beispielsweise in meinem Projekt watch.metalhead.club zum Einsatz kommt). Die Datenbank wird aus öffentlich verfügbaren Routinginformationen gespeist und speichert, welche IP-Adressbereiche (und damit ASNs) welchem Unternehmen zugeordnet sind. Sobald die Inhaberschaft einer IP-Adresse klar ist, lassen sich über das zugeordnete Unternehmen Rückschlüsse auf das geografische Nutzungsgebiet ziehen. IPv6-Adressen, die dem 2003::/19 Netz kommen (also 2003:: bis 2003:1fff:ffff:ffff:ffff:ffff:ffff:ffff) gehören beispielsweise der Deutschen Telekom. Damit ist auch klar, woher ein Benutzer kommt, der so eine IP-Adresse hat und einen Inhalt damit anfragt: Aus Deutschland. GeoIP Datenbanken speichern diese Zusammenhänge, sodass man sie dann befragen kann: “Woher kommt ein Nutzer mit der IP-Adresse xxx?”. Die Datenbank liefert dann eine mehr oder weniger genaue Antwort.

Die Genauigkeit von GeoIP-basierten CDNs

Meine Erfahrung mit den kostenlosen Angeboten solcher Datenbanken hat mir gezeigt: Auf Länderebene funktioniert das noch ganz gut - aber bis auf die Stadt genau kann man Nutzer meistens nicht verorten. Und das ist vielleicht auch ganz gut so. Es gibt bessere und schlechtere Datenbanken. Die genauen Datenbanken befinden sich meistens hinter einem kostspieligen Abomodell. Denn: GeoIP-Datenbanken müssen gepflegt werden. IP-Adressen bzw. Subnetze werden vor allem in Zeiten von IPv4-Adressmangel gehandelt und verkauft und an andere Anbieter verkauft. Ein Adressbereich, der gerade noch einem afrikanischen Mobilfunkanbieter gehört hat, kann morgen schon einem kleinen asiatischen Unternehmen gehören. Werden die Datenbanken nicht regelmäßig gepflegt, sind die Informationen veraltet und wertlos.

Und genau hier liegt der große Nachteil von GeoIP. Während sich Anycast-basierte CDNs darauf stützen, dass Routingsysteme bereits die kürzesten Strecken (im Sinne von Latenz) kennen, verlässt man sich bei GeoIP auf weitere gesammelte Informationen. Die Zuordnung IP-Adresse <=> Besitzer ist nicht schwer zu ermitteln und öffentlich. Die Schwierigkeit dürfte viel eher darin liegen, Art der Verwendung und Verwendungsregion für einen Besitzer korrekt zu ermitteln. Es kann sich schließlich um ein kleines Unternehmen handeln, aber auch im einen ISP, der die Adressen nur an seine Kunden weiterverteilt. Wie so eine Verteilung stattfindet und wie groß das geografische Verwendungsgebiet ist, weiß dann nur der Besitzer bzw. ISP. Um diese Zuordnung akkurater zu gestalten, können zusätzliche Trackinginformationen verwendet werden. So könnten vor allem dank Smartphones beispielsweise GPS-Standpunkt und verwendete IP-Adresse von einem Onlinewerbeunternehmen kombiniert werden, um den Aufenthaltsort eines Nutzers genauer zu bestimmen. Werden diese GPS-Informationen dann an den GeoIP-Anbieter verkauft, kann dieser den Verwendungsort der IP-Adresse viel genauer bestimmen. Aber das ist eine andere Geschichte …

Wie läuft nun die Weiterleitung eines Nutzers an den richtigen Server ab, wenn kein Anycast genutzt wird? Ganz einfach: Über den Verzeichnisdienst des Internets - das DNS.

Will man ein GeoIP-basiertes CDN bauen, braucht man DNS-Server, der dem Nutzer die passende IP-Adresse für seine Regio zurückgibt. Bei jeder Anfrage an den DNS-Service wird die IP-Adresse ermittelt und im Hintergrund der passende Zielhost basierend auf einer GeoIP-Datenbank ermittelt. Ich schreibe bewusst “die IP-Adresse”, denn welche IP-Adresse genau untersucht wird, kommt darauf an …

Resolver-IP oder EDNS Client Subnet (ECS)?

Man könnte nun meinen, es würde die Adresse des anfragenden Nutzers untersucht, beispielsweise die öffentliche IP-Adresse des Smartphones oder des Laptops - dem ist aber nicht so. Denn: Der Nameserver, der für meine Domain z.B. metalhead.club zuständig ist, bekommt diesen Client (fast) nie zu Gesicht. Es sind nämlich die DNS-Resolver, die für den Client die korrekte IP für einen Service anfragen - nicht die Clients selbst. Alles, was der GeoIP-Nameserver also auswerten kann, ist die IP-Adresse des Resolvers.

In vielen Fällen hat man so zwar nicht den Nutzer selbst geortet, ist aber in der Lage, seinen DNS-Resolver zu identifizieren. In den meisten Fällen ist das bei Privatkunden der Standard-DNS-Resolver des Kunden-ISPs, also beispielsweise der Deutschen Telekom. Der Standort des DNS-Resolvers stimmt in den meisten Fällen also ungefähr mit dem Standort des Kunden überein - zumindest, wenn man die Sache auf Länderebene betrachtet. Sieht mein Nameserver also eine IP, die einem Deutsche Telekom Resolver zugeordnet werden kann, kann ich idR. davon ausgehen, dass der eigentlich anfragende Nutzer ebenfalls aus Deutschland kommt.

Dann gibt es da aber noch Sonderfälle: Nämlich global verfügbare und ISP-unabhängige, offene DNS-Resolver. Beispielsweise:

  • Cloudflare DNS
  • Google DNS
  • Quad9
  • DNS4EU

Diese lassen häufig keine Rückschlüsse auf ein bestimmtes Land zu. Damit man den eigentlich anfragenden Kunden hinter dem DNS-Request dennoch ungefähr orten kann, gibt es eine EDNS-Erweiterung namens “ECS” (EDNS Client Subnet), die es erlaubt, zusätzliche Informationen an meinen Nameserver zu schicken: Nämlich das Subnetz des ursprünglichen Nutzers. Der Resolver kennt diese Client-IP naturgemäß und leitet sie in anonymisierter Form (nur Subnetz statt genauer IP-Adresse) an meinen Nameserver weiter. Dieser kann nun das per ECS weitergeleitete Subnetz statt der Resolver-IP für seine GeoIP-Datenbank verwenden und erhält ein präziseres Ergebnis zum geografischen Ursprung der Anfrage.

ECS wird nicht von allen Public Resolvern unterstützt - von DNS4EU wird ECS beispielsweise noch nicht unterstützt - auch, wenn das Feature bei dem Betreiber auf der Todo-Liste steht:

DNS4EU currently does not support EDNS, but we want to add support for this feature. Unfortunately, we do not have a timeline on when this should be done. Please check the project page https://www.joindns4.eu/learn for updates.

Was also nutzen? CDN-Provider oder selbst hosten?

Anycast-Systeme sind teuer. Sehr teuer. Und für jemanden wie mich nicht umzusetzen. Denn dazu müsste man einen eigenen IP-Adressbereich besitzen, für den man selbst BGP Routen definieren kann. Somit war das Thema für mich schnell erledigt. Anycast? Betreibe ich nicht selbst. Nun gibt es da aber noch eine andere Möglichkeit: Schließlich kann man sich ja in bestehende Anycast-Systeme einmieten oder CDNs einfach mieten. Auch das mieten von Anycast-IPs ist kostspielig und wird von den Hostern, die ich nutze bzw. nutzen will, nicht in der Form angeboten.

Frei mietbare CDNs gibt es jedoch wie Sand am Meer: BunnyCDN, Akamai, Cloudflare, KeyCDN, … sie sind nur einige populäre Beispiele. Oftmals werden diese CDNs auch in Kombination mit DNS-Services, S3 Speicher oder DDoS-Schutz verkauft. Mit dabei sind auch einige Angebote, die man sich als kleiner Plattformbetreiber im Internet gut leisten kann. Mein Interesse galt vor allem BunnyCDN. Mit ca. 20-25 € im Monat könnte ich die etwa 2.5 TB an metalhead.club Medien im Monat weltweit ausspielen lassen. Doch es gibt zwei Haken, die mich derzeit noch daran stören:

  1. Ich muss die TLS-Terminierung aus der Hand geben und die Medien fremd hosten lassen. Meine Nutzer verlassen sich allerdings darauf, dass ich alle Daten in meiner eigenen Hand habe
  2. Das Ökostrom-Problem: Es ist einfacher geworden, Serverhoster zu finden, die mit reinem Ökostrom arbeiten. Bei CDN-Anbietern sieht es leider noch nicht so gut aus: Nur Cloudflare scheint 100 % Ökostrom einzusetzen.

Damit fällt also auch das Einmieten in einem bestehenden CDN (erst einmal?) weg.

Ein eigenes Geo-IP basiertes CDN basteln

Bleibt also nur: Selbst basteln!

Meine Ansprüche sind relativ niedrig. Mir ist natürlich bewusst, dass ein eigenes GeoIP-basiertes CDN schnell an seine Grenzen bzw. Effizienz, Genauigkeit und Performance kommt. Ganz besonders dann, wenn man - wie ich - vor hat, nur sehr wenig Geld dafür zu investieren. Mir geht es in erster Linie darum, die Nutzererfahrung für einige meiner metalhead.club Member besser zu machen. Die perfekte Lösung werde ich auf diese Art und Weise nicht erreichen.

Da die Versorgungssituation innerhalb Europas in Ordnung ist und Latenzmessungen über Online-Tools (dazu später mehr!) ein zufriedenstellendes Ergebnis geliefert haben, habe ich mich vor allem zwei Standorten gewidmet: Dem amerikanischen Kontinent und dem asiatischen. Damit wäre mit insgesamt 3 Medienservern für media.metalhead.club der ganze Globus grob abgedeckt.

Über das “Ping Simulation” Tool habe ich mir angesehen, mit welchen Latenzen ich global in etwas rechnen kann, wenn ich die Server so verteile, wie ich es mir vorgestellt habe. Nämlich so, wie es mir der Serverhoster Hetzner durch seine Cloud erlaubt. Einen Hetzner-Account habe ich bereits und kenne mich mit den Produkten aus - zudem erfüllen sie meine Anforderungen (Deutsches Unternehmen, DSGVO-konform, 100 % Ökostrom). Und auch, was die Standorte angeht, hat Hetzner genau das im Angebot was ich will. Denn es gibt neben europäischen Rechenzentren auch zwei in den USA und eines in Singapur.

Die Simulation ergab, dass ich weite Teile der Welt mit etwa 100 ms oder weniger erreichen kann. Natürlich auch immer abhängig vom lokalen Provider, aber das Gesamtbild war einigermaßen gleichmäßig und nur an wenigen Standorten waren die Paketlaufzeiten deutlich höher als 150 ms. Also habe ich bei Hetzner kurzerhand einen Cloudserver in Ashburn (VA, USA) und einen in Singapur gebucht.

Implementierung

Was die vServer angeht, habe ich zu den kleinsten und günstigsten Modellen gegriffen, die Hetzner anbietet. Ich wollte klein starten und das Ganze erst einmal ausprobieren. Wie sich gezeigt hat, reichen die CPX11 Cloudserver bisher völlig aus. Sie müssen nur statische Dateien cachen und ausliefern - mehr nicht.

Nginx Caching Proxy

Auf den Servern läuft nur eine Nginx-Instanz, die

  • … Anfragen an media.metalhead.club entgegennimmt
  • nachsieht, ob die angeforderten Inhalte schon lokal vorliegen
  • (falls nicht, werden diese vom original S3 Bucket angefragt und gecached)
  • an den Client zurückliefert

Meine Konfiguration für Nginx:

proxy_cache_path   /tmp/nginx-cache-metalheadclub-media levels=1:2 keys_zone=s3_cache:10m max_size=30g
                    inactive=48h use_temp_path=off;

server {
   listen 80;
   listen [::]:80;
   listen 443 ssl http2;
   listen [::]:443 ssl http2;

   server_name  media.metalhead.club;

   include snippets/tls-common.conf;

   ssl_certificate /etc/acme.sh/media.metalhead.club/fullchain.pem;
   ssl_certificate_key /etc/acme.sh/media.metalhead.club/privkey.pem;

   client_max_body_size 100M;

   # Register backend URLs
   set $minio_backend 'https://metalheadclub-media.s3.650thz.de';

   root /var/www/media.metalhead.club;

   location / {
      access_log off;
      try_files $uri @minio;
   }

   #
   # Own Minio S3 server (new)
   #
   location @minio {
        limit_except GET {
                deny all;
        }

        resolver 9.9.9.9;
        proxy_set_header Host 'metalheadclub-media.s3.650thz.de';
        proxy_set_header Connection '';
        proxy_set_header Authorization '';
        proxy_hide_header Set-Cookie;
        proxy_hide_header 'Access-Control-Allow-Origin';
        proxy_hide_header 'Access-Control-Allow-Methods';
        proxy_hide_header 'Access-Control-Allow-Headers';
        proxy_hide_header x-amz-id-2;
        proxy_hide_header x-amz-request-id;
        proxy_hide_header x-amz-meta-server-side-encryption;
        proxy_hide_header x-amz-server-side-encryption;
        proxy_hide_header x-amz-bucket-region;
        proxy_hide_header x-amzn-requestid;
        proxy_ignore_headers Set-Cookie;
        proxy_pass $minio_backend$uri;

        # Caching to avoid S3 access
        proxy_cache s3_cache;
        proxy_cache_valid 200 304 48h;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        proxy_cache_lock on;
        proxy_cache_revalidate on;

        expires 1y;
        add_header Cache-Control public;
        add_header 'Access-Control-Allow-Origin' '*';
        add_header X-Cache-Status $upstream_cache_status;
        add_header X-Content-Type-Options nosniff;
        add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
        add_header X-Served-By "cdn-us.650thz.de";
    }
}

Übrigens: Das Hinzufügen des X-Served-By Headers erleichtert das Debuggen bzw. Überprüfen der Funktion. Für jedes Bild, das von media.metalhead.club geladen wird, lässt sich so sehr einfach feststellen, welcher der drei Hosts die Datei denn tatsächlich übertragen hat. Einsehbar ist der Header beispielsweise in den Entwicklertools jedes Webbrowsers.

GeoIP-basierte DNS-Zonen

Fehlt nun noch der GeoIP-Anteil, damit die metalhead.club Member an den jeweils passenden Server weitergeleitet werden. An dieser Stelle hätte ich einen eigenen GeoIP-/GeoDNS-fähigen Nameserver konfigurieren können (wie ich es in einem eigenen Kundenprojekt schon getan habe), doch für mein Experiment wollte ich nicht zu viel Aufwand betreiben. Also habe ich mich etwas umgesehen und bei Scaleway ein sehr interessantes Angebot gefunden. Dort kann man nämlich Nameserver mieten, die zum einen das GeoIP Feature beherrschen und sich zum anderen auch mit externen Domains nutzen lassen (also Domains, die man nicht bei Scaleway gebucht hat). Je nach Nutzung kostet ein solcher Service nur wenige Cent bis niedrige einstellige Eurobeträge für meinen Fall. Genau kann ich es sagen, wenn mein CDN eine Weile gelaufen ist ;-)

Allerdings wollte ich Scaleway nicht meine 650thz.de Root Zone überlassen. Diese sollte nach wie vor von Core-Networks.de gehostet werden. Stattdessen habe ich eine eigene Zone “cdn.650thz.de” angelegt und die Scaleway-Nameserver als autoritative Nameserver festgelegt. Zuvor musste allerdings die Eigentümerschaft von cdn.650thz.de gegenüber Scaleway bewiesen werden. Die NS-Einträge habe ich also noch nicht gesetzt, sondern zuerst einen Verifizierungseintrag in der metalhead.club Zone angelegt:

_scaleway-challenge     IN TXT  3600    "verifizierungs-string"

Nach ca. 30 Minuten war bestätigt, dass ich die Kontrolle über die Domain habe und ich konnte anfangen, die Scaleway-Nameserver für cdn.650thz.de in der 650thz.de Zone bei Core-Networks.de einzutragen:

cdn		86400	NS		ns0.dom.scw.cloud.
cdn		86400	NS		ns1.dom.scw.cloud.

(den _scaleway-challenge Eintrag habe ich wieder gelöscht)

Übrigens: Die 650thz.de Domain nutze ich für sämtliche Infrastruktur im Hintergrund, da metalhead.club zum 650thz.de Projekt gehört. Lasst euch davon nicht verwirren.

In der cdn.650thz.de Zone habe ich dann schließlich den GeoIP-Eintrag für metalheadclub-media.cdn.650thz.de hinzugefügt:

Screenshot Eingabemaske DNS bei Scaleway

Der default-Eintrag zeigt auf s3.650thz.de - den bisherigen S3-Medienserver in Frankfurt. Sollte jedoch ein Clientstandort in Nord- oder Südamerika erkannt werden, wird stattdessen der CDN-Server cdn-us.650thz.de genutzt. Wird ein Standort in Asien oder im pazifischen Raum erkannt, wird auf den CDN-Server cdn-ap.650thz.de verwiesen.

Essentiell ist übrigens der abschließe Punkt hinter jedem der FQDNs in der Eingabemaske! Wird kein Punkt gesetzt, wird ein Eintrag in derselben Zone referenziert - das kann nicht funktionieren.

Die Verkettung von DNS-Records mittels CNAME hat sich im Nachhinein übrigens als ungünstig für weit entfernte Benutzer herausgestellt. Mehr dazu unter “Weitere Verbesserungen: DNS-Optimierung”

Umschaltung auf CDN-Betrieb

Um nun alle Anfragen an media.metalhead.club mit dem passenden Medienserver zu beantworten, war noch noch eine Änderung nötig: Der Eintrag für media.metalhead.club musste im metalhead.club Zonefile auf metalheadclub-media.cdn.650thz.de verweisen:

media		IN CNAME 	3600		metalheadclub-media.cdn.650thz.de.

(auch hier wieder auf den abschließenden Punkt achten!)

Um das CDN nach der DNS-Umstellung (und der zuvor eingetragenen TTL) zu testen, habe ich kurzerhand von jedem der Server aus einen nslookup auf media.metalhead.club gemacht:

  • Von s3.650thz.de aus: Gibt eigene IP zurück
  • Von cdn-us.650thz.de aus: Gibt eigene IP zurück
  • Von cdn-ap.650thz.de aus: Gibt eigene IP zurück

Die dynamische Zuteilung funktionierte also!

Wie gut funktioniert das?

Um nun noch ein breiteres Bild zu bekommen, habe ich noch weitere Tests durchgeführt, zum Beispiel mit folgenden Tools:

Auch metalhead.club User habe ich dazu befragt. Ein Nutzer aus Australien hatte zuvor diese Ping-Zeiten zu media.metalhead.club:

64 bytes from 5.1.72.141: icmp_seq=0 ttl=38 time=369.765 ms
64 bytes from 5.1.72.141: icmp_seq=1 ttl=38 time=350.830 ms
64 bytes from 5.1.72.141: icmp_seq=2 ttl=38 time=469.047 ms
64 bytes from 5.1.72.141: icmp_seq=3 ttl=38 time=379.882 ms
64 bytes from 5.1.72.141: icmp_seq=4 ttl=38 time=400.998 ms

(also im Mittel knapp 400 ms!)

Danach waren die Latenzen deutlich niedriger, weil er korrekterweise zu dem US-Server statt dem EU-Server weitergeleitet wurde:

64 bytes from 5.223.63.2: icmp_seq=0 ttl=50 time=150.384 ms
64 bytes from 5.223.63.2: icmp_seq=1 ttl=50 time=230.931 ms
64 bytes from 5.223.63.2: icmp_seq=2 ttl=50 time=360.083 ms
64 bytes from 5.223.63.2: icmp_seq=3 ttl=50 time=142.986 ms
64 bytes from 5.223.63.2: icmp_seq=4 ttl=50 time=138.416 ms
64 bytes from 5.223.63.2: icmp_seq=5 ttl=50 time=300.561 ms

(im Mittel 264 ms).

Nicht weltbewegend, aber dennoch bedeutend weniger. Dass dieser Benutzer trotzdem eine relativ hohe Latenz zum Medienspeicher hat, kommt daher, das die Strecke von Australien nach Singapur trotzdem nicht zu vernachlässigen ist. Hier zeigt mein kleines CDN gleich seine Schwäche: Durch nur 3 Standorte kann man keine Bestperformance erreichen - aber man kann immerhin eine kleine Verbesserung herbeiführen.

Für einen anderen australischen User hat sich die Latenz von durchschnittlich 346 ms auf 108 ms verbessert!

Und für den User aus den USA, den ich zu Beginn erwähnt habe? Der konnte nach der Umstellung das fragliche Video problemlos und flüssig abspielen.

Mit dem BunnyCDN Test habe ich einen Vorher-Nachher-Vergleich angestellt:

Vorher:

BunnyCDN Screenshot zeigt Latenzzeiten vor der Umstellung auf ein CDN

Nachher:

BunnyCDN Screenshot zeigt Latenzzeiten nach der Umstellung auf ein CDN

Ziel erreicht!

Für die meisten Standorte rund um die USA, Australien, Korea und Japan haben sich die Latenzzeiten deutlich verbessert. Europa ist wie erwartet unverändert. Es gibt aber auch einige unerwartete Ausreißer, die wohl einer falschen IP-Lokalisierung zum Opfer gefallen sind, beispielsweise in Singapur selbst (interessant!), in der Türkei, Indien, im US-Bundesstaat Texas und Chile.

Selbstverständlich hängen die Ergebnisse auch stark damit zusammen, mit welchen IPs getestet wurde und wie die Anbindung vor Ort aussieht. Womöglich wurde die Türkei schon als “Asiatischer Raum” gewertet und der Standort, von dem aus in Texas getestet wurde, wurde womöglich als europäisch erkannt.

Ich werde die Ergebnisse weiter beobachten. Da hier vor allem von Rechenzentren aus gemessen wurde (und nicht von Privathaushalten aus entsprechenden ISP-Bereichen), spiegeln die Ergebnisse womöglich nicht die ganze Wahrheit wider.

Man kann sich also zurecht fragen: …

Ist auf GeoIP Verlass?

Da ich bei der Prüfung meines CDNs mit den oben erwähnten Test-Websites festgestellt habe, dass der kontaktierte Server nicht immer korrekt dem Teststandort entsprach (siehe Ergebnis des Singapur-Standorts!), habe ich meine Nutzer befragt. Denn die Ergebnisse dieser Web-Tools sind vermutlich nicht besonders genau. Ich schätze, dass der Mechanismus für Endkunden-Adressbereiche viel besser funktionieren als für Datacenter-Adressbereiche. Schließlich können für Privatkunden-IPs sehr viel einfacher GPS- und andere Standortinformationen “hinfusioniert” werden.

Und tatsächlich: Die Nutzer bekamen in fast allen Fällen den korrekten Medienserver aufgrund ihrer Herkunft zugeteilt. Siehe: https://metalhead.club/@thomas/114676148254141233 (Den Post hätte ich wohl eher mit einer Umfrage-Option versehen sollen … )

Die letzte manuelle Zählung am 15.06.2025 hat ergeben:

  • Für 83 Benutzer (allerdings die meisten davon aus DE), hat die Zuteilung funktioniert
  • Für 4 Benutzer hat diese nicht funktioniert. 3 davon wurden in die USA weitergeleitet statt Frankfurt - ein Benutzer wurde sogar nach Singapur verbunden, obwohl er in Deutschland war.

Ich habe den Scaleway Support dazu befragt, welche GeoIP Datenbank genutzt wird und wie häufig diese aktualisiert wird. Folgende Antwort habe ich erhalten:

There can occasionally be discrepancies, such as the one you experienced with the Singapore data center being identified as European. It can take time for GeoIP databases to reflect changes like IP reallocation. Our GeoIP database provider involve frequent updates, often on a weekly or bi-weekly basis. While we don’t publicly disclose the specific third-party GeoIP database provider we use, we rely on a reputable industry-standard provider to ensure the highest possible accuracy for our customers. We understand that accurate GeoIP routing is crucial for latency-sensitive applications. If you encounter significant and persistent inaccuracies, we encourage you to report them to our support team so we can investigate further.

Außerdem habe ich nachgehakt, ob bei Scaleway GeoIP nur die Resolver-Adresse für die Ortung genutzt wird, oder auch eine Auswertung des EDNS ECS Felds erfolgt. Das würde die Genauigkeit verbessern:

Our product team has got back to us to indicate that you are right. First we use the EDNS/ECS feature and if it’s not available we use resolver’s IP address.

Wie geht’s weiter?

Mit einem Anycast-basiertem CDN könnte man sicherlich deutlich bessere Ergebnisse erzielen, aber das ist für mich aus den oben genannten Gründen ja erst einmal keine implementierbare Lösung. Da mein kleines GeoIP CDN zwar nicht in allen, aber in den meisten Fällen eine Verbesserung erreicht, werde ich das Experiment weiterlaufen lassen. Vielleicht gibt es noch die ein oder andere Stellschraube, mit der man die Lokalisierung verbessern kann.

Ansonsten spiele ich auch mit dem Gedanken, evtl. doch auf ein professionelleres, fremd gehostetes und AnyCast CDN umzusteigen. Dann wäre Cloudflare allerdings der einzige Anbieter, auf den ich mich stützen könnte. Denn das “100 % Green Energy” Label meiner Dienste bin ich nicht bereit für ein CDN aufzugeben.

Insgesamt kann man sagen, dass mein GeoIP-CDN hilft, den Zugriff für die meisten weit entfernten Benutzer zu verbessern. Es gibt aber auch Einschränkungen:

  • Nicht in allen Fällen wird der passende CDN-Server zugewiesen (Ungenauigkeit der GeoIP Datenbank)
  • Für einen Latenzvorteil muss ein bestimmter Inhalt bereits von einem anderen Benutzer aus der Region abgerufen worden sein (Inhalte werden (noch?) nicht über alle CDN-Server synchron vorgehalten => Mehr Speicherbedarf)
  • Nur Medieninhalte werden vom CDN vorgehalten. API-Services und Webfrontend werden nach wie vor nur in der EU gehostet.

Weitere Verbesserungen: DNS-Optimierung

Nachdem ich mein CDN ausgerollt habe, habe ich durch Performancetools festgestellt, dass die DNS-Namensauflösung vor allem für weit entfernte Benutzer einen großen Teil der gesamten Ladezeit einnimmt. Wie sich das verbessern lässt, habe ich in diesem Folgeartikel beschrieben: “Globale DNS-Auflösung durch Verzicht auf CNAMES beschleunigen