تحرص بوابات VPN عالية السعة على إتاحة منافذ استقبال عبر بروتوكول TCP إلى جانب أنفاق UDP الأساسية. في بيئات البنية التحتية العملية، يعمل TCP كمسار احتياطي يعتمد عليه عندما تفرض شبكات العمل قيودا على حزم UDP، بالإضافة إلى استخدامه في إدارة الاتصال ونقل البيانات المشفرة عبر TLS. وعندما تفتح الخوادم منافذ عامة مثل المنفذ 443، فإنها تصبح هدفا مباشرا لهجمات سيل الاتصالات من نوع TCP SYN flood.

ورغم قدرة بطاقات الشبكة الحديثة على توجيه ملايين الحزم في الثانية، فإن معمارية تتبع الاتصال التقليدية في لينكس تعجز أمام طوفان الاتصالات الوهمية. فإذا قام الجدار الناري بإنشاء سجل تتبع لكل حزمة واردة قبل التحقق من هوية العميل، ستمتلئ جداول الذاكرة وتنهار البوابة قبل استهلاك سعة النطاق الترددي. ويكمن الحل الجذري في إلغاء حفظ الحالة خلال مرحلة المصافحة الأولية بالاعتماد على ميزة nftables SYNPROXY في لينكس.

يتطلب فهم آلية عمل SYNPROXY استيعاب مسار معالجة الحزم داخل بنية Netfilter في نواة لينكس.

خطر استنزاف جدول تتبع الاتصال conntrack:
سيل حزم SYN ──> بطاقة الشبكة (NIC) ──> مرحلة Netfilter PREROUTING ──> حجز ذاكرة تتبع (struct nf_conn)
                                                                                  │
                                                                   امتلاء الجدول (nf_conntrack: table full)
                                                                                  │
                                                                       توقف الخدمة (إسقاط كافة الاتصالات)

─────────────────────────────────────────────────────────────────────────────────────────────────────────────

التصفية عديمة الحالة عبر nftables SYNPROXY:
سيل حزم SYN ──> مسار PREROUTING (notrack) ──> مرحلة INPUT (SYNPROXY) ──> رد SYN-ACK عديم الحالة (Syncookie)
                                                                                  │
                                                                 (بدون استهلاك ذاكرة / بدون حفظ حالة)
                                                                                  │
عميل صالح يرسل حزمة ACK ───────────────────────────────────────> التحقق من الرمز ──> تسجيل في conntrack ──> خادم VPN

اختناق conntrack: قصور كوكيز المقبس القياسية

يعتقد العديد من المهندسين أن تفعيل خيار net.ipv4.tcp_syncookies = 1 كاف للتصدي لهجمات SYN flood. وفي الواقع، يحمي هذا الخيار طابور استماع المقبس للتطبيق فقط (listen(backlog))، ولا يوفر حماية لمنظومة تتبع الاتصال Netfilter المسماة nf_conntrack.

في تدفق شبكة لينكس القياسي، يعترض Netfilter الحزم عند خطاف NF_INET_PRE_ROUTING، وهو يسبق بكثير طبقة النقل المحلية (NF_INET_LOCAL_IN). وبمجرد وصول حزمة تحمل راية SYN، يقوم nf_conntrack بحجز بنية بيانات struct nf_conn وإدراجها في جدول التجزئة العام بحالة SYN_RECV:

وصول الحزمة ──> nf_conntrack_in() ──> init_conntrack() ──> kmem_cache_alloc(nf_conntrack_cachep)

يستهلك كل إدخال ما بين 320 إلى 384 بايتا من ذاكرة النواة. ومع حد افتراضي قدره 262,144 سجلا في nf_conntrack_max، يكفي سيل من 300,000 حزمة في الثانية لاستنزاف الجدول بالكامل في أقل من 900 ميلي ثانية.

