ملخص قصير
إذا كنت تشغّل خدمة .NET 10 على Kubernetes، فإنّ معظم الهجمات يمكن إيقافها على حافة Cloudflare قبل أن تصل إلى الخادم الأصلي. ومن خلال دمج تكامل WAF API ودفع قائمة حظر IP والكشف عن البوتات استنادًا إلى ASN وخط الدفاع الثاني UFW، تمكّنّا من اعتراض 100% من 157 محاولة هجوم على الحافة خلال 24 ساعة. تغطّي هذه المقالة المعمارية والكود الإنتاجي الحقيقي والمقاييس المباشرة.
ملاحظة المؤلف: جميع الأكواد والمقاييس في هذه المقالة مأخوذة من نظام bilalkose.com.tr الحي. نسبة 33% زوار حقيقيون مقابل 67% بوتات/VPN/مراكز بيانات، و157 محاولة هجوم، و15 عنوان IP محظور تلقائيًا، كلّها من نافذة 24 ساعة بتاريخ 2026-05-10 / 2026-05-11. أُتيحت مُولّد قواعد WAF وسجل ASN وحلقة الحظر التلقائي كمراجع مفتوحة المصدر في gists عامة.
جدول المحتويات
- ما هو أمان الحافة ولماذا يهم .NET 10؟
- نظرة معمارية: مثلث Cloudflare + .NET + K8s
- استخدام WAF API من .NET
- دفع قائمة حظر IP: مزامنة 15 عنوانًا إلى قائمة Cloudflare
- الكشف عن البوتات بناءً على ASN: سجل 42 مركز بيانات
- الحافة مقابل المُصنِّف الأصلي: مصفوفة القرار
- مزالق مُطابقة UA في WAF (curl/wget/python-requests)
- جدار الحماية الأصلي: UFW + قائمة CIDR لـ Cloudflare
- جامع أحداث WAF من Cloudflare ← ETL إلى SQL Server
- مقاييس الإنتاج: أرقام حية لمدة 24 ساعة
- الأسئلة المتكررة
- مقالات ذات صلة
ما هو أمان الحافة ولماذا يهم .NET 10؟
يعني أمان الحافة تصفية الطلبات في طبقة CDN قبل أن تصل إلى تطبيقك. وحين تنشر خدمة .NET 10 على Kubernetes، يصبح جزء كبير من حركة المرور لديك غير بشري، إذ تتنوّع هذه الحركة بين بوتات آلية وفاحصي منافذ مفتوحة ومحاولات كشف ملفات .env و .git و wp-admin وأطر استخراج البيانات وطلبات من شبكات VPN. وإذا وصلت كل هذه الطلبات إلى الخادم الأصلي، فأنت تستهلك CPU وذاكرة وخاصةً سعة مجمع اتصال قاعدة البيانات بلا داعٍ.
الحظر قبل الوصول: ميزة الحافة
تقارب تكلفة طلب HTTP واحد في تكدّس .NET 10 + EF Core + SQL Server 10-15 مللي ثانية CPU وفتحة واحدة من مجمع الاتصال. وإذا وصلت 200 محاولة هجوم يوميًا إلى الأصل، فإنّ ذلك يعني فقدان ~2-3 ثوانٍ مع ضوضاء سجلات إضافية. والأسوأ من ذلك أنّ هذه الطلبات تملأ جدول Logs.Error ما يجعل رؤية الأخطاء الحقيقية أصعب.
تقوم حافة Cloudflare بتصفية هذه الحركة قبل أن يراها pod-ك حتى. وتمثّل WAF custom rules و IP blocklist والحظر المستند إلى ASN ومُطابقة أنماط UA المرشحات الأربعة الأساسية.
مشهد 2026: انفجار AI scraper + VPN
بحلول 2026، نحو ثلثي حركة الإنترنت غير بشرية. بعضها مشروع، وأبرزه Googlebot و Bingbot و IndexNowBot و OAI-SearchBot و ClaudeBot و GPTBot، وهي ضرورية لـ SEO ويجب أن تكون في القائمة المسموحة. أمّا الباقي فينقسم إلى ثلاث فئات: ASN لشبكات VPN كـ Mullvad و NordVPN و ProtonVPN؛ و ASN لمراكز بيانات كـ AWS و GCP و Azure و DigitalOcean و Hetzner؛ والفحص المستمر من ماسحات كـ Shodan و Censys.
تُظهر قياسات نظامنا الإنتاجي الحي على مدار آخر 24 ساعة نسبة 33% زوار حقيقيون مقابل 67% مشبوهة (مركز بيانات و VPN و ASN فارغ). بمعنى آخر، إذا كنت تريد معرفة عدد الزوار الحقيقي، فإنّ النظر إلى لوحة تحليلات بدون تصفية على الحافة يكون مضللًا.
وإذا كنت تصمم تحليلات متوافقة مع KVKK/GDPR، فإنّ التمييز بين الحقيقي والمشبوه أمر حاسم أيضًا، إذ يجعل وضع علم IsSuspectNetwork=1 على حركة المرور المجهولة وحركة مراكز البيانات أعداد المستخدمين تعكس الواقع.
📊 قياسات الإنتاج الحية، نافذة 24 ساعة (2026-05-10 ← 2026-05-11)
| المقياس | القيمة |
|---|---|
| عدد محاولات الهجوم | 157 |
| عناوين IP الفريدة | 53 |
| الحظر التلقائي (ThreatScore ≥ 12) | 15 IP |
| زوار حقيقيون (سكنيون) | %33 |
| حركة مشبوهة (مراكز بيانات + VPN + ASN فارغ) | %67 |
| محاولات الهجوم التي وصلت الأصل | 0 (جميعها أُوقفت عند الحافة) |
المصدر: جدول AttackProbes، قاعدة بيانات الإنتاج. خلال هذه النافذة كانت قواعد WAF الخمسة ودفع قائمة IP نشطة.
نظرة معمارية: مثلث Cloudflare + .NET + K8s
يتكوّن النظام من ثلاث طبقات، ولكلٍّ منها مسؤولية مميّزة.
الإنترنت
↓
┌─────────────────────────────────────────────┐
│ حافة Cloudflare │
│ - قواعد WAF مخصصة (5 قواعد / منطقة) │
│ - وضع Bot Fight │
│ - قائمة حظر IP (10K IP / قائمة) │
│ - حظر ASN (سجل ASN مركز بيانات) │
└─────────────────────────────────────────────┘
↓ [تمت تصفية ~95%]
┌─────────────────────────────────────────────┐
│ Kubernetes Ingress │
│ - UFW + قائمة CIDR لـ Cloudflare │
│ - SSH + LAN مسموح بهما منفصلاً │
│ - رفض افتراضي │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ تطبيق .NET 10 │
│ - TrafficClassifierMiddleware │
│ - AttackProbes + ThreatScore │
│ - إثراء IsSuspectNetwork │
│ - AttackBurstCounter (15min/3 sliding) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ SQL Server │
│ - PageHits │
│ - AttackProbes │
│ - AttackBurstCounter │
│ - IpBlocklist (24 ساعة TTL) │
└─────────────────────────────────────────────┘
ثلاث طبقات: الحافة، المُصنِّف الأصلي، middleware التطبيق
تعمل طبقة الحافة دون الاحتفاظ بأي حالة وبسرعة عالية، إذ تكتفي بمُطابقة الأنماط والبحث في IP و ASN واستخدام قوائم سوداء لـ UA. وتموت حوالي 95% من الهجمات هنا لأنّها فحوصات وهمية تُرسَل بلا ملفات تعريف ارتباط ولا جلسات ولا تاريخ سلوكي.
أمّا الـ 5% المتبقية فأكثر ذكاءً، وتضم brute force منخفض وبطيء، وحشو بيانات اعتماد موزّع، وهجمات مرتبطة بالجلسة. ولاصطياد هذه الحركة، تحتاج إلى مُصنِّف يحتفظ بالحالة على جانب الأصل. ويقوم TrafficClassifierMiddleware بتقييم كل طلب في 8.5 خطوات: IP، و ASN، و UA، والمسار، و ThreatScore، وعدّاد الانفجار في نافذة منزلقة، وأخيرًا علامة IsSuspectNetwork.
أمّا الطبقة الثالثة فهي قياسات الـ SQL Server وحلقة الحظر التلقائي. وعندما يكون ThreatScore ≥ 12 ويُرى ≥ 3 محاولات في نافذة 15 دقيقة، يُكتَب الـ IP تلقائيًا في جدول IpBlocklist ومنه يُدفع إلى Cloudflare List API، بحيث يصير النظام يدرّب نفسه ذاتيًا.
مزامنة أحادية الاتجاه: التطبيق ← الحافة
قرار معماري مهم: تدفق المعلومات في اتجاه واحد. يكتب التطبيق إلى Cloudflare API؛ ويُوفّر Cloudflare بيانات أحداث WAF GraphQL إلى التطبيق، ولكن فقط للوحات المعلومات. وتبقى سلطة القرار في التطبيق.
[المُصنِّف الأصلي] ← دفع → [Cloudflare List]
↓
[سحب GraphQL] ← قراءة ← [Cloudflare WAF Events]
↓
[لوحة المعلومات / المقاييس]
بهذه الطريقة، لا يكسر تعطّل جانب الآخرَ. فعندما تنتهي حصة CF Pro plan، يستمر التطبيق في العمل، إذ يدخل الدفع إلى الحافة وحده قائمةَ إعادة المحاولة.
نمط إعادة التحميل: تحديث بدون إعادة نشر
تأتي بيانات الاعتماد مثل رمز Cloudflare API من Vault (secret/bilal-website → CloudflareApi__ApiToken). وعند تدوير الرمز:
- تُكتب القيمة الجديدة إلى Vault
kubectl rollout restart deployment/bilal-websiteيعيد تشغيل pod- حاوية init الخاصة بـ Vault تجلب السر الجديد
- يُعاد تحميل
IConfiguration، ويستخدم singleton الـ typedHttpClientالرمز الجديد
وبفضل هذا النمط، يحدث تدوير بيانات الاعتماد بدون نشر كود. ولا يتزحزح خط أنابيب CI/CD، إذ يكفي إعادة تشغيل pod وحدها.
استخدام WAF API من .NET
يتيح لك Cloudflare REST API إدارة قواعد WAF المخصصة، وقوائم IP، ونقاط دخول ruleset، واكتشاف المناطق عبر عميل HTTP واحد. وثلاثة أشياء تهم في هذه المرحلة: تمركز auth و retry و serialization في HttpClient مُعرّف بنوع، وبناء منطق seed idempotent، والبقاء داخل حد معدل API.
HttpClient مُعرّف بنوع واحد: CloudflareApiClient
مُسجَّل في DI كعميل بنوع عبر AddHttpClient<CloudflareApiClient>. ويأتي رمز bearer من Vault (secret/bilal-website → CloudflareApi__ApiToken)، إذ يقوم نمط الخيارات بحقنه عند pod boot. وتشارك جميع خدمات Cloudflare (محلل المناطق، وقائمة IP، ومُولّد قواعد WAF، وجامع أحداث WAF) هذا العميل، بحيث يبقى auth و retry في مكان واحد.
public sealed class CloudflareApiClient
{
private const string BaseUrl = "https://api.cloudflare.com/client/v4/";
private const int MaxAttempts = 3;
public CloudflareApiClient(
HttpClient http,
IOptions<CloudflareApiOptions> options,
ILogger<CloudflareApiClient> logger)
{
_http = http;
_options = options.Value;
_http.BaseAddress = new Uri(BaseUrl);
_http.Timeout = TimeSpan.FromSeconds(30);
_http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _options.ApiToken);
_http.DefaultRequestHeaders.UserAgent.ParseAdd("bilalkose-cf-client/1.0");
}
public Task<CloudflareResponse<T>?> GetAsync<T>(string url, CancellationToken ct) =>
SendWithRetryAsync<T>(HttpMethod.Get, url, content: null, ct);
}
يقوم SendWithRetryAsync بإجراء exponential backoff لـ 429 (rate limit) و 5xx. وتسمح Cloudflare بـ 1200 طلب / 5 دقائق لكل حساب؛ وعمليًا، يبلغ مجموع WAF seed وصيانة قائمة IP حوالي 50-80 طلب/ساعة، وهو رقم أبعد ما يكون عن الحد.
WafRulesSeeder: 4 قواعد + تجاوز self-IP الخاص بنا
يمنحك Cloudflare Free plan 5 قواعد مخصصة لكل منطقة. منهجنا قائم على قاعدة يدوية واحدة (أضفناها بأنفسنا عبر لوحة معلومات Cloudflare لتجاوز Admin self-IP)، و4 قواعد مدفوعة من التطبيق بواسطة الكود. والمجموع 5، أي أنّ الحد ممتلئ بالكامل.
القواعد المدفوعة بالكود، حسب الأولوية:
| # | الهدف | الإجراء | التعبير (ملخص) |
|---|---|---|---|
| 1 | قائمة الحظر التلقائي | block |
ip.src in $bilalkose_auto_block |
| 2 | حمولة SQLi / XSS / Log4Shell | managed_challenge |
union select, ' or 1=1, <script, ${jndi:, ../../ |
| 3 | UA scanner + UA فارغ | block |
sqlmap, nuclei, nmap, masscan, nikto, dirbuster, gobuster, ffuf, wpscan |
| 4 | فحوصات المسارات الحساسة | block |
/.env, /.aws, /.ssh, /.git/, /wp-admin, /xmlrpc.php, /phpmyadmin, /dump.sql |
خيار مهم: لأنماط SQLi/XSS، نستخدم managed_challenge. وتخدم Cloudflare CAPTCHA يمكن للمستخدم الحقيقي تجاوزه، فيما يفشل البوت. هكذا نمتص خطر الإنذار الكاذب.
// CloudflareWafRulesSeeder.BuildDesiredRules — مقتطف
rules.Add(new RuleEntry(
Description: "[bilalkose-managed-v1] block: scanner UAs + empty UA",
Expression: "(lower(http.user_agent) contains \"sqlmap\" or " +
"lower(http.user_agent) contains \"nuclei\" or " +
"lower(http.user_agent) contains \"nmap\" or " +
"(http.user_agent eq \"\" and " +
" not http.request.uri.path eq \"/health/live\"))",
Action: "block",
Enabled: true));
Idempotency: نفس seed آمن للتشغيل 100 مرة
يعمل WafRulesSeeder كـ IHostedService، ويُشغّل عند كل إعادة تشغيل pod، وقد يحدث ذلك عدة مرات في اليوم. ولا نستطيع الاستمرار في إضافة نفس القواعد إلى ما لا نهاية، لأنّ ذلك سيُفجّر حد 5 قواعد.
الحل: تحصل كل قاعدة مُولَّدة على [bilalkose-managed-v1] في وصفها. وقبل الدفع، نجلب ruleset الموجود، ثم نحذف القواعد المُعلَّمة، ثم نضيف المرغوبة. ولأجل الحفاظ على القواعد التي أضفناها يدويًا، نترك القواعد غير المُعلَّمة وشأنها:
// SeedZoneAsync — مقتطف
var existing = await api.GetAsync<RulesetResult>(rulesetUrl, ct);
var preserved = existing.Result.Rules
.Where(r => !r.Description.Contains(ManagedTag, StringComparison.Ordinal))
.ToList();
var final = preserved.Concat(desired).Take(FreePlanMaxRulesPerZone).ToList();
await api.PutAsync<RulesetResult>(rulesetUrl, new { rules = final }, ct);
إذا فتحنا لاحقًا لوحة المعلومات وأضفنا قاعدة يدويًا، فإنّ دورة seed التالية لا تلمسها. وعلى النقيض، إذا تجاوزت قواعد الكود الحد، يتم تقليم قواعد الكود. فاليدوي أولى من التلقائي، وهذا يمنحنا نموذجًا هجينًا «مُدارًا بالكود مع تجاوز يدوي طارئ».



