BLOG | NGINX

Sichern von URLs mit dem Secure Link-Modul in NGINX und NGINX Plus

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Kunal Pariani Miniaturbild
Kunal Pariani
Veröffentlicht am 29. Juli 2016

Sowohl die Open-Source-Software NGINX als auch NGINX Plus sind als Webserver, Reverse-Proxys und Caches für Ihre Inhalte sehr sicher und zuverlässig. Für zusätzlichen Schutz vor dem Zugriff durch nicht autorisierte Clients können Sie Anweisungen aus dem Secure Link-Modul verwenden, um von den Clients zu verlangen, dass sie in die URL des angeforderten Assets eine bestimmte gehashte Zeichenfolge aufnehmen.

In diesem Blogbeitrag besprechen wir, wie die beiden im Secure Link-Modul implementierten Methoden konfiguriert werden. Die Beispielkonfigurationsausschnitte schützen HTML- und Medienwiedergabelistendateien, können aber auf jeden Typ von HTTP-URL angewendet werden. Die Methoden gelten sowohl für NGINX als auch für NGINX Plus, der Kürze halber beziehen wir uns im Rest des Blogs jedoch nur auf NGINX Plus.

Eine Übersicht über die Methoden im Secure Link-Modul

Das Secure Link-Modul überprüft die Gültigkeit einer angeforderten Ressource, indem es eine codierte Zeichenfolge in der URL der HTTP-Anforderung mit der Zeichenfolge vergleicht, die es für diese Anforderung berechnet. Wenn ein Link eine begrenzte Lebensdauer hat und die Zeit abgelaufen ist, gilt der Link als veraltet. Der Status dieser Prüfungen wird in der Variable „$secure_link“ erfasst und zur Steuerung des Verarbeitungsflusses verwendet.

Wie erwähnt bietet das Modul zwei Methoden. In einem bestimmten HTTP- , Server- oder Standortkontext kann nur einer davon konfiguriert werden.

  • Der erste und einfachere Modus wird durch die Direktive secure_link_secret aktiviert. Die codierte Zeichenfolge ist ein MD5-Hash, der aus der Verkettung zweier Textzeichenfolgen berechnet wird: dem letzten Teil der URL und einem in der NGINX Plus-Konfiguration definierten geheimen Wort. (Einzelheiten zur ersten Textzeichenfolge finden Sie unter Verwenden einfacher sicherer URLs .)

    Um auf die geschützte Ressource zuzugreifen, muss der Client den Hash direkt nach dem URL-Präfix einfügen. Dabei handelt es sich um eine beliebige Zeichenfolge ohne Schrägstriche. In dieser Beispiel-URL lautet das Präfix „videos“ und die geschützte Ressource ist die Datei bunny.m3u8 :

    /videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8

    Ein Anwendungsfall für diese Methode besteht darin, dass ein Benutzer ein Bild oder Dokument zum Teilen auf einen Server hochlädt, jedoch verhindern möchte, dass jemand, der den Dateinamen kennt, darauf zugreift, bis der offizielle Link veröffentlicht wird.

  • Die zweite, flexiblere Methode wird durch die Anweisungen secure_link und secure_link_md5 aktiviert. Hier ist die codierte Zeichenfolge ein MD5-Hash von Variablen, die in der NGINX Plus-Konfigurationsdatei definiert sind. Am häufigsten wird die Variable $remote_addr eingefügt, um den Zugriff auf eine bestimmte Client-IP-Adresse zu beschränken. Sie können jedoch auch andere Werte verwenden, beispielsweise $http_user_agent , das den User-Agent -Header erfasst und so den Zugriff auf bestimmte Browser beschränkt.

    Optional können Sie ein Ablaufdatum angeben, nach dem die URL, auch wenn der Hash korrekt ist, nicht mehr funktioniert.

    Der Client muss das MD5 -Argument an die Anforderungs-URL anhängen, um den Hash anzugeben. Wenn in der gehashten Zeichenfolge ein Ablaufdatum enthalten ist, muss der Client auch das Argument „expires“ anhängen, um das Datum anzugeben, wie in dieser Beispiel-URL zum Anfordern der geschützten Datei „pricelist.html“ :

    /files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740

