InstaTunnel
Navigationsmenu umschalten
Tutorial
10 min read
18 views

Pfadnormalisierung am Tunnelrand: Warum eine Route auf localhost übereinstimmt, aber nicht durch einen Cloudflare Tunnel

Warum Routen auf localhost übereinstimmen, aber nicht durch einen Cloudflare Tunnel. Sehen Sie, wie cloudflared Pfadnormalisierung %2F, Dot-Segmente, Schrägstriche und Ingress-Regeln ändert.

IT
InstaTunnel Team
Published by the InstaTunnel team | Editorial policy
Pfadnormalisierung am Tunnelrand: Warum eine Route auf localhost übereinstimmt, aber nicht durch einen Cloudflare Tunnel

Quick answer

Cloudflared Pfadnormalisierung: Warum Routen in Tunneln scheitern: localhost tunnel answer

A localhost tunnel gives your local app a public HTTPS URL without opening router ports, which is useful for demos, QA, mobile testing, and provider callbacks.

How do I expose localhost without opening ports?

Use a reverse HTTPS tunnel. Your machine connects outbound to the tunnel service, and the public URL forwards requests back to your local app.

When should I use a localhost tunnel?

Use one for webhook testing, OAuth callbacks, client demos, QA previews, mobile device checks, and short-lived development reviews.

Ihre /admin-Route funktioniert auf localhost:8080. Durch den Tunnel gibt //admin etwas anderes zurück, /public/../admin verhält sich erneut anders, und eine Regel, von der Sie annahmen, dass sie den Pfad schützt, scheint nie auszulösen. Nichts ist mit Ihrer Anwendung falsch. Mehrere Komponenten analysieren denselben Pfad nach unterschiedlichen Regeln, und ein zusätzlicher Parser wird durch einen Tunnel der Kette hinzugefügt.

Dieses Kette wird sich ändern. Ab 2027-01-25 werden neue cloudflared-Versionen URL-Normalisierung standardmäßig aktivieren, was Cloudflare zufolge ändern kann, welche Ingress-Regel eine Anfrage zuordnet. Dieser Leitfaden erklärt, was sich ändert, was nicht, wie Pfad-Verwechslungs-Authentifizierungsumgehungen funktionieren und wie Sie Ihr eigenes Routing testen, bevor die Standardeinstellung umgestellt wird.

Kurze Zusammenfassung

  • cloudflared 2026.10.0 und neuere Versionen können den URL-Pfad vor dem Abgleichen der Ingress-Regeln normalisieren.
  • Es ist heute standardmäßig aus und in neuen Releases ab dem 2027-01-25 standardmäßig an.
  • Cloudflare beschränkt die Änderung auf Tunnels mit Ingress-Regeln, die eine Cloudflare Access-Validierung erfordern; andere Konfigurationen bleiben unberührt.
  • Die dokumentierten Transformationsregeln sind Dot-Segment-Entfernung, Backslash-zu-Slash-Konvertierung und das Zusammenführen von mehrfachen Slashes. Der an Ihren Origin weitergeleitete Pfad wird nicht verändert.
  • Prozentkodierung (wie %2F) und abschließende Slashes stehen nicht auf der dokumentierten Liste; testen Sie sie daher, statt Annahmen zu treffen.

Was Cloudflare angekündigt hat

Am 22. Oktober 2026 veröffentlichte Cloudflare einen Changelog-Eintrag mit dem Titel “Cloudflare Tunnel unterstützt URL-Normalisierung.” Die wichtigsten Fakten:

  • Verfügbarkeit: cloudflared-Version 2026.10.0 und neuer. GitHub listet 2026.10.0 als am 5. Oktober 2026 veröffentlicht; die neueste Version, die ich bis zum 5. November 2026 finden konnte, ist 2026.10.6.
  • Standard heute: aus. Das Flag ist invertiert, daher ist der dokumentierte Standard von --disable-path-normalization true.
  • Standard ab 2027-01-25: an, für neue Releases.
  • Geltungsbereich: Cloudflare sagt, es verbessere die Sicherheit für Tunnels mit Regeln, die eine Access-Validierung erfordern, und Konfigurationen ohne solche Regeln bleiben unberührt.
  • Origin-Pfad: unverändert. Die Normalisierung gilt für den Pfad, der zum Matching verwendet wird, nicht für den weitergeleiteten Pfad.

Um es jetzt zu aktivieren:

cloudflared tunnel --disable-path-normalization=false run <TUNNEL_NAME_OR_UUID>

oder setzen Sie TUNNEL_DISABLE_PATH_NORMALIZATION=false auf jeder cloudflared-Replik und starten Sie sie neu.