يترتب على امتلاء الجدول:

  1. تسجيل خطأ النواة net_ratelimit: nf_conntrack: table full, dropping packet.
  2. انقطاع الاتصالات القائمة وإسقاط محاولات الاتصال الجديدة الصالحة فوريا.
  3. استهلاك مفرط لطاقة المعالج بسبب محاولات معالجة الطوابير الممتلئة.

نظرا لأن كوكيز المقبس التقليدية تفحص في دالة tcp_v4_rcv() بعد فشل حجز الذاكرة في nf_conntrack، فإنها لا تعمل إطلاقا. ولحماية البوابات، يجب تقديم التحقق من المصافحة ليسبق خطوة تتبع الاتصال.

البنية الداخلية لمنظومة Netfilter SYNPROXY

تعمل وحدة synproxy البرمجية، والمدمجة في النواة ضمن المسار net/netfilter/nf_synproxy_core.c والمضبوطة عبر nftables، كوكيل عكسي لبروتوكول TCP بدون حالة في طبقة النواة. وتقسم عملية الاتصال إلى مرحلتين: مصافحة خارجية غير مسجلة مع العميل، تليها مصافحة داخلية مع تطبيق الخادم المحلي.

العميل الخارجي                           nftables SYNPROXY                        تطبيق VPN المحلي
      │                                         │                                       │
      │─── 1. حزمة TCP SYN [MSS, WScale] ──────>│ (بدون حفظ حالة، بدون حجز ذاكرة)       │
      │                                         │                                       │
      │<── 2. رد SYN-ACK عديم الحالة [Cookie] ──│ (تجزئة تشفيرية لبيانات الحزمة و ISN) │
      │                                         │                                       │
      │─── 3. حزمة TCP ACK [Cookie + 1] ───────>│                                       │
      │                                         │─── 4. إنشاء TCP SYN محلي ────────────>│
      │                                         │<── 5. استقبال SYN-ACK [رقم الخادم] ──│
      │                                         │─── 6. إرسال ACK محلي ────────────────>│
      │                                         │                                       │
      │═════════════════════════════════════════╪═══════════════════════════════════════│
      │              مرحلة تبادل البيانات وتعديل إزاحة الأرقام التسلسلية                │
      │─── 7. بيانات التطبيق المشفرة TLS ──────>│─── 8. تعديل SEQ/ACK (قيمة الإزاحة) ──>│
      │<── 10. تعديل SEQ/ACK (قيمة الإزاحة) ────│<── 9. بيانات الاستجابة ───────────────│

تتكون مراحل المعالجة من أربع خطوات رئيسية:

الخطوة 1: استبعاد الحزم من التتبع

تحدد حزم SYN الواردة إلى منفذ خدمة VPN بالوسم notrack في جدول التوجيه المسبق الخام لمنع حجز بنية struct nf_conn.

الخطوة 2: توليد كوكيز المصافحة بدون حالة

تصل الحزمة إلى سلسلة INPUT المربوطة بمحرك SYNPROXY. وبدلا من تمريرها للمقبس، تحسب النواة رقم التسلسل الأولي (ISN) بحجم 32 بت باستخدام تجزئة تشفيرية تعتمد على:

  • عناوين IP للمصدر والوجهة
  • أرقام منافذ المصدر والوجهة
  • رقم التسلسل الأولي للعميل
  • مفتاح سري خاص بالنواة يتجدد كل 60 ثانية
  • معلمات TCP المضغوطة (MSS، ومقياس حجم النافذة، وخيار SACK)

يرسل المحرك حزمة SYN-ACK مباشرة إلى العميل دون تخزين أية حالة أو مؤقتات. وتنتهي محاولات الأجهزة الوهمية عند هذه النقطة دون استنزاف خوادم البوابة.

الخطوة 3: التحقق من إشعار الاستلام وبدء التتبع

يرد العميل الصالح بحزمة ACK تحمل الرقم Cookie + 1. يعترض المحرك هذه الحزمة ويتحقق من صحة التجزئة التشفيرية.

بمجرد التأكد من سلامة الحزمة:

  • يتم إنشاء قيد struct nf_conn حقيقي في nf_conntrack.
  • تنتقل الجلسة مباشرة إلى حالة ESTABLISHED.
  • تستعاد خيارات TCP المتفق عليها بالكامل.

