保护 Laravel Reverb
在构建现代应用程序时,Laravel 是 Web 开发的热门选择。凭借其庞大的生态系统,Laravel Reverb 等工具有助于增强开发人员体验,使管理后端流程变得更加容易。但是,与任何工具一样,安全性必须是重中之重。
我将尝试探索保护 Laravel Reverb 的关键实践和可操作步骤,并确保您的实施免受潜在漏洞的影响。
1. 了解 Laravel Reverb 的作用
Laravel Reverb 充当消息代理和事件管理器,促进服务之间的通信。默认情况下,它与 Laravel 的队列和事件系统深度集成。但是,由于它涉及实时数据处理,配置错误可能会使敏感操作暴露于攻击。
潜在风险
2. 保护你的队列配置
Laravel Reverb 依赖于队列驱动程序。配置错误的队列系统可能会导致漏洞。
**特定于环境的驱动程序**:在生产环境中使用安全驱动程序,如 Redis。避免在生产中使用“数据库”或“同步”。这些驱动程序可能会带来性能和安全问题。“数据库”驱动程序会增加大量的数据库负载,使其容易受到 DoS 攻击,并且如果数据库受到攻击,可能会暴露敏感的作业数据。“同步”驱动程序同步执行作业,增加了通过错误暴露敏感信息的风险,并造成了攻击者可以利用的瓶颈,从而使应用程序过载。
QUEUE_CONNECTION=redis
**Redis 身份验证**:对 Redis 连接使用强密码。
REDIS_PASSWORD=your_secure_password
**TLS 加密:**如果远程使用基于云的队列,请启用 TLS 以实现安全通信。当 Redis 或其他队列驱动程序托管在外部时,这一点尤为重要。对于安全网络上的内部托管队列,TLS 可能不是必需的。
3. 验证事件数据
始终验证在事件和侦听器之间传递的数据。Laravel 提供了验证工具,应在事件调度和侦听器阶段应用。
例子:
use Illuminate\Support\Facades\Validator;
class SecureEvent
{
public function __construct(array $data)
{
Validator::make($data, [
'user_id' => 'required|integer',
'action' => 'required|string|max:255',
])->validate();
$this->data = $data;
}
}4. 安全 API 端点
Laravel Reverb 经常公开用于管理事件和队列的 API 端点。限制对这些端点的访问。
**例子:**
**中间件保护:**使用身份验证和授权中间件。
Route::middleware(['auth:sanctum', 'verified'])->group(function () {
Route::post('/reverb/dispatch', [ReverbController::class, 'dispatch']);
});**速率限制**:通过限制 API 请求来防止滥用。
Route::middleware('throttle:60,1')->group(function () {
Route::post('/reverb/dispatch', [ReverbController::class, 'dispatch']);
});5. 安全通道配置
Laravel Reverb 频道决定事件的广播方式以及谁可以访问它们。配置错误的频道可能会暴露敏感数据或允许未经授权的访问。
**公共频道:**
任何知道频道名称的人都可以访问公共频道。避免使用公共频道来获取敏感信息。
例子:
Broadcast::channel('public-channel', function () {
return true;
});仅将公共渠道用于非敏感数据,例如通知或一般更新。
**私人频道:**
私人频道要求在加入前进行身份验证。使用这些频道来处理与经过身份验证的用户相关的事件。
例子:
Broadcast::channel('private-channel.{userPublicId}', function ($user, $userPublicId) {
return $user->public_id === $userPublicId && auth()->check(); // Ensure Public ID matches and user is authenticated
});**存在渠道:**
在线频道通过允许服务器实时跟踪哪些用户在线来扩展私人频道。实施严格的身份验证以防止未经授权的访问。
例子:
Broadcast::channel('presence-channel.{roomId}', function ($user, $roomId) {
return $user->isInRoom($roomId); // Validate room access
});6. 队列存储过载
队列过载是指一次性添加过多作业,从而导致延迟。使用 Laravel 的 ThrottlesExceptions 中间件来限制作业处理(例如每秒 5 个作业),并使用 Supervisor 等工具管理工作者以确保系统稳定性。
namespace App\Jobs;
use Log;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\Middleware\ThrottlesExceptions;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessNotification implements ShouldQueue
{
use Queueable;
public function middleware()
{
// Throttle: Allow max 5 jobs per second for this queue
return [new ThrottlesExceptions(5, 1)];
}
public function handle()
{
// Logic to process the notification
Log::info('Processing notification');
}
}7. 事件重放攻击
重放攻击会重新发送拦截的事件以利用您的系统。为事件添加唯一 ID 和时间戳,在客户端和服务器上对其进行验证,以防止重复并确保仅处理新事件。
实现唯一令牌:
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Support\Str;
class ChatMessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets;
public string $message;
public string $uniqueId; // Prevent replay attacks
public int $timestamp;
public function __construct(string $message)
{
$this->message = $message;
$this->uniqueId = Str::uuid();
$this->timestamp = time();
}
public function broadcastWith()
{
return [
'message' => $this->message,
'uniqueId' => $this->uniqueId,
'timestamp' => $this->timestamp,
];
}
public function broadcastOn()
{
return ['chat-room'];
}
}通过在客户端跟踪uniqueId来防止重复处理同一事件:
const processedEvents = new Set();
Echo.channel('chat-room')
.listen('ChatMessageSent', (event) => {
if (!processedEvents.has(event.uniqueId)) {
processedEvents.add(event.uniqueId);
console.log('New message:', event.message);
}
});使用中间件确保事件时间戳是最新的:
namespace App\Http\Middleware;
use Closure;
class PreventEventReplay
{
public function handle($request, Closure $next)
{
$timestamp = $request->header('X-Timestamp');
if (abs(time() - $timestamp) > 10) { // Allow a 10-second window
return response()->json(['error' => 'Invalid or stale request.'], 400);
}
return $next($request);
}
}8. 安全后端 SSL 连接
即使您使用 Cloudflare 之类的服务作为代理来处理边缘 SSL,在服务器上的 VirtualHost 内配置 SSL 也很重要。这可确保端到端加密并降低潜在风险。
**执行:**
1. 安装 Certbot 并获取证书:
sudo certbot --apache
2. 更新您的 VirtualHost 以使用 SSL:
ServerName yourdomain.com DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem
3. 在 Cloudflare 中启用完整(严格)SSL 模式。
9. 所有通信均使用 HTTPS
为了确保 Reverb 与客户端或服务器之间的安全通信,请使用 HTTPS。更新以下环境变量,特别注意设置“REVERB_SCHEME”和“REVERB_PORT”,以确保使用 HTTPS 协议和安全端口 443:
REVERB_HOST=example.com
REVERB_PORT=443
REVERB_SCHEME=https
REVERB_APP_ID=secure_app_id
REVERB_APP_KEY=secure_app_key
REVERB_APP_SECRET=secure_app_secret
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST=example.com
VITE_REVERB_PORT=443
VITE_REVERB_SCHEME=https