Das Secure Link-Modul ist in vorgefertigten Open-Source -NGINX-Binärdateien von nginx.org , den von Betriebssystemanbietern bereitgestellten NGINX-Paketen und in NGINX Plus enthalten. Es ist nicht standardmäßig enthalten, wenn Sie NGINX aus der Quelle erstellen; aktivieren Sie es, indem Sie dem Konfigurationsbefehl das Argument --with-http_secure_link_module hinzufügen.

Verwenden einfacher gesicherter URLs

Die grundlegendere Möglichkeit zum Sichern von URLs ist die Direktive secure_link_secret . Im folgenden Beispielausschnitt sichern wir eine HTTP Live Streaming (HLS)-Medienwiedergabelistendatei mit dem Namen /bunny.m3u8 . Es wird im Verzeichnis /opt/secure/hls gespeichert, wird Clients jedoch über eine URL zugänglich gemacht, die mit dem Präfix „Videos“ beginnt.

Server {
abhören 80;
Servername secure-link-demo;

Standort /Videos {
secure_link_secret enigma;
if ($secure_link = "") { return 403; }

neu schreiben ^ /secure/$secure_link;
}

Standort /secure {
intern;
root /opt;
}
}

Mit dieser Konfiguration müssen Clients zum Zugriff auf die Datei /opt/secure/hls/bunny.m3u8 die folgende URL angeben:

/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8

Der gehashte String folgt direkt auf das Präfix, bei dem es sich um einen beliebigen String ohne Schrägstriche handelt (hier: videos ).

Der Hash wird anhand einer Textzeichenfolge berechnet, die zwei Elemente verkettet:

  • Der Teil der URL, der auf den Hash folgt, hier hls/bunny.m3u8 .
  • Der Parameter zur Direktive secure_link_secret , hier enigma .

Wenn die Anforderungs-URL des Clients nicht über den richtigen Hash verfügt, setzt NGINX Plus die Variable $secure_link auf die leere Zeichenfolge. Der if- Test schlägt fehl und NGINX Plus gibt die 403Verbotener Statuscode in der HTTP-Antwort.

Andernfalls (d. h. der Hash ist korrekt) schreibt die Rewrite- Direktive die URL um, in unserem Beispiel in /secure/hls/bunny.m3u8 (die Variable $secure_link erfasst den Teil der URL, der auf den Hash folgt). URLs, die mit /secure beginnen, werden vom zweiten Standortblock behandelt. Die Root -Direktive in diesem Block legt /opt als Stammverzeichnis für angeforderte Dateien fest und die interne Direktive gibt an, dass der Block nur für intern generierte Anforderungen verwendet wird.

Generieren des Hashs auf dem Client für eine einfache, sichere URL

Um den MD5-Hash im Hexadezimalformat zu erhalten, den der Client in die URL aufnehmen muss, führen wir den Befehl openssl md5 mit der Option -hex aus:

# echo -n 'hls/bunny.m3u8enigma' | openssl md5 -hex (stdin)= 80e2dfecb5f54513ad4e2e6217d36fd4

Eine Erläuterung der programmgesteuerten Hash-Generierung finden Sie unter Programmgesteuertes Generieren von Hashes .

Serverantwort auf grundlegende gesicherte URLs

Die folgenden Beispiel -Curl -Befehle zeigen, wie der Server auf verschiedene sichere URLs reagiert.

Wenn die URL den korrekten MD5-Hash enthält, lautet die Antwort200 OK :

# curl -I http://secure-link-demo/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8 | head -n 1 HTTP/1.1 200 OK

Wenn der MD5-Hash falsch ist, lautet die Antwort403 Verboten :

# curl -I http://secure-link-demo/videos/2c5e80de986b6fc80dd33e16cf824123/hls/bunny.m3u8 | head -n 1 HTTP/1.1 403 Verboten

Wenn der Hash für bunny.m3u8 für eine andere Datei verwendet wird, lautet die Antwort ebenfalls403 Verboten :

# curl -I http://secure-link-demo/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hs/oven.m3u8 | head -n 1 HTTP/1.1 403 Verboten

Verwenden gesicherter URLs, die ablaufen

Die flexiblere Methode zum Sichern von URLs verwendet die Anweisungen secure_link und secure_link_md5 . In diesem Beispiel verwenden wir sie, um den Zugriff auf die Datei /var/www/files/pricelist.html nur von Clients mit der IP-Adresse 192.168.33.14 und nur bis zum 31. Dezember 2016 zuzulassen.