Eine betriebliche Detail verdient Beachtung. Eigenständige cloudflared-Binärdateien, die als Dienst laufen, aktualisieren sich standardmäßig automatisch alle 24 Stunden (autoupdate-freq). Paketmanager-Installationen, Windows- und interaktive Ausführungen aktualisieren sich nicht automatisch. Wenn Ihr Tunnel automatisch aktualisiert wird, oder Sie ein schwebendes latest-Image-Tag verwenden, wird die neue Standardeinstellung ohne gezielte Aktualisierung eintreten. Setzen Sie das Flag entweder jetzt explizit oder pinnen Sie Ihre Version, bis Sie getestet haben.

Was normalisiert wird und was nicht

Cloudflares Konfigurationsdokumentation beschreibt das Verhalten anhand von drei Beispielen. Eingehende Pfade werden so gezeigt, wie cloudflared sie empfängt:

Eingehender Pfad Wird für das Ingress-Matching verwendet An Origin gesendet
/hello/../path /path /hello/../path
/hello//path /hello/path /hello//path
/hello\\path /hello/path /hello\\path

In Worten: Dot-Segmente (. und ..) werden gemäß RFC 3986 Abschnitt 5.2.4 entfernt, Backslashes werden zu Vorwärtsschrägstrichen (Slash); und wiederholte Slashes werden zusammengeführt.

Beachten Sie, was die Dokumentation nicht auflistet: Prozentdekodierung, Umgang mit abschließenden Slashes, Semikolon-Pfadparameter und Groß-/Kleinschreibung. Das ist wichtig, weil RFC 3986 hier eine harte Grenze zieht. Ein prozentkodiertes unreserviertes Zeichen wie %61 (der Buchstabe “a”) ist dem wörtlichen Form gleichwertig, sodass Normalizer es decodieren können. Ein prozentkodiertes reserviertes Zeichen ist nicht äquivalent: %2F ist nicht dasselbe wie /, und ein standardskonformer Normalizer darf sie nicht zusammenführen.

Mein Fazit: Behandeln Sie alles außerhalb der drei dokumentierten Transformationen von Cloudflare als “nicht normalisiert”, bis Ihre eigenen Tests etwas anderes zeigen. Ich habe dies anhand der Dokumentation von Cloudflare verifiziert, nicht durch das Instrumentieren von cloudflared, daher ist die untenstehende Testmatrix der Weg, das Verhalten Ihrer Version zu bestätigen.

Warum localhost und ein Tunnel widersprechen

Der Aufruf von localhost:8080/admin verwendet einen Pfadparser: den Ihres Frameworks. Eine durch den Tunnel weitergeleitete Anfrage durchläuft mindestens drei:

  1. Der Cloudflare-Edge, der eine eigene URL-Normalisierung besitzt. Laut Cloudflare-Dokumentation ist die eingehende URL-Normalisierung standardmäßig aktiviert, und bestimmte Basisschritte (zum Beispiel das Zusammenführen benachbarter Slashes) werden immer angewendet und können nicht deaktiviert werden.
  2. cloudflared, das den Pfad gegen Ihre Ingress-Regeln abgleicht.
  3. Ihr Origin, dessen Framework, Reverse-Proxy oder der statische Dateihandler seine eigene Decodierung und Dot-Segment-Logik anwendet.

Es gibt einen vierten, leicht übersehenen Mitspieler: Ihren Test-Client. Browser lösen ..-Segmente, bevor sie eine Anfrage senden, und der WHATWG-URL-Parser behandelt Backslashes als Slashes für HTTP- und HTTPS-URLs. Ein Mausklick durch einen Browser führt daher selten zu dieser Eingabe. Sogar curl klammert Dot-Segmente aus, es sei denn, Sie verwenden --path-as-is. Wenn Sie einen Pfad “getestet” haben und er funktionierte, hat der Client ihn möglicherweise zuerst in eine sichere Version umgeschrieben.

Jede Uneinigkeit zwischen Parsern ist eine potenzielle Umgehung. Wenn Ebene zwei der Ansicht ist, dass die Anfrage /public/... gehört, und Ebene drei, dass sie /admin gehört, wird eine für eine Regel geschriebene Regel gegen die andere ausgewertet.

Die Pfad-Verwechslungs-Authentifizierungsumgehung, Schritt für Schritt

Betrachten Sie einen Tunnel, der /admin mit einer Access-Validierung bei cloudflared schützt, eine Defense-in-Depth hinter Ihrer Access-Richtlinie:

tunnel: <TUNNEL_UUID>
credentials-file: /etc/cloudflared/<TUNNEL_UUID>.json