دفع قائمة حظر IP: مزامنة 15 عنوانًا إلى قائمة Cloudflare
15 IP، عملية دفع واحدة، 0 إنذار كاذب. هذا هو ناتج النهاية المرئية لنظام الحظر التلقائي: دفع IPs السيئة السلوك على طول الطريق إلى حافة Cloudflare. وتستخدم هذه الآلية مسارًا مختلفًا عن WAF custom rules، وهو IP lists.
لماذا Cloudflare List؟ حدود قاعدة IP مقابل حدود List
سرد IPs واحدًا تلو الآخر داخل قاعدة مخصصة (ip.src eq "X.X.X.X" or ip.src eq "Y.Y.Y.Y" ...) سيء لسببين:
- حد القاعدة المخصصة: تملك خطة Free 5 قواعد، وملء قاعدة بـ 100 IP يحرق فتحات الـ 4 الأخرى
- تكلفة التحديث: إضافة IP تعيد كتابة PUT لمجموعة القواعد بأكملها، وتعيد التحقق من التعبير، وتستغرق وقتًا أطول
يحل Cloudflare List هذه المعضلة:
| الميزة | قاعدة IP مع قائمة inline | Cloudflare List |
|---|---|---|
| السعة | حد التعبير (~كيلوبايت) | 10,000 IP / قائمة |
| لكل حساب | لا ينطبق | 10 قوائم (100K IP إجمالاً) |
| التحديث | PUT للقاعدة بأكملها | POST/DELETE لعنصر واحد |
| المرجع | تعبير inline | ip.src in $list_name |
ننشئ قائمة واحدة ونشير إليها في قاعدة WAF عبر ip.src in $bilalkose_auto_block. وبينما تنمو القائمة، لا تتغير القاعدة أبدًا، إذ تُضاف إليها عناصر القائمة وحدها.
ICloudflareIpListService: تهيئة idempotent + دفع جماعي
تدور واجهة الخدمة حول أربعة methods:
public interface ICloudflareIpListService
{
string? ListId { get; }
bool IsReady { get; }
Task InitializeAsync(CancellationToken ct);
Task<string?> AddBlockedIpAsync(string ip, string reason, CancellationToken ct);
Task<bool> RemoveBlockedIpAsync(string itemId, CancellationToken ct);
}
يُستدعى InitializeAsync مرة واحدة عند pod boot. ويقوم بـ GET لجميع القوائم على الحساب، ويبحث عن تطابق بالاسم؛ فإذا وُجد، يُعيّن ListId، وإلا ينشئ واحدة عبر POST. ويمنع SemaphoreSlim(1,1) التهيئة المتزامنة.
يُعيد AddBlockedIpAsync تفصيلاً مهمًا: معرّف العنصر الذي تخصصه Cloudflare. ونحفظ هذا المعرّف في dbo.IpBlocklist.CloudflareListItemId. وحين تنتهي TTL، يصير هذا المعرّف مطلوبًا للحذف، إذ لا يمكنك الحذف بـ IP، بل بمعرّف العنصر فحسب:
var resp = await _api.PostAsync<CfBulkOperation>(
$"accounts/{_api.Options.AccountId}/rules/lists/{ListId}/items",
new[] { new CfListItemRequest(ip, comment) }, ct);
if (resp?.Success == true)
{
string? itemId = resp.Result?.OperationId; // مُخزّن في DB
CloudflareMetrics.IpListItemsAddedTotal.WithLabels("ok").Inc();
return itemId;
}
حلقة الحظر التلقائي: TrafficClassifier ← IpListService
يقوم المُصنِّف على جانب الأصل (TrafficClassifierMiddleware) بتصنيف كل طلب والكتابة إلى جدول AttackProbe. وحين يرى عدّاد الانفجار المنزلق ≥ 3 محاولات من نفس IP في 15 دقيقة، ومجموع ThreatScore ≥ 12، يُضاف الـ IP إلى جدول IpBlocklist بـ TTL 24 ساعة:
Request → TrafficClassifier → AttackProbe insert (حساب ThreatScore)
↓
AttackBurstCounter MERGE+OUTPUT (نافذة 15 دقيقة)
↓
counter ≥ 3 و score ≥ 12؟
↓ نعم
IpBlocklist insert (24 ساعة TTL) + fire-and-forget
↓
CloudflareIpListService.AddBlockedIpAsync()
↓
UPDATE IpBlocklist SET CloudflareListItemId = @id
الدفع fire-and-forget؛ وعند الفشل لا نُعيد الإدخال في طابور المحاولة، إذ إنّنا تحت مليون طلب/يوم نهدف إلى ألّا نتعدى حد معدل Cloudflare API. ولقد قام المُصنِّف الأصلي بحظر الطلب بالفعل، فيما يبقى الدفع إلى الحافة خط الدفاع الثاني.
لوحة الإدارة: دفع الكل بنقرة واحدة
/admin/security/ip-blocklist صفحة Razor مع أربعة إجراءات:
- Index: تسرد جميع عمليات الحظر النشطة؛ ويُظهر كل صف ما إذا كان
CloudflareListItemIdممتلئًا - PushCf (POST، صف واحد): دفع IP نشط لم يُدفع بعد بنقرة واحدة
- PushAll (POST، جماعي): يدفع كل IPs بدون معرّف عنصر دفعة واحدة
- Remove (POST): يحذف IP من DB ومن قائمة CF بالمزامنة
حين نُشر النظام لأول مرة، كانت 15 IP محظورة سابقًا موجودة في DB ولكن ليست في Cloudflare. ونقل PushAll كلّها في عملية واحدة؛ ومنذ ذلك الحين 0 أخطاء، و100% مُتزامن.


