تقوية أمن السحابة وKubernetes

أمان الشبكات في السحابة

18 دقيقة الدرس 4 من 28

أمان الشبكات في السحابة

في مراكز البيانات التقليدية، كانت محيط الشبكة جدار حماية مادياً عند حافة المبنى. في السحابة، ينهار هذا النموذج: كل خدمة قادرة على الوصول إلى كل خدمة أخرى بشكل افتراضي ما لم تمنع ذلك صراحةً. لذا فإن أمان الشبكة في السحابة هو فعل مقصود وقائم على السياسات — يجب عليك تقسيم الشبكة وتقييدها ومراقبة كل مسار حركة مرور، وإلا فإن المهاجم الذي يخترق حاوية واحدة أو دالة واحدة سيتنقل بحرية عبر بنيتك بأكملها.

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

التقسيم: محيطات دقيقة في كل طبقة

التقسيم يعني تقسيم شبكتك إلى مناطق، حيث تمتلك كل منطقة الحد الأدنى من الاتصالية التي تحتاجها. في AWS، اللبنات الأساسية هي: VPCs، والشبكات الفرعية، ومجموعات الأمان (SGs)، وقوائم التحكم في الشبكة (NACLs). في Kubernetes، المكافئ هو سياسات الشبكة (Network Policies) التي تُنفذها إضافة CNI مثل Cilium أو Calico.

تسلسل التقسيم في بيئة AWS ناضجة يبدو كالتالي:

  • العزل على مستوى الحساب — الإنتاج والتطوير والأدوات تعيش في حسابات AWS منفصلة ضمن مؤسسة AWS Organization. حركة المرور العابرة للحسابات تمر عبر Transit Gateway أو PrivateLink، وليس الإنترنت العام أبداً.
  • تقسيم VPC — كل بيئة تحصل على VPC خاص بها. الاقتران (Peering) صريح ومحدد النطاق عبر جداول التوجيه؛ الاقتران الكامل بين جميع الشبكات علامة على غياب التصميم.
  • تقسيم الشبكات الفرعية — شبكات عامة (موازنات التحميل)، وخاصة للتطبيقات (الحوسبة)، ومعزولة للبيانات (RDS وElastiCache وOpenSearch). شبكات البيانات لا تملك مسار توجيه للإنترنت مطلقاً.
  • قواعد مجموعات الأمان — جدار الحماية الدقيق على مستوى النسخة. يعمل بحالة (Stateful)، والافتراضي هو الرفض. استخدم معرّفات SG بدلاً من نطاقات CIDR لحركة المرور الداخلية لكي لا تنكسر القواعد عند تدوير عناوين IP.
  • سياسات شبكة Kubernetes — جدار حماية على مستوى البود داخل الكتلة.

إليك سياسة شبكة Kubernetes مُصنّفة للإنتاج تمنح بود payments فقط حركة المرور الواردة التي يحتاجها — من نطاق اسم api-gateway على المنفذ 8443 ومن Prometheus للمراقبة:

# network-policy-payments.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: payments-ingress namespace: payments spec: podSelector: matchLabels: app: payments-service policyTypes: - Ingress - Egress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: api-gateway podSelector: matchLabels: app: api-gateway ports: - protocol: TCP port: 8443 - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: monitoring podSelector: matchLabels: app: prometheus ports: - protocol: TCP port: 9090 egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: payments-db ports: - protocol: TCP port: 5432 - to: # kube-dns - namespaceSelector: {} podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53
الرفض الافتراضي هو الهدف. سياسة NetworkPolicy تسري فقط على البودات التي يحددها podSelector. نطاق الأسماء الذي لا يحتوي على أي سياسة شبكة يكون مفتوحاً بالكامل. ابدأ دائماً بنشر سياسة رفض-الكل الافتراضية ثم افتح فقط ما تحتاجه.

نقاط النهاية الخاصة: إبقاء البيانات بعيدة عن الإنترنت العام

عندما تستدعي نسخة EC2 واجهة برمجة S3، يغادر هذا الاتصال افتراضياً VPC الخاص بك، ويعبر الإنترنت العام، ويصل إلى عنوان IP عام لـ S3، ثم يعود. هذا يعني أن بياناتك تعبر بنية تحتية لا تتحكم فيها، ونطاقك الترددي الصادر مُكلّف، وتحتاج إلى فتح HTTPS الصادر في مجموعة الأمان الخاصة بك إلى 0.0.0.0/0 — أسوأ قاعدة ممكنة.

