🔴 Mevcut Sistem - HLS Fallback MP3 Sorunu

📅 Tarih: 2025-12-04 🎯 Tenant: muzibu.com (1001) 🔒 Odak: MP3 Fallback Güvenlik Riski 👤 Hedef: Guest/Normal User için 30 saniye HLS preview

🚨 Kritik Güvenlik Sorunu

⚠️ MP3 FALLBACK RİSKİ - ACİL MÜDAHALE GEREKLİ!

Sorun: HLS dönüşümü tamamlanmamış şarkılar için sistem MP3 fallback kullanıyor. Bu şifresiz MP3 dosyasını direkt serve ediyor!

Risk: MP3 URL'si paylaşılırsa, kimlik doğrulaması olmadan tüm şarkı indirilebilir.

Etkilenen Kullanıcılar: Guest (üye olmayan) + Normal User (premium olmayan)

Etki Alanı: Henüz HLS'e dönüşmemiş tüm şarkılar (lazy conversion bekleyen)

// SongStreamController.php - Mevcut Kod (SORUNLU!) // Guest kullanıcı için: if ($song->hls_converted && !empty($song->hls_path)) { // ✅ HLS dönüşmüş → Güvenli (AES-128 şifreli) $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 60); $streamType = 'hls'; } else { // ❌ HLS dönüşmemiş → MP3 serve et (GÜVENLİK RİSKİ!) $streamUrl = $this->signedUrlService->generateStreamUrl($songId, 30); $streamType = 'mp3'; ← SORUN BURADA! }

📊 Mevcut Durum vs Hedef Durum

❌ MEVCUT DURUM (Sorunlu)

  • HLS dönüşmemişse MP3 serve edilir
  • MP3 URL'si şifresiz erişim sağlar
  • URL paylaşılırsa indirme riski
  • Guest user MP3'e erişebilir
  • 30 saniye kontrolü sadece client-side

✅ HEDEF DURUM (Güvenli)

  • Sadece HLS serve edilir (MP3 fallback yok)
  • Tüm şarkılar AES-128 şifreli
  • URL paylaşımı işe yaramaz
  • Guest user sadece HLS preview (30 saniye)
  • 6 chunk (5 saniye/chunk) hassas kontrol

🎯 Öneri Listesi - Öncelik Sırasıyla

1️⃣ Test Müziklerini HLS'e Dönüştür
KRİTİK ⏱️ 5 dakika

Amaç: Şu anki test şarkılarını (deneme dataları) toplu olarak HLS + AES-128 ile dönüştür.

Nasıl:

# 1. Kaç şarkı HLS'e dönüşmemiş kontrol et mysql -u root -p tuufi_4ekim -e " SELECT COUNT(*) as toplam_sarki, SUM(hls_converted = 0) as hls_olmayan, SUM(hls_converted = 1) as hls_olan FROM tenant_muzibu_1528d0.muzibu_songs WHERE is_active = 1; " # 2. Manuel toplu dönüşüm başlat (Tinker ile) php artisan tinker # 3. Tinker içinde: >>> $songs = \Modules\Muzibu\App\Models\Song::where('hls_converted', 0)->get(); >>> foreach($songs as $song) { \Modules\Muzibu\App\Jobs\ConvertToHLSJob::dispatch($song); } >>> echo "Toplam {$songs->count()} şarkı kuyruğa eklendi";

Beklenen Sonuç: Tüm test şarkıları 5-10 dakika içinde HLS + AES-128'e dönüşecek.

2️⃣ MP3 Fallback'i Kaldır
KRİTİK ⏱️ 10 dakika

Amaç: HLS dönüşmemişse MP3 serve etme, bunun yerine "hazırlanıyor" mesajı göster.

Dosya: SongStreamController.php (Guest + Normal User bölümleri)

