Manchmal liegen Mediendateien auf einem Server, der nicht direkt öffentlich erreichbar ist — oder der Zugriff soll auf authentifizierte Nutzer beschränkt werden. Ein PHP-Streaming-Proxy löst beide Probleme elegant.
Grundprinzip
Der Proxy öffnet die Datei (lokal oder per SSH/SCP auf einem entfernten Host), prüft Berechtigungen und streamt sie mit korrekten HTTP-Headern zum Browser. Der Nutzer sieht nur die öffentliche Proxy-URL — keine internen Pfade.
<?php
// Sicherheits-Checks zuerst
if (!isLoggedIn()) { http_response_code(403); exit; }
$file = basename($_GET["f"] ?? "");
$allowed_dir = "/var/media/audio/";
$full_path = $allowed_dir . $file;
// Path-Traversal verhindern
if (strpos(realpath($full_path), realpath($allowed_dir)) !== 0) {
http_response_code(403); exit;
}
if (!file_exists($full_path)) { http_response_code(404); exit; }
// MIME-Typ bestimmen
$mime_map = ["mp3" => "audio/mpeg", "flac" => "audio/flac", "ogg" => "audio/ogg"];
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
$mime = $mime_map[$ext] ?? "application/octet-stream";
// Streaming-Header
header("Content-Type: $mime");
header("Content-Length: " . filesize($full_path));
header("Accept-Ranges: bytes");
header("X-Accel-Buffering: no"); // nginx buffering deaktivieren
header("Cache-Control: no-cache");
// Datei streamen
readfile($full_path);
Remote-Dateien via SSH streamen
Wenn die Mediendateien auf einem anderen Server liegen, kann PHP via popen() und SSH die Datei direkt durchleiten — ohne sie lokal zwischenzuspeichern:
$ssh_key = "/pfad/zum/ssh-key";
$ssh_user = "media-user";
$ssh_host = "media-server";
$remote = escapeshellarg("/media/" . $file);
$cmd = "ssh -i $ssh_key -o StrictHostKeyChecking=no "
. "-o BatchMode=yes $ssh_user@$ssh_host cat $remote";
header("Content-Type: audio/mpeg");
header("X-Accel-Buffering: no");
$handle = popen($cmd, "r");
while (!feof($handle)) {
echo fread($handle, 65536);
flush();
}
pclose($handle);
Sicherheitshinweise
- Immer
basename()auf Benutzereingaben anwenden und gegen ein Whitelist-Verzeichnis prüfen - SSH-Key ohne Passphrase +
command=-Restriction inauthorized_keysnutzen (nurcaterlaubt) - Dateigröße für
Content-Lengthnur setzen wenn bekannt — sonst weglassen (chunked transfer) - Rate-Limiting auf die Proxy-URL einrichten um Bandbreiten-Missbrauch zu verhindern