نقاط نهاية VPC في AWS تحل هذه المشكلة. نقطة النهاية من نوع Gateway تُبقي حركة مرور S3 وDynamoDB داخل شبكة AWS الرئيسية، مجاناً. نقطة النهاية من نوع Interface (PrivateLink) تنشئ واجهة شبكة مرنة (ENI) في شبكتك الفرعية لأي خدمة AWS تقريباً — SQS وSSM وECR وSecrets Manager وRDS Data API وCloudWatch Logs وغيرها. الحركة لا تغادر شبكة Amazon أبداً، ويتحسن زمن الوصول، ويمكنك تقييد مجموعات الأمان لرفض حركة 443 الصادرة إلى الإنترنت كلياً.

# Terraform: نقطة نهاية Interface لـ Secrets Manager + ECR (مطلوبة لعقد EKS الخاصة) resource "aws_vpc_endpoint" "secretsmanager" { vpc_id = aws_vpc.main.id service_name = "com.amazonaws.${var.region}.secretsmanager" vpc_endpoint_type = "Interface" subnet_ids = aws_subnet.private[*].id security_group_ids = [aws_security_group.vpce.id] private_dns_enabled = true # يُلغي DNS العام — لا حاجة لتغيير كود التطبيق tags = { Name = "secretsmanager-vpce" } } resource "aws_vpc_endpoint" "ecr_api" { vpc_id = aws_vpc.main.id service_name = "com.amazonaws.${var.region}.ecr.api" vpc_endpoint_type = "Interface" subnet_ids = aws_subnet.private[*].id security_group_ids = [aws_security_group.vpce.id] private_dns_enabled = true } resource "aws_vpc_endpoint" "ecr_dkr" { vpc_id = aws_vpc.main.id service_name = "com.amazonaws.${var.region}.ecr.dkr" vpc_endpoint_type = "Interface" subnet_ids = aws_subnet.private[*].id security_group_ids = [aws_security_group.vpce.id] private_dns_enabled = true } # مجموعة أمان نقطة النهاية: السماح بالمنفذ 443 الوارد من مجموعة أمان عقد الكتلة فقط resource "aws_security_group" "vpce" { name = "vpce-sg" vpc_id = aws_vpc.main.id ingress { from_port = 443 to_port = 443 protocol = "tcp" security_groups = [aws_security_group.eks_nodes.id] } }
قائمة فحص EKS ذات النطاق الخاص الكامل. لعقد عمال EKS بدون وصول للإنترنت تحتاج إلى نقاط نهاية Interface لـ: ecr.api وecr.dkr وs3 (Gateway) وec2 وsts وelasticloadbalancing وlogs (CloudWatch) وssm وssmmessages إن كنت تستخدم SSM Session Manager للوصول إلى العقد. إغفال أي واحدة منها سيترك العقد في حالة NotReady مع أخطاء سحب غامضة.

التحكم في حركة المرور الصادرة: خط الدفاع الأخير قبل التسرب

فلترة حركة المرور الصادرة هي التحكم الشبكي الأكثر إغفالاً في بيئات السحابة — والتحكم الذي يعتمد عليه المهاجمون أكثر من أي شيء آخر. تجهيز برامج الفدية، ونداءات مُعدِّنات العملات المشفرة، وعمليات تسرب البيانات كلها تتطلب اتصالاً صادراً. إذا سمحت بـHTTPS صادر غير مقيد من الحوسبة، فيمكن للحاوية المخترقة الاتصال بالخارج بصمت لأشهر.

معمارية حركة المرور الصادرة في الإنتاج:

  • كل حركة المرور الصادرة إلى الإنترنت تُجبر على المرور عبر بروكسي خروج مُدار (في AWS: NAT Gateway + طبقة فلترة DNS مثل AWS Network Firewall أو مجموعة Squid ذاتية الإدارة؛ في GCP: Cloud NAT + Cloud Armor؛ في Azure: Azure Firewall مع قواعد FQDN).
  • يُنفذ البروكسي قائمة مسموح بها من أسماء النطاقات الكاملة (FQDN) — وليس نطاقات IP، لأن كبار مزودي السحابة يُدورون عناوين IP باستمرار. فقط أسماء المضيفين المحددة التي تحتاجها خدماتك فعلاً مسموح بها.
  • أعباء عمل Kubernetes التي لا تحتاج لأي وصول للإنترنت تحصل على سياسات شبكة ترفض كل حركة الإخراج باستثناء الخدمات الداخلية للكتلة ونقاط نهاية VPC. الأعباء التي تحتاج فعلاً للإنترنت تُعزل في مجموعة عقد ونطاق أسماء مخصص مع تسجيل تدقيق إضافي.
