فصل ۳: پیکربندی پیشرفته Reverb

در این فصل، به بررسی پیکربندی‌های پیشرفته Laravel Reverb در نسخه ۱۲ لاراول می‌پردازیم. این شامل تنظیم credentials و allowed origins، پشتیبانی از چندین اپلیکیشن، پیکربندی SSL/TLS برای اتصالات امن، و مدیریت هاست و پورت است. هدف این است که توسعه‌دهندگان بتوانند Reverb را برای سناریوهای پیچیده‌تر و محیط‌های تولید آماده کنند. تمام مثال‌ها و کدها بر اساس مستندات رسمی لاراول ۱۲.x و بهترین شیوه‌های توسعه تنظیم شده‌اند.

تنظیم Credentials و Allowed Origins در config/reverb.php

فایل config/reverb.php که پس از اجرای php artisan reverb:install ایجاد می‌شود، تنظیمات اصلی Reverb را تعریف می‌کند. این فایل شامل متغیرهایی برای مدیریت credentials و محدود کردن دسترسی به سرور WebSocket است.

تنظیمات Credentials

Credentials شامل app_id، key و secret هستند که برای احراز هویت کلاینت‌ها استفاده می‌شوند. نمونه‌ای از فایل config/reverb.php:

<?php

return [
    'apps' => [
        [
            'app_id' => env('REVERB_APP_ID', 'my-reverb-app'),
            'key' => env('REVERB_APP_KEY', 'your-app-key'),
            'secret' => env('REVERB_APP_SECRET', 'your-app-secret'),
            'capacity' => null,
            'allowed_origins' => ['*'],
        ],
    ],

    'host' => env('REVERB_HOST', 'localhost'),
    'port' => env('REVERB_PORT', 8080),
    'scheme' => env('REVERB_SCHEME', 'http'),
    'scaling' => [
        'enabled' => env('REVERB_SCALING_ENABLED', false),
        'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
    ],
];
  • app_id: شناسه منحصربه‌فرد اپلیکیشن. باید با مقدار REVERB_APP_ID در فایل .env همخوانی داشته باشد.
  • key و secret: برای احراز هویت کلاینت‌ها هنگام اتصال به WebSocket استفاده می‌شوند.
  • allowed_origins: لیستی از دامنه‌های مجاز برای اتصال به سرور Reverb. به‌صورت پیش‌فرض روی * تنظیم شده (همه دامنه‌ها مجازند)، اما در تولید باید محدود شود.

تنظیم Allowed Origins

برای افزایش امنیت، باید دامنه‌های مجاز برای اتصال به Reverb را مشخص کنید. مثلاً، اگر اپلیکیشن شما روی example.com اجرا می‌شود، فایل config/reverb.php را به این صورت ویرایش کنید:

'allowed_origins' => ['example.com', 'www.example.com'],

نکته امنیتی: استفاده از * در محیط تولید خطرناک است، زیرا هر دامنه‌ای می‌تواند به سرور Reverb متصل شود. همیشه دامنه‌های خاص را مشخص کنید.

به‌روزرسانی فایل .env

اطمینان حاصل کنید که متغیرهای زیر در فایل .env تنظیم شده‌اند:

REVERB_APP_ID=my-reverb-app
REVERB_APP_KEY=your-unique-key
REVERB_APP_SECRET=your-unique-secret

برای تولید مقادیر امن، می‌توانید از دستور زیر استفاده کنید:

php artisan key:generate --show

پشتیبانی از چندین اپلیکیشن (Multi-App Setup)

Reverb از چندین اپلیکیشن در یک سرور پشتیبانی می‌کند، که برای پروژه‌هایی با چندین کلاینت (مانند اپلیکیشن‌های جداگانه یا tenant‌ها در یک سیستم چندگانه) مفید است. برای این کار، آرایه apps در config/reverb.php را گسترش دهید.

مثال: تنظیم دو اپلیکیشن

فرض کنید دو اپلیکیشن دارید: یک اپلیکیشن چت (chat-app) و یک داشبورد تحلیلی (analytics-app). فایل config/reverb.php را به این صورت تنظیم کنید:

<?php