الخطوة 4: المصافحة المحلية وتعديل الإزاحة

نظرا لأن تطبيق خادم VPN يتوقع مصافحة قياسية، ينشئ المحرك حزمة SYN موجهة محليا نحو المقبس الداخلي.

وعندما يستجيب التطبيق بحزمة SYN-ACK تحمل رقم التسلسل الخاص به (ISN_server)، يحسب المحرك الفارق:

$$\Delta = ext{ISN}_{ ext{server}} - ext{Cookie}$$

وخلال كافة مراحل تدفق البيانات اللاحقة، يعدل المحرك ترويسات الحزم مباشرة في النواة:

  • للحزم الواردة: يضاف الفارق $\Delta$ إلى رقم التسلسل.
  • للحزم الصادرة: يطرح الفارق $\Delta$ من رقم إشعار الاستلام.

تتم هذه العملية بسرعة الخط المادي ودون أية تعديلات برمجية على التطبيقات.

التطبيق العملي: إعداد قواعد nftables SYNPROXY

تتطلب التصفية إعداد جدار الحماية nftables بأولويات مناسبة للقنوات.

ملف الضبط المخصص لحماية المنفذ 443:

#!/usr/sbin/nft -f

flush ruleset

table inet vpn_filter {
    synproxy synproxy_vpn {
        mss 1460
        wscale 7
        timestamp sack-perm
    }

    chain raw_prerouting {
        type filter hook prerouting priority raw; policy accept;
        tcp dport 443 tcp flags syn notrack
    }

    chain filter_input {
        type filter hook input priority filter; policy drop;

        iif "lo" accept
        ct state established,related accept
        ct state invalid drop

        tcp dport 443 synproxy config synproxy_vpn
        tcp dport 443 ct state new accept
    }

    chain filter_forward {
        type filter hook forward priority filter; policy drop;
    }

    chain filter_output {
        type filter hook output priority filter; policy accept;
    }
}

تحميل الإعدادات في نظام التشغيل:

sudo nft -f /etc/nftables.conf

التحقق من عمل القواعد:

sudo nft list table inet vpn_filter

تحسين معلمات النواة ومراقبة المؤشرات

تتطلب المنظومة ضبط متغيرات النواة في الملف /etc/sysctl.d/99-synproxy.conf:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps = 1
net.netfilter.nf_conntrack_tcp_loose = 0
net.netfilter.nf_conntrack_max = 2097152
net.netfilter.nf_conntrack_buckets = 524288
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10
net.netfilter.nf_conntrack_tcp_timeout_established = 3600

تطبيق التغييرات:

sudo sysctl --system

متابعة الإحصائيات المباشرة

يمكن قراءة العدادات عبر واجهة /proc:

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/net/stat/synproxy

دلالات العدادات:

  • entries: إجمالي الاتصالات المدارة حاليا بواسطة SYNPROXY.
  • syn_received: عدد حزم SYN التي تم التعامل معها بعدم الحالة.
  • cookie_invalid: حزم ACK المرفوضة لعدم صحة التوقيع.
  • cookie_valid: الاتصالات المؤكدة التي أدرجت في conntrack بنجاح.

الدور في معمارية بوابات RiceGuard

ترتكز الحماية الأمنية الشاملة على مناعة كافة بروتوكولات الشبكة. ومع أن بروتوكول RiceGuard يعمل أساسا عبر UDP بآلية تحقق تشفيرية مدمجة، فإن البوابات تحتفظ بواجهات TCP لضمان الاتصال في الشبكات المعقدة وحماية استعلامات DNS عبر HTTPS.

يتيح نشر nftables SYNPROXY عند الحافة صد هجمات الحرمان من الخدمة العنيفة دون استنزاف موارد الذاكرة، مما يضمن تدفقا سلسا للبيانات المشفرة لجميع المستخدمين.

تحميل VPNRice