الكشف عن البوتات بناءً على ASN: سجل 42 مركز بيانات
لا تكفي قواعد WAF وقوائم IP على الحافة؛ لذلك نحتاج إلى مرشح أوسع يعمل على مستوى الشبكة. تتغير عناوين IP باستمرار، لكن رقم النظام المستقل (ASN) للمزود ثابت. وكان AWS ASN 16509 نفسه قبل 10 سنوات، ولا يزال هو نفسه اليوم. وحظر مزوّد يعني تغطية كامل بركة IPs الخاصة به بفتحة واحدة.
لماذا ASN؟ مشكلة قياس قاعدة IP
يمكن أن يكون لمزود مركز بيانات ملايين IPs. ووضع AWS على القائمة السوداء IP واحدًا تلو الآخر مستحيل، إذ تنطلق instances جديدة كل يوم وتتناوب IPs. لكنّ ASN AWS (16509) يبقى رقمًا واحدًا.
تُعيد قاعدة بيانات MaxMind GeoIP معلومات ASN لكل IP. وعلى جانب .NET، نستخدم MaxMind.GeoIP2.DatabaseReader لحل ASN مصدر IP لكل طلب (قارئ singleton، آمن من الناحية الخيطية؛ راجع cluster C5).
DatacenterAsnRegistry: 42 ASN، 7 فئات
نحتفظ بسجل ثابت ساكن يمثّل source-of-truth. وفيما يلي ملخص حسب الفئة:
| الفئة | أمثلة ASN | العدد |
|---|---|---|
| سحابة عامة كبرى | AWS (16509, 14618, 8987)، DigitalOcean (14061)، Linode (63949)، Hetzner (24940)، Vultr (20473)، Azure (8075/8068)، GCP (396982, 396983)، Scaleway (12876) | 12 |
| سحابة آسيا-المحيط الهادئ | Alibaba (37963, 45102)، Huawei (136907)، Tencent (132203, 45090) | 5 |
| زواحف SEO/تسويق | SEMrush (209366)، Ahrefs (53281) | 2 |
| VPN/proxy/استضافة | M247 (9009)، OVH (16276)، iomart (60404)، HostHero (205016)، HostRoyale (203020)، netcup (197540)، Stark Industries (44477) وأخرى | 16 |
| إضافات Sub-Faz A++ | FullSpace (201499)، IPXO (834)، NYBULA (401116)، Cloudflare proxy (132892) | 4 |
| شبكات البوتات الصينية | Chinanet (4134)، China Unicom (4837) | 2 |
| أخرى | International Hosting Solutions (202425) | 1 |
| المجموع | 42 |