Unser virtueller Server lauscht auf Port 80 und verarbeitet alle gesicherten HTTP-Anfragen im Speicherort- /Files -Block, wobei die Root- Direktive /var/www als Stammverzeichnis für angeforderte Dateien festlegt.

Die Direktive „secure_link“ definiert zwei Variablen, die Argumente in der Anforderungs-URL erfassen: „$arg_md5“ wird auf den Wert des „md5“ -Arguments gesetzt und „$arg_expires“ auf den Wert des „expires “-Arguments.

Die Direktive secure_link_md5 definiert den Ausdruck, der gehasht wird, um den MD5-Wert für die Anfrage zu generieren; während der URL-Verarbeitung wird der Hash mit dem Wert von $arg_md5 verglichen. Der Beispielausdruck hier enthält die in der Anforderung übergebene Ablaufzeit (erfasst in der Variable $secure_link_expires ), die URL ( $uri ), die Client-IP-Adresse ( $remote_addr ) und das Wort enigma .

Server {
Listen 80;
Servername secure-link-demo;

Standort /files {
root /var/www;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr enigma";

if ($secure_link = "") { return 403; }
if ($secure_link = "0") { return 410; }
}
}

Um mit dieser Konfiguration auf /var/www/files/pricelist.html zuzugreifen, muss ein Client mit der IP-Adresse 192.168.33.14 diese Anforderungs-URL vor Samstag, 31. Dezember 2016, 23:59:00 UTC senden:

/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740

Wenn der Hash in der vom Client gesendeten URL (erfasst in der Variable $arg_md5 ) nicht mit dem aus der Direktive secure_link_md5 berechneten Hash übereinstimmt, setzt NGINX Plus die Variable $secure_link auf die leere Zeichenfolge. Der if- Test schlägt fehl und NGINX Plus gibt die403 Verbotener Statuscode in der HTTP-Antwort.

Wenn die Hashes übereinstimmen, der Link jedoch abgelaufen ist, setzt NGINX Plus den $sicherer_Link variabel auf 0; wieder die Wenn Der Test schlägt fehl, aber dieses Mal gibt NGINX Plus das 410 Gegangen Statuscode in der HTTP-Antwort.

Generieren des Hashs und der Ablaufzeit auf einem Client

Sehen wir uns nun an, wie ein Client die MD5- und Ablaufargumente berechnet, die in die URL aufgenommen werden sollen.

Der erste Schritt besteht darin, das Unix-Zeitäquivalent des Ablaufdatums zu bestimmen, da dieser Wert in Form der Variablen $secure_link_expires im gehashten Ausdruck enthalten ist. Um die Unix-Zeit zu erhalten – die Anzahl der Sekunden seit Epoche (1970-01-01 00:00:00 UTC) – verwenden wir den Datumsbefehl mit der Option -d und dem Formatbezeichner +%s .

In unserem Beispiel legen wir die Ablaufzeit auf Samstag, 31. Dezember 2016, 23:59:00 UTC fest. Der Befehl lautet also:

# Datum -d "2016-12-31 23:59" +%s1483228740

Der Client schließt diesen Wert als Argument expires=1483228740 in die Anforderungs-URL ein.

Nun führen wir den durch die Direktive secure_link_md5 definierten String – $secure_link_expires$uri$remote_addr enigma – durch drei Befehle aus:

  • Der Befehl openssl md5 mit der Option -binary generiert den MD5-Hash im Binärformat.
  • Der Befehl openssl base64 wendet die Base64- Kodierung auf den Hashwert an.
  • Die tr -Befehle ersetzen das Pluszeichen ( + ) durch den Bindestrich ( - ) und den Schrägstrich ( / ) durch den Unterstrich ( _ ) und löschen das Gleichheitszeichen ( = ) aus dem codierten Wert.

Für unser Beispiel lautet der vollständige Befehl:

# echo -n '1483228740/files/pricelist.html192.168.33.14 enigma' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = AUEnXC7T-Tfv9WLsWbf-mw

Der Client schließt diesen Wert als Argument md5=AUEnXC7T-Tfv9WLsWbf-mw in die Anforderungs-URL ein.

Programmgesteuertes Generieren des Hashs

