تحقق من الرأس (header) Origin في طلبات WebSocket للتأكد من أن الطلبات تأتي من نطاقات موثوقة فقط.
const allowedOrigins = ["https://website.com"]; io.use((socket, next) => { const origin = socket.handshake.headers.origin; if (allowedOrigins.includes(origin)) { return next(); } return next(new Error("Unauthorized")); });
مع استخدام التحقق من التوكن لكونه أسلوب فعال لضمان أن الاتصالات تأتي من مستخدمين موثقين.
فعلى جانب العميل توليد وإرسال توكن عند إنشاء اتصال WebSocket.
socket = io("", { reconnection: true, closeOnBeforeunload: false, transports: trans, query: { token: "GENERATED_TOKEN" } });
وعلى جانب الخادم التحقق من التوكن عند استلام الطلب.
io.use((socket, next) => { const token = socket.handshake.query.token; if (isValidToken(token)) { return next(); } return next(new Error("Authentication error")); }); function isValidToken(token) { // تحقق من صلاحية التوكن return token === "EXPECTED_TOKEN"; }
أيضًأ تحديد معدل الاتصالات يساعد في تجنب الهجمات التي تعتمد على إرسال طلبات لا نهائية.
const rateLimit = require("express-rate-limit"); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100, message: "Too many requests, please try again later." }); app.use("/socket.io", limiter);
بالطبع عليك تعديل بعض البيانات فيما سبق مثل التوكين والموقع وخلافه.
وكما ذكرت لك من قبل، استخدام جدار حماية لتطبيقات الويب (WAF) يوفر طبقة إضافية من الحماية ضد الهجمات الشائعة.
مع تحديد وقت الانتظار للاتصالات غير النشطة لتقليل الحمل على الخادم.
io.set('heartbeat timeout', 5000); // وقت الانتظار
وإذا أردت قم باستخدام reverse proxy مثل NGINX أو Apache لتمرير طلبات العملاء إلى الخادم الفعلي ويعيد الاستجابة إلى العملاء، أي يضيف طبقة إضافية من الحماية.
إن لم يكن لديك NGINX مثبتًا، تستطيع تثبيته باستخدام الأوامر التالية على لينكس:
sudo apt update sudo apt install nginx
ثم إنشاء أو تعديل ملف تكوين NGINX لإعداد الوكيل العكسي، ويكون الملف في /etc/nginx/sites-available/ وباستطاعتك تسميته كما تشاء، مثلاً socketio_proxy.
server { listen 80; server_name your-website.com; location /socket.io/ { proxy_pass http://localhost:3000/socket.io/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location / { proxy_pass http://localhost:3000/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
ثم تفعيل ملف التكوين الجديد وإعادة تشغيل خدمة NGINX لتطبيق التغييرات.
sudo ln -s /etc/nginx/sites-available/socketio_proxy /etc/nginx/sites-enabled/ sudo nginx -t # لاختبار التكوين والتأكد من عدم وجود أخطاء sudo systemctl restart nginx
لاحظ proxy_pass http://localhost:3000/socke... بتوجيه طلبات Socket.IO إلى خادمك الفعلي الذي يعمل على المنفذ 3000، لذا عليك تعديل تلك الإعدادات.
و proxy_set_header يضمن تمرير الرؤوس الضرورية للحفاظ على الاتصال وترقية البروتوكول إلى WebSocket إذا لزم الأمر.
وتستطيع ضبطه لتصفية الطلبات غير المرغوب فيها أو الضارة قبل أن تصل إلى خادمك الفعلي، وذلك يشمل حظر عناوين IP معينة، أو تصفية الطلبات بناءًا على نمط معين.
http { # قائمة IPs محظورة deny 192.168.1.1; deny 203.0.113.0/24; # السماح لبقية العناوين allow all; }
الهجمات الموزعة لحجب الخدمة تستهدف إغراق الخادم بعدد كبير من الطلبات، مما يؤدي إلى تعطيله، لكن NGINX يساعد في الحد من تأثير تلك الهجمات بعدة طرق، منها Rate Limiting أو Connection Limiting عليك ضبطه وفقًا لذلك.
التعليقات