ingress:
  - hostname: app.example.com
    path: ^/admin(/|$)
    service: http://localhost:8080
    originRequest:
      access:
        required: true
        teamName: <your-team-name>
        audTag:
          - <access-application-aud-tag>
  - hostname: app.example.com
    service: http://localhost:8080
  - service: http_status:404

Ingress-Regeln werden von oben nach unten ausgewertet, und path ist ein regulärer Ausdruck, der mit Go’s regexp/syntax-Paket geparst wird. Jetzt senden Sie GET /public/../admin/users.

  • Normalisierung aus: Der Matcher sieht /public/../admin/users. Der Regex der ersten Regel verlangt, dass der Pfad mit /admin beginnt, also passt sie nicht. Die Anfrage geht zur zweiten Regel über, die keine Access-Anforderung hat, und wird mit dem ursprünglichen Pfad weitergeleitet.
  • Ihr Origin reduziert das Dot-Segment, leitet die Anfrage zu /admin/users weiter und dient sie aus. Die JWT-Überprüfung, die /admin schützen sollte, lief nie.
  • Normalisierung an: Der Matcher sieht /admin/users, wählt die erste Regel aus und verlangt eine gültige Access-JWT. Der Origin erhält weiterhin den ursprünglichen Pfad.

Das Muster ist allgemein: Eine Sicherheitsentscheidung, die auf einer Interpretation eines Pfads basiert, während die Aktion auf einer anderen erfolgt. Genau das beschrieb Orange Tsai in seinem 2018er Black-Hat-/DEF CON-Forschungsbericht “Breaking Parser Logic”. Seine Folien zeigten, dass /foo;name=orange/bar/ von Apache, Nginx und IIS als /foo;name=orange/bar/ gelesen wird, aber von Tomcat und Jetty als /foo/bar/ gelesen wird, und nutzten diese Lücke, um proxy-ACLs zu umgehen.

Es passiert weiter, auch in diesem Jahr:

  • Heimdall (CVE-2026-42274): vor Version 0.17.14 matchte der identity-aware Proxy Regeln anhand des rohen Pfads, während nachgelagerte Komponenten Dot-Segmente normalisierten, sodass eine Anfrage wie /user/../admin als ein Pfad autorisiert werden konnte und als ein anderer verarbeitet wurde.
  • Quarkus (CVE-2026-50559): pfadbasierte Autorisierungspolitiken konnten mit prozentkodierten Semikolons (%3B), Slashes (%2F) oder Backslashes (%5C) umgangen werden, weil die Sicherheits- und Routing-/Statisik-Datei-Lagen sie unterschiedlich dekodierten.
  • @opennextjs/cloudflare (CVE-2026-3125): ein Backslash in /cdn-cgi\\image/ schlüpfte an Cloudflare’s Edge Interception vorbei, dann konvertierte die URL-Klasse eines Workers es in einen Vorwärts-Slash, wodurch ein verwundbarer Handler erreicht wurde. Behoben in 1.17.1.
  • fast-uri (CVE-2026-6321): die Bibliothek dekodierte prozentkodierte Trennzeichen und Dot-Segmente, bevor Dot-Segmente entfernt wurden, sodass unterschiedliche URIs auf einen einzigen normalen Pfad zusammenfallen konnten. Behoben in 3.1.1.

Verschiedene Stacks, dieselbe Grundursache: zwei Parser, ein Pfad.

Die vier Eingaben zum Testen

Dot-Segmente (/../ und /./)

Dies ist die klassische Traversal-Verwirrung, die direkt durch die neue cloudflared-Einstellung adressiert wird. Testen Sie einfache .. und die kodierten Formen %2e%2e und %2E%2E. RFC 3986 besagt, dass prozentkodierte unreservierte Zeichen gleichwertig mit ihren literalen Formen sind, und der WHATWG-URL-Parser behandelt %2e als Punkt in Pfadsegmenten. Viele Origins decodieren %2e vor dem Entfernen der Punkte, wie der Quarkus-Hinweis zeigt. Cloudflare dokumentiert Dot-Segment-Entfernung, sagt aber nicht, ob kodierte Punkte zuerst decodiert werden; daher braucht diese Zeile einen echten Test.