return [
    'apps' => [
        [
            'app_id' => 'chat-app',
            'key' => 'chat-app-key',
            'secret' => 'chat-app-secret',
            'capacity' => 100, // حداکثر تعداد اتصالات همزمان
            'allowed_origins' => ['chat.example.com'],
        ],
        [
            'app_id' => 'analytics-app',
            'key' => 'analytics-app-key',
            'secret' => 'analytics-app-secret',
            'capacity' => 50,
            'allowed_origins' => ['analytics.example.com'],
        ],
    ],

    'host' => env('REVERB_HOST', 'localhost'),
    'port' => env('REVERB_PORT', 8080),
    'scheme' => env('REVERB_SCHEME', 'http'),
];

نکات:

  • capacity: تعداد حداکثر اتصالات همزمان برای هر اپلیکیشن را محدود می‌کند (اختیاری).
  • کلاینت‌ها: هر اپلیکیشن باید از app_id و key مربوطه در تنظیمات Laravel Echo استفاده کند.
  • مدیریت منابع: برای جلوگیری از بار اضافی روی سرور، تعداد اتصالات را محدود کنید.

تست Multi-App Setup

  1. سرور Reverb را اجرا کنید:
php artisan reverb:start
  1. با استفاده از wscat به هر اپلیکیشن متصل شوید:
wscat -c ws://localhost:8080/app/chat-app-key?protocol=7&client=js
wscat -c ws://localhost:8080/app/analytics-app-key?protocol=7&client=js

پیکربندی SSL/TLS برای اتصالات امن

برای محیط تولید، استفاده از SSL/TLS برای اتصالات WebSocket ضروری است تا داده‌ها رمزنگاری شوند. Reverb از پروتکل wss:// پشتیبانی می‌کند، که نسخه امن WebSocket است.

استفاده از Laravel Herd/Valet

در محیط توسعه، ابزارهایی مانند Laravel Herd یا Valet می‌توانند گواهی‌های SSL خودکار تولید کنند:

  1. Laravel Herd:

  2. Herd به‌صورت پیش‌فرض SSL را برای دامنه‌های محلی (مانند reverb-project.test) فعال می‌کند.

  3. فایل .env را به‌روزرسانی کنید:
REVERB_SCHEME=https
REVERB_HOST=reverb-project.test
REVERB_PORT=443
  1. Laravel Valet:

  2. دامنه را با SSL فعال کنید:

valet secure reverb-project
  • تنظیمات .env را مانند بالا به‌روزرسانی کنید.

استفاده از گواهی‌های سفارشی

برای سرورهای تولید، می‌توانید از گواهی‌های Let’s Encrypt یا گواهی‌های تجاری استفاده کنید:

  1. گواهی‌های SSL (فایل‌های .crt و .key) را در سرور ذخیره کنید (مثلاً در /etc/ssl/).
  2. فایل config/reverb.php را برای استفاده از SSL به‌روزرسانی کنید:
<?php

return [
    'apps' => [
        [
            'app_id' => env('REVERB_APP_ID', 'my-reverb-app'),
            'key' => env('REVERB_APP_KEY', 'your-app-key'),
            'secret' => env('REVERB_APP_SECRET', 'your-app-secret'),
            'allowed_origins' => ['example.com'],
        ],
    ],

    'host' => env('REVERB_HOST', 'example.com'),
    'port' => env('REVERB_PORT', 443),
    'scheme' => env('REVERB_SCHEME', 'https'),
    'ssl' => [
        'local_cert' => '/etc/ssl/cert.pem',
        'local_pk' => '/etc/ssl/private.key',
        'passphrase' => null,
    ],
];
  1. فایل .env را به‌روزرسانی کنید:
REVERB_SCHEME=https
REVERB_HOST=example.com
REVERB_PORT=443
  1. سرور Reverb را با SSL اجرا کنید:
php artisan reverb:start

ایجاد و استفاده از گواهی Self-Signed برای Reverb

در محیط‌های توسعه یا تست که دسترسی به گواهی‌های معتبر SSL (مانند Let’s Encrypt) ممکن نیست، می‌توانید از گواهی‌های Self-Signed برای فعال کردن پروتکل wss:// استفاده کنید. این گواهی‌ها توسط خود شما تولید می‌شوند و نیازی به مقام صدور گواهی (CA) ندارند، اما به دلیل عدم تأیید توسط CA، مرورگرها و کلاینت‌ها ممکن است هشدارهای امنیتی نمایش دهند. این روش برای محیط‌های غیرتولیدی مناسب است.