// ❌ ESKİ KOD (SongStreamController.php - Line 64-75 ve 109-120) if ($song->hls_converted && !empty($song->hls_path)) { $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 60); $streamType = 'hls'; } else { // MP3 fallback - KALDIRILACAK! $streamUrl = $this->signedUrlService->generateStreamUrl($songId, 30); $streamType = 'mp3'; } // ✅ YENİ KOD if ($song->hls_converted && !empty($song->hls_path)) { // HLS hazır → Serve et $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 60); $streamType = 'hls'; $fallbackUrl = null; return response()->json([ 'status' => 'preview', 'message' => 'Kayıt olun, tam dinleyin', 'stream_url' => $streamUrl, 'stream_type' => 'hls', 'preview_duration' => 30, 'preview_chunks' => 6, 'is_premium' => false, ]); } else { // HLS hazır değil → Dönüşüm başlat + "hazırlanıyor" mesajı ConvertToHLSJob::dispatch($song); return response()->json([ 'status' => 'converting', 'message' => 'Şarkı hazırlanıyor, lütfen 30 saniye bekleyip tekrar deneyin', 'retry_after' => 30, 'preview_duration' => 30, 'is_premium' => false, ], 202); // HTTP 202 Accepted }

Beklenen Sonuç: Hiçbir şarkı şifresiz MP3 olarak serve edilmeyecek!

3️⃣ Chunk Süresi Optimizasyonu (10s → 5s)
ÖNEMLİ ⏱️ 15 dakika

Amaç: 30 saniye preview için daha hassas kontrol. 3 chunk çok az!

Şu an: 10 saniye/chunk → 30 saniye = 3 chunk

Yeni: 5 saniye/chunk → 30 saniye = 6 chunk (2x daha hassas!)

Dosya: ConvertToHLSJob.php

// Line 123: FFmpeg command // ❌ ESKİ: -hls_time 10 (10 saniye/chunk) $command = sprintf( 'ffmpeg -i %s -map 0:a -c:a aac -b:a %dk -af %s -start_number 0 -hls_time 10 ...' ); // ✅ YENİ: -hls_time 5 (5 saniye/chunk) $command = sprintf( 'ffmpeg -i %s -map 0:a -c:a aac -b:a %dk -af %s -start_number 0 -hls_time 5 ...' );

Beklenen Sonuç:

  • 30 saniye preview = 6 chunk (segment-000.ts ... segment-005.ts)
  • Server-side chunk kontrolü daha hassas
  • Guest user 7. chunk'ı isterse → 403 Forbidden

Not: Bu değişiklik sonrası yeni yüklenen şarkılar 5 saniye chunk ile dönüşecek. Mevcut HLS'li şarkılar 10 saniye olarak kalır (sorun değil).

4️⃣ Preview Limiti 30 Saniye Net Ayarla
ÖNEMLİ ⏱️ 5 dakika

Amaç: Response'ta preview_chunks parametresi ekle, frontend'de chunk sayısı kontrolü yap.

Dosya: SongStreamController.php

// Guest User Response return response()->json([ 'status' => 'preview', 'message' => 'Kayıt olun, tam dinleyin', 'stream_url' => $streamUrl, 'stream_type' => 'hls', 'preview_duration' => 30, ← 30 saniye sabit 'preview_chunks' => 6, ← 6 chunk (5 saniye/chunk) 'chunk_duration' => 5, ← Her chunk 5 saniye 'is_premium' => false, ]); // Normal User (Premium değil) Response return response()->json([ 'status' => 'preview', 'message' => 'Premium'a geçin, sınırsız dinleyin', 'stream_url' => $streamUrl, 'stream_type' => 'hls', 'preview_duration' => 30, 'preview_chunks' => 6, 'chunk_duration' => 5, 'is_premium' => false, ]);

Frontend Implementation (Opsiyonel): HLS player'da chunk sayısını kontrol et, 6. chunk'tan sonra durmasını sağla.