Wenn Ihr NGINX Plus-Webserver dynamische Inhalte von einem Anwendungsserver bereitstellt, müssen sowohl NGINX Plus als auch der Anwendungsserver dieselbe sichere URL verwenden. Sie können den Hash für das MD5 -Argument in der URL programmgesteuert generieren. Die folgende Node.js-Funktion generiert einen Hash, der mit dem im obigen NGINX Plus-Konfigurationsausschnitt definierten übereinstimmt. Es verwendet eine Ablaufzeit, eine URL, eine Client-IP-Adresse und ein geheimes Wort als Argumente und gibt den Base64-codierten MD5-Hash im Binärformat zurück.

var crypto = require("crypto");

Funktion generateSecurePathHash(expires, url, client_ip, secret) {
if (!expires || !url || !client_ip || !secret) {
return undefiniert;
}

var input = expires + url + client_ip + " " + secret;
var binaryHash = crypto.createHash("md5").update(input).digest();
var base64Value = neuer Puffer(binaryHash).toString('base64');
return base64Value.replace(/=/g, '').replace(/+/g, '-').replace(///g, '_');
}

Um den Hash für unser aktuelles Beispiel zu berechnen, übergeben wir diese Argumente:

generateSecurePathHash(neues Datum('12/31/2016 23:59:00').getTime()), '/files/pricelist.html', „192.168.33.14“, „enigma“);

Serverantwort auf gesicherte URLs mit Ablaufzeiten

Die folgenden Beispiel -Curl -Befehle zeigen, wie der Server auf sichere URLs reagiert.

Wenn ein Client mit der IP-Adresse 192.168.33.14 den korrekten MD5-Hash und die Ablaufzeit angibt, lautet die Antwort200 OK :

# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 200 OK

Wenn ein Client mit einer anderen IP-Adresse dieselbe URL sendet, lautet die Antwort403 Verboten :

# curl -I --interface "192.168.33.33" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 403 Verboten

Wenn der Hashwert des MD5 -Arguments falsch ist, lautet die Antwort403 Verboten :

# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=qeUNjiY2FTIVMaXUsxG-7w&expires=1483228740' | head -n 1 HTTP/1.1 403 Verboten

Wenn die URL abgelaufen ist (das durch das Argument expires dargestellte Datum liegt in der Vergangenheit), lautet die Antwort410 Gegangen :

# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=Z2rNva2InyVcRTlhqAkT4Q&expires=1467417540' | head -n 1 HTTP/1.1 410 Weg

Beispiel – Segmentdateien mit Ablaufdatum sichern

Hier ist ein weiteres Beispiel für eine sichere URL mit Ablaufdatum, die zum Schutz sowohl der Wiedergabeliste für ein Medienobjekt als auch der Segmentdateien verwendet wird.

Ein Unterschied zum vorhergehenden Beispiel besteht darin, dass wir hier einen Kartenkonfigurationsblock hinzufügen, um die Erweiterung aus der Wiedergabeliste ( .m3u8 -Datei) und aus den HLS-Segmenten ( .ts -Dateien) zu entfernen, während wir den Dateinamen in der Variable „$file_name“ erfassen, die an die Direktive „secure_link_md5“ übergeben wird. Dies dient der Absicherung der Anfragen sowohl an die einzelnen .ts Segmente als auch an die Playlist.

Ein weiterer Unterschied zum ersten Beispiel besteht darin, dass wir die Variable $http_user_agent (die den User-Agent- Header erfasst) in die Direktive secure_link_md5 aufnehmen, um den Zugriff auf Clients in bestimmten Webbrowsern einzuschränken (beispielsweise, damit die URL in Safari funktioniert, aber nicht in Chrome oder Firefox).

map $uri $file_name {
Standard keine;
"~*/s/(?<name>.*).m3u8" $name;
"~*/s/(?<name>.*).ts" $name;
}

Server {
abhören 80;
Servername secure-link-demo;

Standort /s {
root /opt;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$file_name$http_user_agent enigma";

if ($secure_link = "") { return 403; }
if ($secure_link = "0") { return 410; }
}
}

Zusammenfassung

Mit dem Secure Link-Modul in NGINX können Sie Dateien vor unberechtigtem Zugriff schützen, indem Sie verschlüsselte Daten hinzufügen, beispielsweise den Hash eines bestimmten Teils der URL. Durch das Hinzufügen einer Ablaufzeit wird auch die Gültigkeitsdauer von Links begrenzt, um die Sicherheit noch weiter zu erhöhen.

Um NGINX Plus auszuprobieren, starten Sie noch heute Ihre kostenlose 30-Tage-Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen.


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."