مرحله ۱: تولید گواهی Self-Signed

برای ایجاد گواهی Self-Signed، می‌توانید از ابزار OpenSSL استفاده کنید که معمولاً روی اکثر سیستم‌های لینوکس، مک و ویندوز (با نصب OpenSSL) در دسترس است.

  1. نصب OpenSSL (در صورت نیاز):

  2. در لینوکس (Ubuntu/Debian):

sudo apt-get install openssl
  • در مک:
brew install openssl
  • در ویندوز، می‌توانید OpenSSL را از پروژه‌هایی مانند Git Bash یا WSL نصب کنید.

  • تولید کلید خصوصی و گواهی:

در ترمینال، دستور زیر را اجرا کنید تا یک کلید خصوصی (private.key) و گواهی Self-Signed (cert.pem) تولید شود:

openssl req -x509 -newkey rsa:4096 -keyout private.key -out cert.pem -days 365 -nodes
  • توضیحات:
    • req -x509: ایجاد یک گواهی Self-Signed.
    • -newkey rsa:4096: تولید کلید خصوصی RSA با طول 4096 بیت.
    • -keyout private.key: ذخیره کلید خصوصی در فایل private.key.
    • -out cert.pem: ذخیره گواهی در فایل cert.pem.
    • -days 365: تنظیم مدت اعتبار گواهی به یک سال.
    • -nodes: عدم رمزگذاری کلید خصوصی (برای ساده‌سازی در توسعه).

در حین اجرا، اطلاعاتی مانند نام کشور، سازمان و دامنه از شما خواسته می‌شود. برای دامنه، می‌توانید localhost یا نام دامنه توسعه (مانند reverb-project.test) وارد کنید. مثال:

Country Name (2 letter code) [AU]: IR
State or Province Name (full name) [Some-State]: Tehran
Locality Name (eg, city) []: Tehran
Organization Name (eg, company) [Internet Widgits Pty Ltd]: MyCompany
Organizational Unit Name (eg, section) []: Development
Common Name (e.g. server FQDN or YOUR name) []: localhost
Email Address []: dev@example.com
  1. ذخیره فایل‌ها:

فایل‌های cert.pem و private.key را در یک مسیر امن در پروژه خود ذخیره کنید، مثلاً در storage/ssl/:

mkdir -p storage/ssl
mv cert.pem private.key storage/ssl/

مرحله ۲: پیکربندی Reverb برای استفاده از گواهی Self-Signed

فایل config/reverb.php را برای اشاره به گواهی و کلید خصوصی به‌روزرسانی کنید:

<?php

return [
    'apps' => [
        [
            'app_id' => env('REVERB_APP_ID', 'my-reverb-app'),
            'key' => env('REVERB_APP_KEY', 'your-app-key'),
            'secret' => env('REVERB_APP_SECRET', 'your-app-secret'),
            'allowed_origins' => ['localhost', 'reverb-project.test'],
        ],
    ],

    'host' => env('REVERB_HOST', 'localhost'),
    'port' => env('REVERB_PORT', 443),
    'scheme' => env('REVERB_SCHEME', 'https'),
    'ssl' => [
        'local_cert' => base_path('storage/ssl/cert.pem'),
        'local_pk' => base_path('storage/ssl/private.key'),
        'passphrase' => null,
    ],
];
  • توضیحات:

  • local_cert: مسیر فایل گواهی (cert.pem).

  • local_pk: مسیر فایل کلید خصوصی (private.key).
  • passphrase: اگر کلید خصوصی رمزگذاری شده باشد، رمز عبور را اینجا وارد کنید (در این مثال نیازی نیست).

فایل .env را نیز به‌روزرسانی کنید:

REVERB_SCHEME=https
REVERB_HOST=localhost
REVERB_PORT=443
REVERB_SERVER_HOST=127.0.0.1

مرحله ۳: اجرای سرور Reverb با SSL

سرور Reverb را با تنظیمات SSL اجرا کنید:

php artisan reverb:start

مرحله ۴: تست اتصال با گواهی Self-Signed

  1. اتصال با wscat:

برای تست، از wscat استفاده کنید و گزینه --no-check را برای نادیده گرفتن هشدارهای گواهی Self-Signed اضافه کنید:

wscat -c wss://localhost:443/app/your-app-key?protocol=7&client=js --no-check
  • اگر اتصال برقرار شود، باید یک پرامپت > ببینید که نشان‌دهنده اتصال موفق است.

  • اتصال با مرورگر:

در مرورگر، به دلیل Self-Signed بودن گواهی، ممکن است هشدار امنیتی ببینید. برای ادامه، باید گواهی را به‌صورت دستی بپذیرید:

  • در Chrome/Firefox، روی "Advanced" یا "Proceed to unsafe" کلیک کنید.
  • برای جلوگیری از هشدارها در توسعه، می‌توانید گواهی را به لیست گواهی‌های مورد اعتماد سیستم اضافه کنید:
  • در لینوکس/مک:
sudo cp storage/ssl/cert.pem /usr/local/share/ca-certევ
sudo update-ca-certificates
  • در ویندوز:
certutil -addstore -f "Root" storage/ssl/cert.pem
  1. تست با Laravel Echo: فایل welcome.blade.php را برای استفاده از wss:// به‌روزرسانی کنید (مانند مثال عملی در متن اصلی، اما با wss://):
const ws = new WebSocket('wss://localhost:443/app/your-app-key?protocol=7&client=js');

مرحله ۵: نکات مهم برای گواهی Self-Signed

  • هشدارهای مرورگر: به دلیل Self-Signed بودن، کاربران باید به‌صورت دستی گواهی را بپذیرند، که برای محیط تولید مناسب نیست.
  • محیط تولید: در تولید، از گواهی‌های معتبر (مانند Let’s Encrypt) استفاده کنید.
  • امنیت فایل‌ها: فایل‌های cert.pem و private.key را در .gitignore قرار دهید تا در مخزن پروژه آپلود نشوند.

تست نهایی

  1. به https://localhost/send-secure بروید و پیام‌های ارسال‌شده را بررسی کنید.
  2. لاگ‌های Reverb را با گزینه --debug بررسی کنید:
php artisan reverb:start --debug

ادغام با متن اصلی

این بخش را می‌توان بعد از زیربخش "استفاده از گواهی‌های سفارشی" در بخش "پیکربندی SSL/TLS برای اتصالات امن" اضافه کرد. ساختار پیشنهادی به این صورت است:

  1. پیکربندی SSL/TLS برای اتصالات امن (متن اصلی)
  2. استفاده از Laravel Herd/Valet (متن اصلی)
  3. استفاده از گواهی‌های سفارشی (متن اصلی)
  4. ایجاد و استفاده از گواهی Self-Signed برای Reverb (بخش جدید)
  5. تست اتصال امن (متن اصلی)

نکات اضافی

  • این بخش با محتوای موجود هماهنگ است و تمرکز آن بر محیط توسعه است، در حالی که بخش‌های دیگر روی تولید متمرکز هستند.
  • کدهای نمونه و دستورات با نسخه ۱۲ لاراول و Reverb سازگار هستند.
  • برای حفظ یکپارچگی، از همان سبک نگارش و ساختار استفاده شده است.

اگر نیاز به تغییرات خاصی در این بخش یا ادغام متفاوت دارید، لطفاً اطلاع دهید!

تست اتصال امن

با استفاده از wscat:

wscat -c wss://example.com:443/app/your-app-key?protocol=7&client=js

مدیریت Host و Port (تفاوت REVERB_SERVER_HOST و REVERB_HOST)

در تنظیمات Reverb، دو متغیر مرتبط با هاست وجود دارد که گاهی باعث سردرگمی می‌شوند:

  • REVERB_HOST: هاستی که کلاینت‌ها (مانند Laravel Echo) برای اتصال به سرور Reverb استفاده می‌کنند. این معمولاً دامنه عمومی (مانند example.com) یا localhost در توسعه است.
  • REVERB_SERVER_HOST: هاستی که سرور Reverb روی آن bind می‌شود. این معمولاً 0.0.0.0 (برای گوش دادن به تمام رابط‌ها) یا یک IP خاص در سرور است.

تفاوت در عمل

  • محیط توسعه:
REVERB_HOST=localhost
REVERB_SERVER_HOST=127.0.0.1
REVERB_PORT=8080

در اینجا، کلاینت‌ها به ws://localhost:8080 متصل می‌شوند، اما سرور روی 127.0.0.1:8080 bind می‌شود.

  • محیط تولید با Reverse Proxy:

فرض کنید از Nginx به‌عنوان reverse proxy استفاده می‌کنید:

REVERB_HOST=example.com
REVERB_SERVER_HOST=127.0.0.1
REVERB_PORT=8080

کلاینت‌ها به wss://example.com متصل می‌شوند، اما Nginx درخواست‌ها را به 127.0.0.1:8080 هدایت می‌کند.

مثال: تنظیم Nginx برای Reverb

فایل تنظیم Nginx برای هدایت درخواست‌های WebSocket:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/ssl/cert.pem;
    ssl_certificate_key /etc/ssl/private.key;

    location /app {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}
  1. فایل بالا را در /etc/nginx/sites-available/reverb ذخیره کنید.
  2. آن را فعال کنید:
ln -s /etc/nginx/sites-available/reverb /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

مثال عملی: راه‌اندازی یک اپلیکیشن با SSL

  1. فایل config/reverb.php را مانند بالا تنظیم کنید.
  2. یک event ساده برای تست ایجاد کنید:
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class SecureMessage implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    public function __construct($message)
    {
        $this->message = $message;
    }

    public function broadcastOn()
    {
        return new Channel('secure-channel');
    }

    public function broadcastAs()
    {
        return 'secure.message';
    }
}
  1. یک route برای ارسال پیام تعریف کنید:
<?php

use App\Events\SecureMessage;
use Illuminate\Support\Facades\Route;

Route::get('/send-secure', function () {
    event(new SecureMessage('Secure message via Reverb!'));
    return 'Secure message sent!';
});
  1. فایل welcome.blade.php را برای دریافت پیام تنظیم کنید:
<!DOCTYPE html>
<html>
<head>
    <title>Secure Reverb Test</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
    <h1>Test Secure Reverb</h1>
    <button onclick="sendSecureMessage()">Send Secure Message</button>
    <p id="messages"></p>

    <script>
        const ws = new WebSocket('wss://localhost:443/app/your-app-key?protocol=7&client=js');

        ws.onopen = () => {
            ws.send(JSON.stringify({
                command: 'subscribe',
                identifier: JSON.stringify({ channel: 'secure-channel' })
            }));
        };

        ws.onmessage = (event) => {
            const data = JSON.parse(event.data);
            if (data.type === 'message') {
                $('#messages').append(`<p>${data.data.message}</p>`);
            }
        };

        function sendSecureMessage() {
            $.get('/send-secure');
        }
    </script>
</body>
</html>
  1. سرور Reverb را با SSL اجرا کنید:
php artisan reverb:start
  1. به https://localhost/send-secure بروید و پیام را در صفحه ببینید.

نکات و بهترین شیوه‌ها

  • امنیت Credentials: مقادیر REVERB_APP_KEY و REVERB_APP_SECRET را در یک سیستم مدیریت اسرار (مانند AWS Secrets Manager) ذخیره کنید.
  • Allowed Origins: همیشه دامنه‌های خاص را مشخص کنید تا از حملات Cross-Origin جلوگیری شود.
  • SSL در تولید: از Let’s Encrypt برای گواهی‌های رایگان یا سرورهای مدیریت‌شده مانند Laravel Forge استفاده کنید.
  • مانیتورینگ: لاگ‌های Reverb را با --debug بررسی کنید تا مشکلات اتصال را شناسایی کنید.

تمرین پیشنهادی

  • دو اپلیکیشن جداگانه در config/reverb.php تنظیم کنید و برای هر کدام یک event و route جداگانه ایجاد کنید.
  • یک reverse proxy با Apache به‌جای Nginx تنظیم کنید و اتصال WebSocket را تست کنید.

منابع

  • مستندات رسمی لاراول: laravel.com/docs/12.x/reverb
  • مستندات Nginx برای WebSocket: nginx.com/blog/websocket-nginx

در فصل بعدی، به مفاهیم broadcasting و ایجاد events پیشرفته‌تر خواهیم پرداخت.