5️⃣ Key Endpoint Token Validation
ORTA ⏱️ 20 dakika

Amaç: Encryption key endpoint'ine ek güvenlik katmanları ekle.

Dosya: SongController.php - serveEncryptionKey()

public function serveEncryptionKey(int $id, Request $request) { // 1. Referer Check (Hotlink engelleme) $referer = $request->header('Referer'); $allowedDomain = tenant()->domains->first()->domain; if (!$referer || !str_contains($referer, $allowedDomain)) { Log::warning('Invalid referer for key request', [ 'song_id' => $id, 'referer' => $referer ]); abort(403, 'Invalid referer'); } // 2. User Agent Check (Bot filtresi) $userAgent = $request->userAgent(); if (empty($userAgent) || str_contains(strtolower($userAgent), 'bot')) { abort(403, 'Invalid user agent'); } // 3. Rate Limiting (zaten route'ta var ama double-check) // 4. Song + encryption key kontrolü (mevcut kod) $song = Song::where('song_id', $id)->where('is_active', 1)->first(); // ... rest of the code }

Beklenen Sonuç: Encryption key sadece yetkili stream istekleri için serve edilir, bot/hotlink engellenir.

6️⃣ Signed URL Süresi Kısaltma
ORTA ⏱️ 5 dakika

Amaç: Guest/Normal user için token sürelerini kısalt, URL paylaşım riskini azalt.

Dosya: SongStreamController.php

// ❌ ESKİ SÜRE (Tüm user tipleri için aynı) $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 60); // 60 dakika // ✅ YENİ SÜRE (User tipine göre) // Guest User (üye değil) if (!$user) { $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 10); // 10 dakika } // Normal User (premium değil) if (!$user->isPremium()) { $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 15); // 15 dakika } // Premium User $streamUrl = $this->signedUrlService->generateHlsUrl($songId, 60); // 60 dakika (değişmez)

Beklenen Sonuç: Guest user URL'i paylaşsa bile 10 dakika sonra geçersiz olur.

📋 Implementation Öncelik Tablosu

# İşlem Süre Kritiklik Dosya
1 Test müziklerini HLS'e dönüştür 5 dk 🔴 KRİTİK Tinker
2 MP3 fallback'i kaldır 10 dk 🔴 KRİTİK SongStreamController.php
3 Chunk süresini 5 saniye yap 15 dk 🟡 ÖNEMLİ ConvertToHLSJob.php
4 Preview limiti 30 saniye ayarla 5 dk 🟡 ÖNEMLİ SongStreamController.php
5 Key endpoint güvenliği 20 dk 🟢 ORTA SongController.php
6 Signed URL süresi kısalt 5 dk 🟢 ORTA SongStreamController.php
TOPLAM ~1 saat

🎉 Beklenen Sonuçlar

✅ Bu Değişiklikler Uygulandıktan Sonra:
  • %100 HLS Streaming: Hiçbir şarkı şifresiz MP3 olarak serve edilmeyecek
  • 30 Saniye Preview: Guest/Normal user sadece 6 chunk (30 saniye) dinleyebilecek
  • Hassas Kontrol: 5 saniye/chunk → Server-side chunk index kontrolü kolaylaşacak
  • URL Paylaşımı İşe Yaramaz: Guest için 10 dakika, Normal user için 15 dakika token süresi
  • Key Endpoint Korumalı: Referer + User Agent + Rate limiting ile güçlendirilecek
  • Premium Avantajı Net: Sadece premium user'lar sınırsız dinleyebilir

🚀 Sıradaki Adım

💬 Kullanıcı Onayı Bekleniyor

Seçenek 1: Tüm önerileri sırayla uygula (1-2-3-4-5-6)

Seçenek 2: Sadece kritik olanları uygula (1-2), ardından test et

Seçenek 3: Önce X numaralı öneriyi uygula

👉 Hangi yaklaşımı tercih ediyorsun?