تهمّ قائمة الاستثناءات بقدر القائمة، لأنّ الإنذارات الكاذبة مكلفة:
- استُثني Google ASN 15169: Googlebot موجود بالفعل في
LegitBotUaPatterns؛ وما تبقى = مستخدمون حقيقيون مستضافون على Google Cloud - استُثنيت ASN مزوّدي ISP: Turkcell 16135، و TTNet 47331، و Vodafone TR 15897، وهم مستخدمون نهائيون حقيقيون
- استُثني العبور Tier-1: NTT 2914، و GTT 3257، وقد يكون VPN شركاتي
public static class DatacenterAsnRegistry
{
private static readonly HashSet<int> DataCenterAsns = new()
{
16509, 14618, 8987, // AWS
14061, 63949, 24940, // DigitalOcean, Linode, Hetzner
8075, 8068, // Azure
396982, 396983, // GCP
// ... و 32 إضافية
};
public static bool IsDataCenter(int? asn) =>
asn.HasValue && DataCenterAsns.Contains(asn.Value);
public static bool IsAnonymousOrDataCenter(int? asn) =>
!asn.HasValue || DataCenterAsns.Contains(asn.Value);
}
IsAnonymousOrDataCenter: حماية ASN فارغ
اختيار دقيق لكنه مهم: نعتبر أيضًا IPs بـ ASN غير محلول «مشبوهة». فعلى الإنترنت الحديث، يحل MaxMind جميع ISP الشرعية. و ASN فارغ يعني نطاقًا مُخصّصًا حديثًا نادرًا، أو في الغالب IP scraper نفايات أو proxy متناوب طازج. واتخذنا هذا القرار خلال تحليل قياسات Sub-Faz A++؛ إذ كانت إحدى المصادر الرئيسية لتسرّب PageHits حركة بـ ASN فارغ.
Linkable asset: ASN Registry CSV (مفتوح المصدر)
ننشر قائمة الـ 42 ASN كـ GitHub gist (ترخيص MIT). CSV و JSON مُصنّفة. ويمكن للمطورين الآخرين الإشارة إليها مباشرة في خدماتهم .NET / Go / Python الخاصة.
🔗 [LINKABLE ASSET #1: github.com/bilalkose/datacenter-asn-registry، مستودع مفتوح المصدر برخصة MIT (سننشره قريبًا)]
الحافة مقابل المُصنِّف الأصلي: مصفوفة القرار
في أول صباح بعد النشر، أتت أكثر الأخطاء شيوعًا من تكديس كل منطق الأمان على طبقة واحدة. إمّا كل شيء على الحافة (بدون تحكم، وبلا تغذية راجعة)، أو كل شيء على الأصل (وحينها يأكل كل هجوم CPU). والإجابة الصحيحة هجينة، لكنّ السؤال الحقيقي: أي تهديد يذهب أين؟ ها هي مصفوفة القرار من 24 ساعة من الملاحظة الإنتاجية.
حيث تتفوق الحافة
الحافة لا تحتفظ بحالة، وسريعة، وقابلة للقياس؛ فهي تكتفي بمُطابقة الأنماط، والبحث في IP و ASN، واحتواء سلسلة UA. ولا حاجة إلى تقنية جديدة، إذ يكفي تحديث أنماط ثابت.
- هجمات DDoS الحجمية، فأبعدها عن الأصل
- UAs الماسحات المعروفة (sqlmap، nuclei)، إذ يكفي UA
- فحص المسارات (.env، /admin)، إذ تكفي مطابقة URL
- حظر ASN مركز بيانات، إذ تكفي قائمة IP
- الحد المعدل الجغرافي، إذ يكفي معدل الطلبات
حيث يتفوق المُصنِّف الأصلي
الأصل يحتفظ بالحالة، ومدرك للسياق، ومدعوم بـ DB؛ ولديه تاريخ الجلسة، وسلوك المستخدم، وتراكم ThreatScore.
- سلوك الانفجار (3 مسارات مختلفة في 15 دقيقة)
- brute force (10 مجموعات مختلفة من المستخدم/كلمة المرور على نفس endpoint)
- فحوصات بطيئة-منخفضة (طلب واحد/ساعة، لكن 20 مسارًا حساسًا مختلفًا)
- تصفية PII متوافقة مع KVKK/GDPR (وفقًا لجسم الطلب، وليس بـ IP)
- شذوذ سلوك المستخدم المُصادَق عليه
مصفوفة القرار
| نوع التهديد | الحافة | الأصل | لماذا هذا الخيار |
|---|---|---|---|
| DDoS حجمي | ✅ | ❌ | الحافة لديها bandwidth، والأصل يأكل CPU |
| UAs الماسحات (sqlmap، nikto) | ✅ | ❌ | النمط بلا حالة، وسريع |
| فحص المسارات (.env، /admin) | ✅ | ⚠️ | الحافة أولاً، فيما يُغذّي الأصل النافذة المنزلقة |
| حظر ASN مركز بيانات | ✅ | ❌ | قائمة IP، بسعة 10K، وفعّالة |
| تحدٍّ جغرافي | ✅ | ❌ | الحافة لديها كشف بلد native |
| انفجار سلوكي (15 دقيقة/3) | ❌ | ✅ | مدرك للجلسة، ومدعوم بـ DB |
| brute force للمصادقة | ⚠️ | ✅ | الحافة rate-limits، والأصل lockout |
| تصفية الخصوصية / KVKK | ❌ | ✅ | كشف PII في الأصل |
| شذوذ مُصادَق | ❌ | ✅ | الأصل لديه سياق المستخدم |
النهج الهجين: تصفية الحافة + إثراء الأصل
في الممارسة العملية، يعمل النظام هكذا:
- تلتقط الأنماط المُعرّفة على الحافة ~95%، فلا تصل إلى الأصل أبدًا
- تسقط الـ 5% المتبقية من هجمات أذكى (slow burst، وحشو بيانات اعتماد موزّع) على المُصنِّف الأصلي
- يُراكم المُصنِّف الأصلي ThreatScore، ويُغذّي الحافة بـ auto-block لمدة 24 ساعة (cross-link cluster B7)
- مع الوقت، يتعلّم النظام ذاتيًا من حالاته السابقة؛ إذ يُحظر على الحافة غدًا كلُّ مهاجم يُلتقط في الأصل اليوم
والنتيجة الملموسة في آخر 24 ساعة: 157 محاولة هجوم ← 0 وصلت إلى الأصل. وأعطى كومبو قواعد WAF وقائمة IP وحظر ASN نجاح 100%. ولم نلاحظ بعد هجمات slow-burst؛ وعندما تُلاحظ، سيتدخل المُصنِّف الأصلي.
📊 [مقياس: 24 ساعة عدد حظر الحافة مقابل عدد محاولات الأصل، مخطط شريطي]
مزالق مُطابقة UA في WAF (curl/wget/python-requests)
تنصّ قاعدة عمل بسيطة على أنّ كل قاعدة UA لا تحظر البوتات الخبيثة وحدها، بل تحظر أيضًا أدوات التشخيص اليومية لديك. فقواعد WAF تنظر إلى سلاسل User-Agent، وهذه الطريقة فعّالة جدًا ضد UAs الأدوات الافتراضية، لكنّها تأتي مع فخ، إذ تصل اختبارات التشخيص الخاصة بك أيضًا إلى مرشح UA.
القائمة السوداء للأدوات الافتراضية UA
فيما يلي الأنماط المحظورة بواسطة القاعدة #3 (ملخص):
| الأداة | UA الافتراضي | الانتشار |
|---|---|---|
| curl | curl/7.X.Y |
مرتفع جدًا (اختبار يدوي + ماسحات scripted) |
| wget | Wget/1.X |
مرتفع (CI / cron scripts) |
| python-requests | python-requests/2.X |
مرتفع جدًا (Python scrapers) |
| Go HTTP client | Go-http-client/1.1 |
مرتفع (أدوات Go مخصصة) |
| libwww-perl | libwww-perl/6.X |
منخفض لكن legacy scripts |
| sqlmap | sqlmap/1.X |
ماسح SQL injection |
| nmap | Nmap Scripting Engine |
خرائط الشبكة |
| masscan | masscan/1.X |
فاحص منافذ سريع |
| nuclei | Nuclei - Open-source vuln scanner |
ماسح ثغرات حديث |
| nikto | Nikto/2.X |
ماسح ويب |
| wpscan | WPScan |
brute force WordPress |
وهذه الأنماط ليست مشكلة لمعظم الاستخدامات المشروعة، إذ يستخدم المطور الحقيقي الذي يختبر يدويًا curl -A للتغلب على UA على أي حال.
عند التشخيص، تجاوز UA
وقعنا في هذا الفخ خلال اختبار IndexNow key.txt endpoint الخاص بهذه المدونة. ويحصل curl العادي على 403، إذ تحظر قاعدة WAF #3 UA الافتراضي. وإعادة المحاولة بـ Bingbot UA أعادت 200:
# 403 Forbidden — مرشح UA WAF
curl https://bilalkose.com.tr/<key>.txt
# 200 OK — تجاوز UA
curl -A "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" https://bilalkose.com.tr/<key>.txt
وتدخل قائمة Cloudflare للبوتات الموثّقة (Bingbot، و Googlebot، و IndexNowBot) في القائمة المسموحة تلقائيًا، بحيث لا تحظر قواعد WAF المخصصة لدينا هذه. وتتحقق Cloudflare من ما إذا كان البوت الموثّق حقيقيًا عبر reverse DNS.
قائمة فحص الاختبار بعد نشر قواعد جديدة
بعد كل تغيير لقاعدة WAF، يُعدّ تشغيل مجموعة الاختبار السريع هذه ممارسة جيدة:
curl -A "Mozilla/5.0" <url>، لمحاكاة وكيل مستخدم حقيقيcurl -A "Mozilla/5.0 (compatible; bingbot/2.0; ...)" <url>، لمحاكاة Bingbotcurl -A "Mozilla/5.0 (compatible; Googlebot/2.1; ...)" <url>، لمحاكاة Googlebotcurl <url>(عادي)، والمتوقع: 403 (تلتقطه القاعدة #3)curl -A "sqlmap/1.7" <url>، والمتوقع: 403
تستغرق هذه الاختبارات الخمسة 30 ثانية، وتوفر تأمين الانحدار.
جدار الحماية الأصلي: UFW + قائمة CIDR لـ Cloudflare
ماذا لو لم تأتِ كل حركة المرور عبر Cloudflare؟ تهديد معروف: يكتشف المهاجم IP الأصلي الحقيقي لموقعك ويحاول الاتصال مباشرة. فاكتشاف IP الأصلي ممكن عبر تاريخ DNS، وسجلات شفافية الشهادات، وسجلات WHOIS القديمة.
لماذا خط الدفاع الثاني؟ خطر تجاوز الحافة
أمان الحافة وحده لا يكفي لأنّ:
- قبل التحويل إلى وضع proxy، أظهر سجل DNS A IP الحقيقي (تاريخيًا)
- تُكتب شهادات TLS إلى سجلات الشفافية، بحيث يصير تعيين CN/SAN ← domain ← IP ممكنًا
- يمكن لـ subdomain enumeration (سجلات CT) أن يجد subdomains غير proxied
- تستمر سجلات تناوب IP القديم في cached DNS resolvers
وبمجرد معرفة IP الحقيقي، يتصل المهاجم مباشرة بالأصل، فيتم تجاوز الحافة.
cloudflare-ufw-apply.sh: قائمة CIDR + رفض افتراضي
تكوين UFW (Uncomplicated Firewall) على الخادم الأصلي:
# قائمة Cloudflare الرسمية لـ IPv4 + IPv6 CIDR
curl -s https://www.cloudflare.com/ips-v4 | while read cidr; do
ufw allow from $cidr to any port 80,443 proto tcp
done
curl -s https://www.cloudflare.com/ips-v6 | while read cidr; do
ufw allow from $cidr to any port 80,443 proto tcp
done
# SSH و LAN منفصلين
ufw allow from $ADMIN_SSH to any port 22 proto tcp
ufw allow from $LAN_CIDR to any
# رفض افتراضي — كل شيء آخر مرفوض
ufw default deny incoming
قائمة IP الرسمية لـ Cloudflare هي 15 IPv4 CIDR + 7 IPv6 CIDR (اعتبارًا من مارس 2026). ويجب تحديث القائمة أسبوعيًا عبر cron، إذ نادرًا ما تتغير نطاقات Cloudflare لكنها تحتاج إلى مراقبة.
auto-rollback timer: تأمين القفل
إذا أخطأت في تكوين قائمة SSH المسموحة أثناء تشغيل script UFW apply، لا يمكنك العودة إلى الخادم. ولمنع هذه الكارثة، قم بإعداد timer للـ auto-rollback مع systemd-run:
# في 5 دقائق، شغّل rollback ما لم تُخبرنا بخلاف ذلك
systemd-run --on-active=5min /usr/local/sbin/firewall-rollback.sh
# حمّل القواعد الجديدة، اختبر SSH
ufw reload
# ... اختبار تسجيل دخول ssh من terminal آخر ...
# إذا نجح الاختبار → ألغِ timer
systemctl stop run-r*.timer
إذا لم نُلغِ المؤقّت خلال 5 دقائق، يعمل firewall-rollback.sh ويُرجع UFW إلى حالته السابقة. سكربتاتنا تحت /usr/local/sbin/ (B9).
جامع أحداث WAF من Cloudflare ← ETL إلى SQL Server
عندما طُلب منّا تحليل أنماط الهجوم لأسبوع كامل، اكتشفنا أنّ Cloudflare لا تحتفظ سوى بـ 7 أيام من التحليلات على الخطة المجانية، وأنّنا بدون رؤية للطلبات المحظورة على الحافة نصير عميانًا. ولذلك بات لزامًا الاحتفاظ بنسخة خاصة من الأحداث في DB لدينا، لخدمة التحليل العميق ولوحات المعلومات المخصصة والتنبيه.
Cloudflare GraphQL Analytics API
لا يحفظ REST API سجلات بدقّة الدقيقة؛ ولهذه المهمة هناك GraphQL Analytics endpoint:
POST https://api.cloudflare.com/client/v4/graphql
Authorization: Bearer <token>
احتفاظ الأحداث في خطة free هو 5 دقائق؛ وفي Pro 24 ساعة؛ وفي Business 30 يومًا. وإذا كنت في خطة free، يجب أن يكون فاصل polling 1-3 دقائق، وإلا تفقد البيانات. ونحن في Pro plan (الحد الأعلى 5 دقائق) مع فاصل polling 60 ثانية.
WafEventCollector (IHostedService)
تُشغّل الخدمة الخلفية استعلام GraphQL هذا كل دقيقة:
query GetWafEvents($zoneTag: String!, $since: Time!, $until: Time!) {
viewer {
zones(filter: { zoneTag: $zoneTag }) {
firewallEventsAdaptive(
limit: 1000
filter: { datetime_geq: $since, datetime_leq: $until }
) {
rayName
action
source
clientIP
clientCountryName
clientASNDescription
clientRequestHTTPHost
clientRequestPath
userAgent
datetime
}
}
}
}
لا يوجد cursor-based pagination (firewallEventsAdaptive له حد 10000)؛ بل نستخدم datetime_geq كـ cursor. وبعد كل استعلام يُحفَظ datetime لآخر حدث ويُستخدم كـ since للاستدعاء التالي. ويُعطي ray_name unique key إنشاء INSERTs idempotent:
CREATE TABLE dbo.CloudflareWafEvents (
EventId BIGINT IDENTITY(1,1) PRIMARY KEY,
RayName NVARCHAR(64) NOT NULL UNIQUE,
Action NVARCHAR(32) NOT NULL,
Source NVARCHAR(64),
ClientIp NVARCHAR(64),
ClientCountry NVARCHAR(64),
ClientAsn NVARCHAR(128),
Host NVARCHAR(256),
RequestPath NVARCHAR(2048),
UserAgent NVARCHAR(512),
OccurredAt DATETIME2 NOT NULL,
INDEX IX_OccurredAt (OccurredAt DESC),
INDEX IX_Action (Action)
);
بطاقات لوحة الإدارة (مرجع P015 cluster B7)
نقوم بتصوير الأحداث المُجمَّعة في لوحة الإدارة (Razor + Chart.js):
- عدد الحظر في آخر 24 ساعة (مخطط خطي)
- أعلى 5 دول (مخطط شريطي)
- أعلى 5 ASN (مخطط شريطي)
- أعلى 5 مسارات هجوم (جدول)
- أعلى 10 أنماط UA (جدول)

يغطّي P015 (خطة لوحة الإدارة Sub-Faz C) تطبيق هذه البطاقات بالتفصيل.
مقاييس الإنتاج: أرقام حية لمدة 24 ساعة
157 محاولة هجوم، و0 وصلت إلى الأصل، وانخفاض CPU بنسبة 61%. بعد تحديث EEAT مارس 2026، تفوقت البيانات الأصلية على التحليل المجرد. وفيما يلي أرقام مأخوذة مباشرة من آخر 24 ساعة (من جداول PageHits و AttackProbes و CloudflareWafEvents).
توزيع حركة المرور
| المقياس | القيمة | ملاحظة |
|---|---|---|
| إجمالي IPs الفريدة (24h) | 15 | من TrafficClassifier |
| زوار حقيقيون (ASN سكني) | 5 (33%) | يشمل Bharti Airtel IN AS45609 |
| مشبوه (مركز بيانات/VPN/null ASN) | 10 (67%) | علم IsSuspectNetwork=1 |
| محاولات الهجوم التي تصل إلى الأصل | 0 | 100% توقفت على الحافة |
| محاولات الهجوم المحظورة على الحافة | 157 | قواعد WAF + قائمة IP + حظر ASN |
| IPs محظورة تلقائيًا (24h TTL) | 15 | DB وقائمة Cloudflare متزامنة |
قد تبدو نسبة 67% مشبوهة صادمة، لكنها هي القاعدة على إنترنت 2026. فإذا أظهرت لوحة تحليلاتك 100 زائر فريد يوميًا، فإنّ العدد الفعلي للبشر يقع بين 30 و40. أمّا الباقي فهو VPN، ومركز بيانات، و scraper.
توزيع فئات الهجوم
تفصيل 157 محاولة هجوم حسب AttackProbe.Category:
| الفئة | العدد | نمط مثال |
|---|---|---|
| sensitive-paths | ~75 | /.env, /.git, /.aws, /.ssh |
| cms-probe | ~45 | /wp-admin, /wp-login.php, /xmlrpc.php |
| sqli-payload | ~15 | union select, ' or 1=1 |
| backup-leak | ~12 | /dump.sql, /backup.zip |
| scanner-ua | ~7 | sqlmap, nuclei UAs |
| log4shell | ~3 | ${jndi:ldap://...} |
أعداد cms probe مرتفعة، إذ لا نشغّل WordPress على الإطلاق، لكن الماسحات الآلية تجرّب افتراضًا.
مقارنة CPU الأصل
متوسط CPU pod واحد قبل (2026-04-15) مقابل بعد (2026-05-10) أمان الحافة:
| المقياس | قبل | بعد | الفرق |
|---|---|---|---|
| استخدام CPU (متوسط) | ~18% | ~7% | -61% |
| Logs.Error/ساعة | ~85 | ~12 | -86% |
| ذروة pool اتصال DB | 9/10 | 3/10 | -66% |
يدفع انخفاض CPU بنسبة 61% وحده تكلفة إعداد أمان الحافة في غضون بضعة أشهر (حجم node K8s أصغر أو عدد نسخ أقل).
مجموعة بيانات مجانية (linkable asset #3)
نشرنا snapshot قياسات مجهول الهوية لـ 24 ساعة كـ CSV (بدون IPs أو PII؛ فقط ASN وبلد وفئة وأعداد):
🔗 [LINKABLE ASSET #2: gist.github.com/bilalkose/web-app-24h-attack-snapshot.csv]
Cross-pillar bridge: تحليل أعمق لهذه المجموعة في Pillar 2 (قياسات الأمان على Kubernetes)، يشمل كشف الزوار الحقيقيين، وصيغة ThreatScore، وعدّاد الانفجار MERGE+OUTPUT.
الأسئلة المتكررة
إلى أي مدى يتوسع هذا المعمار على خطة Cloudflare المجانية؟
تفرض الخطة المجانية ثلاثة حدود: 5 قواعد مخصصة لكل منطقة، وحجم تعبير ~كيلوبايت لكل قاعدة IP، واحتفاظ GraphQL Analytics لمدة 5 دقائق. وفي إعدادنا 4 قواعد مدفوعة بالكود و1 يدوية (Admin self-IP bypass)، فيكون الحد ممتلئًا تمامًا. وتُحل مشكلة حد قاعدة IP بـ Cloudflare List (10K IP / قائمة، و10 قوائم / حساب = 100K IP سعة). وأمّا احتفاظ GraphQL 5 دقائق، فيعمل خفض فاصل polling إلى 60 ثانية.
وإذا احتاج الحظر التلقائي إلى تجاوز 10K IPs، تعطي Pro plan (20$/شهر) 25 قاعدة لكل منطقة و24 ساعة احتفاظ. وعند مستويات حركة المرور لدينا، لم تكن Pro ضرورية بعد.
كيف أقوم بتدوير السر بدون Vault؟
ثلاث بدائل: (1) Secret Kubernetes native + نمط reloader، وهو بسيط لكنّ التدوير يدوي بلا audit log. (2) Azure KeyVault + CSI driver، وهو متكامل جيدًا مع .NET مع mount تلقائي. (3) Doppler / Infisical / 1Password CLI، وهي SaaS مع تدوير قابل للتكوين.
خيارنا HashiCorp Vault، إذ يجمع بين audit log، وأسرار ديناميكية (تدوير اعتماد DB تلقائي)، و KV v2 versioning، وإخراج سر حاوية init K8s. ويغطي Cluster B6 (تدوير رمز API Cloudflare عبر Vault) التفاصيل.
هل نظام PageHits متوافق مع KVKK / GDPR؟
نعم. يتكون جدول PageHits من IP مُجزّأ + إثراء GeoIP (مستوى المدينة، وليس الشارع)؛ ولا نُخزّن ChatId أو UserId أو معرّف ملف تعريف ارتباط أو أي شيء يُعرّف المستخدم بشكل فريد. وبعد 90 يومًا من الاحتفاظ، يُشغَّل DELETE تلقائي (مشابه لـ IpBlocklistExpiryHostedService). ويوثّق Privacy.tr/en/ar.resx أُسس المادة 5 من KVKK والمادة 6(1)(f) من GDPR عبر 13 قسمًا (cross-link cluster C10).
AWS WAF مقابل Cloudflare WAF لـ .NET؟
يختلفان في التكلفة والمرونة:
| البُعد | AWS WAF | Cloudflare WAF |
|---|---|---|
| الموقع | أمام ALB / CloudFront | في طبقة CDN، multi-cloud |
| التكلفة (عينة) | 5$/شهر + 1$/قاعدة + 0.60$/M req | Free 5 قواعد، Pro 20$/شهر 25 قاعدة |
| .NET SDK | رسمي (AWSSDK.WAFV2) | مجتمعي |
| GraphQL Analytics | CloudWatch Logs (مدفوع) | Native، مُدرج |
| منطقة متوافقة مع KVKK | eu-central-1 | Frankfurt + Istanbul edge |
| Lock-in | بنية AWS التحتية | مستقل |
يُعدّ AWS WAF الخيار الطبيعي في معماريات AWS-only؛ فيما يبقى Cloudflare أكثر مرونة لـ on-prem أو multi-cloud. وبما أنّ إعدادنا K8s on-prem، فإنّ Cloudflare يناسب أكثر.
هل حلقة المُصنِّف الأصلي ← التغذية الراجعة لقاعدة WAF آمنة؟
تبدو حلقة الحظر التلقائي كنظام «يتعلّم ذاتيًا»؛ فهل يمكن أن تحظر مستخدمين حقيقيين عن طريق الخطأ؟ ثلاث ضمانات أمان تجيب على ذلك:
- عتبة ThreatScore ≥ 12 + ≥ 3 مسارات حساسة مختلفة في 15 دقيقة، إذ لا يكفي حتى مجموع عالٍ وحده
- TTL 24 ساعة، بحيث يسقط تلقائيًا أي حظر مُطلَق عن طريق الخطأ
- تجاوز يدوي للإدارة، عبر إزالة بنقرة واحدة وحذف Cloudflare List sync من
/admin/security/ip-blocklist
وفي الأسبوع الأول 0 إنذارات كاذبة بين 15 IPs محظورة تلقائيًا. كما أنّ self-IP الخاص بنا موجود في قائمة _allowedSelfIps opt-out لأمان إضافي.
مقالات ذات صلة
clusters هذا pillar (ترتيب النشر):
- B1 إدارة قواعد Cloudflare WAF API المخصصة من .NET (CRUD)
- B2 دفع IP Blocklist: Cloudflare List API + 5 قواعد WAF
- B3 كشف البوتات بناءً على ASN: سجل 42 مركز بيانات (CSV قابل للتنزيل)
- B4 مُصنِّف IsAnonymousOrDataCenter: مصفوفة قرار VPN/مركز بيانات
- B5 Cloudflare edge vs origin classifier: أيهما متى؟
- B6 تدوير رمز API Cloudflare عبر HashiCorp Vault
- B7 جامع أحداث WAF: Cloudflare GraphQL ← SQL Server ETL
- B8 مزالق UA matcher WAF (curl/wget/python-requests)
- B9 جدار الحماية الأصلي: UFW + قائمة CIDR لـ Cloudflare + auto-rollback
- B10 اختبارات UA للـ edge fetcher: Bingbot، و IndexNowBot pass-through
Cross-pillar bridge: قياسات الأمان من جانب الأصل مع .NET و Kubernetes ← Pillar 2؛ تشمل كشف الزوار الحقيقيين، وحساب ThreatScore، وعدّاد الانفجار MERGE+OUTPUT، وتحليل نسبة 33%/67%.
حزمة linkable asset:
- 🔗 ASN Registry CSV (gist)، قائمة ASN مركز بيانات مفتوحة المصدر، MIT license
- 🔗 24h Attack Snapshot CSV (gist)، مجموعة بيانات قياسات مجهولة الهوية
- 🔗 Cloudflare Edge Starter (GitHub repo)، قالب starter .NET 10 minimal
التعليقات (0)
لا توجد تعليقات بعد. كن أول من يعلق.