Zero-Egress Cloud Architecture AWS VPC — الشبكات الفرعية الخاصة فقط Internet (Attacker C2) EKS Cluster api-pod egress: deny-all worker-pod egress: deny-all notify-pod egress: proxy batch-pod egress: deny-all نقاط نهاية VPC الخاصة Secrets Manager ECR · S3 · STS · SSM CloudWatch Logs · SQS (لا تصل إلى الإنترنت أبداً) Egress Proxy AWS Network Firewall قائمة FQDN المسموح بها AWS Backbone (شبكة خاصة) api.stripe.com (FQDN مدرج في القائمة) BLOCKED مسموح محظور بواسطة NP
معمارية صفرية الإخراج: البودات تستخدم نقاط نهاية VPC لخدمات AWS؛ فقط بروكسي الخروج المخصص يمكنه الوصول إلى نطاقات FQDN الخارجية؛ المسارات المحظورة موضحة باللون الأحمر.

تطبيق نمط الإخراج الصفري

إليك مجموعة قواعد Terraform لـ AWS Network Firewall التي تُنفذ قائمة FQDN المسموح بها على مستوى VPC. هذه مجموعة قواعد ذات حالة (Stateful) — تفحص مؤشر اسم الخادم (SNI) في مصافحات TLS، لذا تعمل مع HTTPS بدون فك التشفير:

resource "aws_networkfirewall_rule_group" "egress_allowlist" { capacity = 100 name = "egress-fqdn-allowlist" type = "STATEFUL" rule_group { rules_source { rules_source_list { generated_rules_type = "ALLOWLIST" target_types = ["TLS_SNI", "HTTP_HOST"] targets = [ "api.stripe.com", "hooks.slack.com", "o1234567.ingest.sentry.io", "updates.example-vendor.com", ] } } stateful_rule_options { rule_order = "STRICT_ORDER" } } } resource "aws_networkfirewall_policy" "egress" { name = "egress-policy" firewall_policy { stateless_default_actions = ["aws:forward_to_sfe"] stateless_fragment_default_actions = ["aws:forward_to_sfe"] stateful_rule_group_reference { resource_arn = aws_networkfirewall_rule_group.egress_allowlist.arn priority = 1 } # إسقاط كل شيء غير مسموح به صراحةً stateful_default_actions = ["aws:drop_established", "aws:alert_established"] } }
NAT Gateway ليس تحكماً في حركة المرور الصادرة. بوابة NAT تسمح بخروج كل شيء — إنها جهاز توجيه، وليست جدار حماية. كثير من المؤسسات تعتقد أنها تتحكم في حركة المرور الصادرة لأنها تستخدم NAT Gateway. أنت بحاجة إلى طبقة ذات حالة (Network Firewall أو بروكسي أو قواعد أمان مجموعة الخروج محدودة النطاق بنطاقات CIDR معروفة) أمام NAT لفلترة حركة المرور فعلياً. يعرف المهاجمون هذا ويستغلونه بانتظام.

أنماط الفشل في الإنتاج

  • إغفال egress لـ kube-dns في سياسة الشبكة — البودات لا تستطيع تحليل أسماء الخدمات. أدرج دائماً egress UDP/53 إلى kube-dns في أي سياسة مخصصة وإلا يفشل التحليل بصمت.
  • نقطة نهاية Interface في نطاق التوافر الخاطئ — إذا كانت ENI نقطة النهاية في us-east-1a فقط لكن البودات تعمل في us-east-1b، تتراكم تكاليف وتأخيرات عبر مناطق التوافر. انشر نقاط النهاية في كل منطقة توافر تستخدمها عقدك.
  • قائمة FQDN لا تغطي أسماء مضيفي CDN — البائعون غالباً يقدمون تحديثات SDK من أسماء نطاقات CDN متغيرة (*.cloudfront.net). يجب استخدام القواعد ذات الأحرف البدل في Network Firewall بتعمد وبأضيق نطاق ممكن.
  • ترك قاعدة 0.0.0.0/0 للإخراج في مجموعة الأمان — مزود Terraform لـ AWS ينشئ هذه القاعدة افتراضياً. استخدم كتل دورة حياة create_before_destroy وقواعد إخراج صريحة لإزالتها.
دقق في حركة الإخراج الخاصة بك اليوم. نفّذ الأمر aws ec2 describe-security-groups --filters Name=ip-permission.from-port,Values=443 Name=ip-permission.cidr,Values=0.0.0.0/0 --query 'SecurityGroups[*].GroupId' للعثور على كل مجموعة أمان في حسابك تسمح بـHTTPS الصادر إلى العالم. كل نتيجة هي مسار تسرب بيانات محتمل.