Doppelte Slashes (//)

Frameworks unterscheiden sich darin, ob //admin gleich /admin ist. Einige vereinigen sie, andere behandeln das leere Segment als signifikant, wieder andere lehnen es ab. Die Normalisierung von Cloudflare (cloudflared) vereint sie nur für das Matching. Ein Muster wie ^/admin passt ohne Normalisierung nicht zu //admin, und ein Origin, der es ebenfalls zusammenführt, bedient statt dessen /admin.

Trailing Slashes (/admin vs /admin/)

Die dokumentierte Normalisierung erwähnt keine trailing Slashes; gehen Sie davon aus, dass sie unberührt bleiben. Das macht Regex-Anker entscheidend: ^/admin$ passt zu /admin, aber nicht zu /admin/, während viele Frameworks (zum Beispiel Express) beide auf denselben Handler routen. Schreibe geschützte Pfadmuster als ^/admin(/|$), oder schütze besser den ganzen Host und carve Ausnahmen für öffentliche Pfade.

Kodierte Slashes (%2F) und Freunde

%2F ist der Grenzpunkt, an dem Parseren zerlegen. Manche Origins dekodieren es in einen echten Separator vor der Weiterleitung, andere belassen es in einem einzelnen Segment, und manche verweigern es ganz (viele Server bieten eine Einstellung dazu). Weil RFC 3986 es als nicht äquivalent zu / behandelt, gibt es keinen offensichtlichen Grund, es zu decodieren, und ein standards-konformer Matcher würde /admin%2Fusers als ein einziges, undurchsichtiges Segment behandeln. Ihr Origin könnte das nicht tun. Gleiches gilt für %5C (Backslash) und %3B (Semikolon). Der Quarkus-Fall zeigt, wie eine Umgehung genau in dieser Lücke versteckt sein kann.

Eine Testmatrix, die Sie heute ausführen können

Angenommen, die obige Konfiguration gilt, wobei der Origin 200 auf /admin/* nur dann zurückgibt, wenn ein Access-JWT vorhanden ist. Für jede Anfrage gilt als Pass-Bedingung, dass sie genauso wie der einfache /admin/users abgelehnt wird.

Anfragepfad Entspricht als (aus) Entspricht als (an) Dokumentiert?
/admin/users /admin/users /admin/users Baseline
/public/../admin/users roh /admin/users Ja
//admin/users roh /admin/users Ja
/admin//users roh /admin/users Ja
\\admin\\users roh /admin/users Ja
/admin/ roh roh Trailing Slash nicht gelistet
/%61dmin/users roh Nicht dokumentiert Nein, testen
/admin%2Fusers roh Nicht dokumentiert Nein, testen
/public/%2e%2e/admin/users roh Nicht dokumentiert Nein, testen
/admin;x=1/users roh Nicht dokumentiert Nein, testen

Zwei Warnungen beim Lesen der Ergebnisse. Erstens ist die eigene Edge-Normalisierung von Cloudflare eine separate Schicht. Einige Zeilen können bei aktiver bzw. inaktiver cloudflared-Normalisierung identisch aussehen, da der Edge sie bereits neu geschrieben hat; das ist in Ordnung, aber Sie möchten wissen, welche Schicht die Arbeit erledigt. Zweitens zeigt cloudflared tunnel ingress rule <URL>, welche Regel eine URL übereinstimmt, aber Cloudflare-Dokumentation sagt nicht, ob sie das Normalisierungsflag respektiert; bestätigen Sie dies ebenfalls mit Live-Verkehr.

Hier ist ein kleines Python-Harness, das Pfade genau so sendet, wie sie geschrieben stehen, was curl und Browser nicht immer tun:

import http.client, ssl

HOST = "app.example.com"
PATHS = [
    "/admin/users", "/public/../admin/users", "//admin/users",
    "/admin//users", "\\admin\\users", "/admin/", "/%61dmin/users",
    "/admin%2Fusers", "/public/%2e%2e/admin/users", "/admin;x=1/users",
]

ctx = ssl.create_default_context()
for path in PATHS:
    conn = http.client.HTTPSConnection(HOST, context=ctx, timeout=10)
    conn.request("GET", path)
    print(f"{path!r:34} -> {conn.getresponse().status}")
    conn.close()

Führen Sie es zweimal aus: einmal mit dem Tunnel auf den aktuellen Standardeinstellungen, einmal mit --disable-path-normalization=false. Jeglicher Pfad, der etwas anderes als die Basisverweigerung zurückgibt, ist ein Fund. Für Einzelchecks gilt: curl --path-as-is stoppt curl davor, Dot-Segmente zu collapsen.

Rollout-Checkliste vor dem 2027-01-25

  1. Prüfen Sie, ob Sie im Scope sind. Suchen Sie nach access:-Blöcken mit required: true. Keine solchen Regeln, und Cloudflare sagt, Sie seien nicht betroffen.
  2. Prüfen Sie, wo der access-Block sitzt. Ein offenes Issue in Cloudflare-Dokumentations-Repository berichtet, dass in cloudflared 2026.7.1 ein top-Level-originRequest.access-Block nicht durchgesetzt wurde, während derselbe Block unter einer einzelnen Ingress-Regel durchgesetzt wurde. Dies ist ein Nutzerbericht, keine bestätigte Dokumentation, daher verifizieren Sie in Ihrer Version statt dem bloßen Lesen.
  3. Führen Sie die Matrix in der Staging-Umgebung mit Normalisierung aus/off aus. Notieren Sie jede Differenz.
  4. Audit Regex-Anker. Ersetzen Sie unanchored- oder $-beendete Muster für geschützte Pfade durch solche, die Trailing Slashes handhaben.
  5. Aktivieren Sie es frühzeitig, explizit. Das Flag jetzt zu setzen bedeutet einen No-op für Sie beim Januar-Wechsel. Nach dem Cutover prüfen Sie die Release-Notes, ob das Flag weiterhin respektiert wird.
  6. Kontrollieren Sie Auto-Updates (--no-autoupdate, Version-Pinning) bis die Matrix auf der neuen Version besteht.
  7. Beheben Sie auch das Origin-Verhalten. Normalisierung am Tunnel ist Defense in depth. Lassen Sie Ihre Anwendung ambige Pfade (kodierte Slashes, Backslashes, Dot-Segmente) ablehnen, statt sich auf die Frontlayer zu verlassen.
  8. Protokollieren Sie rohe Anforderungsziele, damit ein Erkundungsversuch als %2e%2e oder \ in Ihren Logs erscheint, nicht als bereinigter Pfad.

FAQ

Verändert sich der Pfad, den meine Anwendung erhält? Nein. Cloudflare gibt an, dass der an Ihren Ursprung gesendete URL-Pfad unverändert bleibt. Nur der Pfad, der zum Auswählen einer Ingress-Regel verwendet wird, wird normalisiert.

Wird mein Tunnel am 2027-01-25-Stichtag brechen? Nur, wenn Sie Regeln mit Access-Validierung haben und Ihre Abgleichung auf unnormalisierten Pfaden beruht. Cloudflare gibt an, dass Konfigurationen ohne solche Regeln unberührt bleiben, empfiehlt aber, die pfadbasierten Routings vor dem Datum zu testen.

Ist Normalisierung am Tunnel ausreichend, um Pfad-Verwechslungs-Umgehungen zu stoppen? Sie deckt den Bereich ab, den die Transformationen abdecken. Sie macht nicht die Parsers Ihres Origin konsistent mit dem Tunnel, und Cloudflare dokumentiert nicht das Decodieren von reservierten Zeichen wie %2F. Betrachten Sie es als eine Schicht.

Besteht dasselbe Risiko bei anderen Tunneln und Reverse Proxies? Ja. Jedes Baustein, der eine Routing- oder Autorisierungsentscheidung auf einem Pfad trifft, den der nächste Layer nicht normalisiert, ist verwundbar. Führen Sie die Matrix gegen das aus, was an Ihrem Edge sitzt.

Webhook-Signatur-Überprüfung hinter Tunneln ist ein separater Ausfallmodus, behandelt im früheren Beitrag zu Signaturen.

Quellen

Continue from this article into the most relevant product guides and workflows.

Related Topics

#cloudflared path normalization#cloudflared URL normalization#cloudflare tunnel path normalization#cloudflared ingress rules#cloudflared ingress path matching#cloudflare tunnel routing#cloudflare tunnel ingress#cloudflared 2027 update#cloudflared default normalization#cloudflared changelog#route works on localhost but not through tunnel#localhost vs tunnel routing#tunnel path mismatch#tunnel edge routing#URL normalization#path normalization#URL path normalization security#path normalization bypass#path confusion attack#path confusion auth bypass#path traversal normalization#encoded slash %2F#%2F in URL path#percent encoded slash#URL encoding bypass#dot-segment removal#dot segments in URL#double slash in URL path#trailing slash routing#trailing slash mismatch#path canonicalization#URL canonicalization#RFC 3986 normalization#reverse proxy path normalization#reverse proxy routing rules#ingress rule matching#ingress path regex#access rules bypass#authentication bypass URL#authorization bypass path#access control path matching#Cloudflare Access path rules#WAF path normalization#API gateway path matching#HTTP request smuggling path#proxy and origin parser differential#path parsing differences#normalization test matrix#URL normalization testing#tunnel routing test cases#cloudflared config.yml#cloudflared hostname path rules#expose localhost securely#localhost tunneling#localhost tunnel security#developer tunneling tools#DevOps routing best practices#cloud-native networking#web security for developers

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles