مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

توجه داشته باشید. ترجمه: نویسنده مقاله، Reuven Harrison، بیش از 20 سال تجربه در توسعه نرم افزار دارد و امروز مدیر ارشد فناوری و یکی از بنیانگذاران Tufin است، شرکتی که راه حل های مدیریت سیاست های امنیتی را ایجاد می کند. در حالی که او سیاست‌های شبکه Kubernetes را ابزاری نسبتاً قدرتمند برای تقسیم‌بندی شبکه در یک خوشه می‌داند، او همچنین معتقد است که پیاده‌سازی آنها در عمل چندان آسان نیست. این ماده (بسیار حجیم) برای بهبود آگاهی متخصصان از این موضوع و کمک به آنها در ایجاد تنظیمات لازم است.

امروزه بسیاری از شرکت ها به طور فزاینده ای Kubernetes را برای اجرای برنامه های خود انتخاب می کنند. علاقه به این نرم افزار آنقدر زیاد است که برخی کوبرنتیس را «سیستم عامل جدید مرکز داده» می نامند. به تدریج، Kubernetes (یا k8s) به عنوان بخش مهمی از تجارت در نظر گرفته می شود، که نیاز به سازماندهی فرآیندهای تجاری بالغ، از جمله امنیت شبکه دارد.

برای متخصصان امنیتی که از کار با Kubernetes گیج شده‌اند، آشکار شدن واقعی ممکن است خط‌مشی پیش‌فرض پلتفرم باشد: اجازه دادن به همه چیز.

این راهنما به شما کمک می کند تا ساختار داخلی سیاست های شبکه را درک کنید. تفاوت آنها با قوانین فایروال های معمولی را درک کنید. همچنین برخی از مشکلات را پوشش می دهد و توصیه هایی برای کمک به ایمن سازی برنامه های کاربردی در Kubernetes ارائه می دهد.

سیاست های شبکه Kubernetes

مکانیسم خط مشی شبکه Kubernetes به شما امکان می دهد تا تعامل برنامه های کاربردی مستقر در پلت فرم را در لایه شبکه (سومین در مدل OSI) مدیریت کنید. خط‌مشی‌های شبکه فاقد برخی از ویژگی‌های پیشرفته فایروال‌های مدرن، مانند اجرای لایه ۷ OSI و شناسایی تهدید هستند، اما سطح پایه‌ای از امنیت شبکه را فراهم می‌کنند که نقطه شروع خوبی است.

سیاست های شبکه ارتباطات بین پادها را کنترل می کند

بارهای کاری در Kubernetes در بین پادها توزیع می شوند که از یک یا چند کانتینر تشکیل شده اند که با هم مستقر شده اند. Kubernetes به هر پاد یک آدرس IP اختصاص می دهد که از پادهای دیگر قابل دسترسی است. خط‌مشی‌های شبکه Kubernetes حقوق دسترسی را برای گروه‌هایی از pod‌ها تنظیم می‌کنند، به همان روشی که گروه‌های امنیتی در ابر برای کنترل دسترسی به نمونه‌های ماشین مجازی استفاده می‌شوند.

تعریف سیاست های شبکه

مانند سایر منابع Kubernetes، سیاست های شبکه در YAML مشخص شده است. در مثال زیر، اپلیکیشن balance دسترسی به postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

(توجه داشته باشید. ترجمه: این اسکرین شات، مانند همه موارد مشابه بعدی، نه با استفاده از ابزارهای بومی Kubernetes، بلکه با استفاده از ابزار Tufin Orca که توسط شرکت نویسنده مقاله اصلی توسعه داده شده و در انتهای مطلب ذکر شده است، ایجاد شده است.)

برای تعریف خط مشی شبکه خود، به دانش اولیه YAML نیاز دارید. این زبان بر اساس تورفتگی است (به جای زبانه ها با فاصله مشخص می شود). یک عنصر تورفتگی متعلق به نزدیکترین عنصر فرورفته بالای آن است. یک عنصر لیست جدید با خط فاصله شروع می شود، همه عناصر دیگر دارای فرم هستند ارزش کلیدی.

پس از تشریح خط مشی در YAML، استفاده کنید کوبکتلبرای ایجاد آن در خوشه:

kubectl create -f policy.yaml

مشخصات خط مشی شبکه

مشخصات خط مشی شبکه Kubernetes شامل چهار عنصر است:

  1. podSelector: غلاف های تحت تأثیر این سیاست (هدف ها) را تعریف می کند - مورد نیاز است.
  2. policyTypes: نشان می دهد که چه نوع خط مشی هایی در این مورد گنجانده شده است: ورود و/یا خروج - اختیاری است، اما توصیه می کنم در همه موارد به صراحت آن را مشخص کنید.
  3. ingress: مجاز را تعریف می کند ورودی ترافیک به غلاف های هدف - اختیاری.
  4. egress: مجاز را تعریف می کند برونگرا ترافیک از غلاف های هدف اختیاری است.

نمونه برگرفته از وب سایت Kubernetes (من جایگزین کردم role بر app)، نحوه استفاده از هر چهار عنصر را نشان می دهد:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: db
  policyTypes:    # <<<
  - Ingress
  - Egress
  ingress:        # <<<
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:         # <<<
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی
مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

لطفاً توجه داشته باشید که هر چهار عنصر لازم نیست گنجانده شوند. فقط اجباری است podSelector، پارامترهای دیگر را می توان به دلخواه استفاده کرد.

اگر حذف کنیم policyTypes، سیاست به صورت زیر تفسیر می شود:

  • به طور پیش فرض، فرض می شود که سمت ورودی را تعریف می کند. اگر خط مشی به صراحت این را بیان نکند، سیستم فرض می کند که تمام ترافیک ممنوع است.
  • رفتار در سمت خروجی با وجود یا عدم وجود پارامتر خروجی مربوطه تعیین می شود.

برای جلوگیری از اشتباه توصیه می کنم همیشه آن را صریح بیان کنید policyTypes.

با توجه به منطق فوق، اگر پارامترهای ingress و یا egress در صورت حذف، این خط مشی تمام ترافیک را رد می کند (به "قانون سلب کردن" در زیر مراجعه کنید).

خط مشی پیش فرض Allow است

اگر هیچ خط مشی تعریف نشده باشد، Kubernetes به طور پیش فرض اجازه می دهد تا همه ترافیک را انجام دهد. همه غلاف ها می توانند آزادانه اطلاعات را بین خود مبادله کنند. این ممکن است از منظر امنیتی غیر منطقی به نظر برسد، اما به یاد داشته باشید که Kubernetes در ابتدا توسط توسعه دهندگان برای فعال کردن قابلیت همکاری برنامه ها طراحی شده بود. سیاست های شبکه بعدا اضافه شد.

فضاهای نام

فضاهای نام مکانیسم همکاری Kubernetes هستند. آنها برای جداسازی محیط های منطقی از یکدیگر طراحی شده اند، در حالی که ارتباط بین فضاها به طور پیش فرض مجاز است.

مانند اکثر اجزای Kubernetes، سیاست های شبکه در یک فضای نام خاص زندگی می کنند. در بلوک metadata می توانید مشخص کنید که این خط مشی متعلق به کدام فضای است:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

اگر فضای نام به طور صریح در فراداده مشخص نشده باشد، سیستم از فضای نام مشخص شده در kubectl استفاده می کند (به طور پیش فرض namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

من توصیه می کنم فضای نام را به صراحت مشخص کنید، مگر اینکه سیاستی بنویسید که چندین فضای نام را همزمان هدف قرار دهد.

اصلی عنصر podSelector در خط مشی، غلاف ها را از فضای نامی که خط مشی به آن تعلق دارد انتخاب می کند (دسترسی به پادها از فضای نام دیگر ممنوع است).

به طور مشابه، podSelectors در بلوک های ورودی و خروجی فقط می تواند پادها را از فضای نام خود انتخاب کند، مگر اینکه البته آنها را با آنها ترکیب کنید namespaceSelector (این مورد در بخش "فیلتر بر اساس فضاهای نام و غلاف" مورد بحث قرار خواهد گرفت).

قوانین نامگذاری خط مشی

نام‌های خط‌مشی در همان فضای نام منحصربه‌فرد هستند. نمی‌توان دو سیاست با نام یکسان در یک فضا وجود داشته باشد، اما می‌تواند سیاست‌هایی با نام یکسان در فضاهای مختلف وجود داشته باشد. این زمانی مفید است که می‌خواهید یک خط مشی مشابه را در چندین فضا دوباره اعمال کنید.

من به خصوص یکی از روش های نامگذاری را دوست دارم. این شامل ترکیب نام فضای نام با غلاف های هدف است. مثلا:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

برچسب ها

می‌توانید برچسب‌های سفارشی را به اشیاء Kubernetes، مانند پادها و فضاهای نام، وصل کنید. برچسب ها (برچسب ها - برچسب ها) معادل برچسب ها در ابر هستند. خط‌مشی‌های شبکه Kubernetes از برچسب‌ها برای انتخاب استفاده می‌کنند غلاف هاکه به آنها اعمال می شود:

podSelector:
  matchLabels:
    role: db

… یا فضاهای نامکه برای آنها اعمال می شود. این مثال همه غلاف ها را در فضای نام با برچسب های مربوطه انتخاب می کند:

namespaceSelector:
  matchLabels:
    project: myproject

یک احتیاط: هنگام استفاده namespaceSelector مطمئن شوید که فضاهای نامی که انتخاب می‌کنید دارای برچسب صحیح باشند. توجه داشته باشید که فضاهای نام داخلی مانند default и kube-system، به طور پیش فرض حاوی برچسب نیستند.

می توانید یک برچسب به فضایی مانند این اضافه کنید:

kubectl label namespace default namespace=default

در همان زمان، فضای نام در بخش metadata باید به نام فضای واقعی اشاره داشته باشد، نه برچسب:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

منبع و مقصد

خط‌مشی‌های فایروال شامل قوانینی با منابع و مقصد هستند. خط‌مشی‌های شبکه Kubernetes برای یک هدف تعریف می‌شوند - مجموعه‌ای از پادها که برای آن اعمال می‌شوند - و سپس قوانینی را برای ترافیک ورودی و/یا خروجی تعیین می‌کنند. در مثال ما، هدف خط مشی تمام پادهای موجود در فضای نام خواهد بود default با برچسب با کلید app و معنی db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db   # <<<
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی
مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

زیر بخش ingress در این خط مشی، ترافیک ورودی را به پادهای هدف باز می کند. به عبارت دیگر، ورودی منبع و هدف مقصد مربوطه است. به همین ترتیب، خروج مقصد و هدف منبع آن است.

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

این معادل دو قانون فایروال است: Ingress → Target. هدف → خروج.

Egress و DNS (مهم!)

با محدود کردن ترافیک خروجی، به DNS توجه ویژه ای داشته باشید - Kubernetes از این سرویس برای نگاشت خدمات به آدرس های IP استفاده می کند. به عنوان مثال، سیاست زیر کار نخواهد کرد زیرا شما به برنامه اجازه نداده اید balance دسترسی به DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

می توانید با باز کردن دسترسی به سرویس DNS آن را برطرف کنید:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

آخرین عنصر to خالی است و بنابراین به طور غیر مستقیم انتخاب می کند همه غلاف ها در همه فضاهای نام، اجازه می دهد balance پرس و جوهای DNS را به سرویس مناسب Kubernetes ارسال کنید (معمولاً در فضا اجرا می شود kube-system).

این رویکرد به هر حال کار می کند بیش از حد مجاز و ناامن، زیرا اجازه می دهد پرس و جوهای DNS به خارج از خوشه هدایت شوند.

شما می توانید آن را در سه مرحله متوالی بهبود بخشید.

1. فقط درخواست های DNS را مجاز کنید در داخل با افزودن خوشه namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

2. درخواست های DNS فقط در فضای نام مجاز است kube-system.

برای این کار باید یک برچسب به فضای نام اضافه کنید kube-system: kubectl label namespace kube-system namespace=kube-system - و آن را در خط مشی استفاده بنویسید namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

3. افراد پارانوئید می توانند حتی فراتر رفته و درخواست های DNS را به یک سرویس DNS خاص محدود کنند kube-system. بخش "فیلتر بر اساس فضاهای نام و غلاف" به شما می گوید که چگونه به این هدف برسید.

گزینه دیگر حل DNS در سطح فضای نام است. در این صورت، برای هر سرویس نیازی به باز کردن آن نخواهد بود:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

خالی podSelector همه غلاف ها را در فضای نام انتخاب می کند.

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

اولین مسابقه و ترتیب قانون

در فایروال های معمولی، عمل (Allow یا Deny) روی یک بسته با قانون اولی که آن را برآورده می کند تعیین می شود. در Kubernetes، ترتیب سیاست ها مهم نیست.

به طور پیش‌فرض، وقتی هیچ خط‌مشی تنظیم نشده باشد، ارتباطات بین پادها مجاز است و می‌توانند آزادانه اطلاعات را تبادل کنند. هنگامی که شروع به تدوین خط مشی ها می کنید، هر غلاف تحت تأثیر حداقل یکی از آنها بر اساس تفکیک (OR منطقی) همه خط مشی هایی که آن را انتخاب کرده اند، جدا می شود. غلاف هایی که تحت تأثیر هیچ سیاستی قرار نگرفته اند باز می مانند.

شما می توانید این رفتار را با استفاده از یک قانون سلب تغییر دهید.

قانون سلب کردن ("انکار")

خط‌مشی‌های فایروال معمولاً هرگونه ترافیکی را که صراحتاً مجاز نیست، رد می‌کند.

عمل انکار در Kubernetes وجود نداردبا این حال، یک اثر مشابه را می توان با یک خط مشی منظم (مجاز) با انتخاب یک گروه خالی از غلاف منبع (ورود) به دست آورد:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

این خط‌مشی همه غلاف‌ها را در فضای نام انتخاب می‌کند و ورودی را نامشخص می‌گذارد و همه ترافیک ورودی را رد می‌کند.

به روشی مشابه، می‌توانید تمام ترافیک خروجی را از یک فضای نام محدود کنید:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

لطفا توجه داشته باشید که هرگونه خط مشی اضافی که به ترافیک پادها در فضای نام اجازه می دهد بر این قانون اولویت دارد (شبیه به اضافه کردن یک قانون اجازه قبل از یک قانون انکار در پیکربندی فایروال).

همه چیز را مجاز کنید (Any-Any-Any-Allow)

برای ایجاد یک خط مشی Allow All، باید خط مشی Deny بالا را با یک عنصر خالی تکمیل کنید ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

اجازه دسترسی از همه پادها در همه فضاهای نام (و همه IP) به هر پاد در فضای نام default. این رفتار به طور پیش فرض فعال است، بنابراین معمولاً نیازی به تعریف بیشتر نیست. با این حال، گاهی اوقات ممکن است لازم باشد برخی از مجوزهای خاص را برای تشخیص مشکل به طور موقت غیرفعال کنید.

این قانون را می توان محدود کرد تا فقط به آن دسترسی داشته باشید مجموعه خاصی از غلاف ها (app:balance) در فضای نام default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

خط مشی زیر به همه ترافیک ورودی و خروجی، از جمله دسترسی به هر IP خارج از خوشه اجازه می دهد:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی
مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

ترکیب چند سیاست

سیاست ها با استفاده از OR منطقی در سه سطح ترکیب می شوند. مجوزهای هر پاد مطابق با تفکیک همه خط‌مشی‌هایی که بر آن تأثیر می‌گذارند تنظیم می‌شوند:

1. در مزارع from и to سه نوع عنصر را می توان تعریف کرد (که همه آنها با استفاده از OR ترکیب می شوند):

  • namespaceSelector - کل فضای نام را انتخاب می کند.
  • podSelector - غلاف ها را انتخاب می کند.
  • ipBlock - یک زیرشبکه را انتخاب می کند.

علاوه بر این، تعداد عناصر (حتی یکسان) در بخش‌های فرعی from/to بدون محدودیت. همه آنها با OR منطقی ترکیب خواهند شد.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

2. داخل بخش سیاست ingress می تواند عناصر زیادی داشته باشد from (ترکیب با OR منطقی). به طور مشابه، بخش egress ممکن است شامل عناصر زیادی باشد to (همچنین با تفکیک ترکیب شده است):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

3. سیاست های مختلف نیز با OR منطقی ترکیب می شوند

اما هنگام ترکیب آنها، یک محدودیت وجود دارد که در آن وجود دارد اشاره کرد کریس کونی: Kubernetes فقط می تواند سیاست ها را با سیاست های مختلف ترکیب کند policyTypes (Ingress یا Egress). خط‌مشی‌هایی که ورود (یا خروج) را تعریف می‌کنند، یکدیگر را بازنویسی می‌کنند.

رابطه بین فضاهای نام

به طور پیش فرض، اشتراک گذاری اطلاعات بین فضاهای نام مجاز است. این را می‌توان با استفاده از یک خط‌مشی انکار که ترافیک خروجی و/یا ورودی به فضای نام را محدود می‌کند، تغییر داد (به «قانون حذف» در بالا مراجعه کنید).

هنگامی که دسترسی به یک فضای نام را مسدود کردید (به "قانون سلب کردن" در بالا مراجعه کنید)، می توانید با اجازه دادن به اتصالات از یک فضای نام خاص با استفاده از خط مشی انکار، استثنا قائل شوید. namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

در نتیجه، تمام غلاف ها در فضای نام default به غلاف ها دسترسی خواهند داشت postgres در فضای نام database. اما اگر بخواهید دسترسی به آن را باز کنید چه می شود postgres فقط غلاف های خاص در فضای نام default?

فیلتر بر اساس فضای نام و غلاف

Kubernetes نسخه 1.11 و بالاتر به شما امکان ترکیب اپراتورها را می دهد namespaceSelector и podSelector با استفاده از AND منطقی به نظر می رسد:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

چرا این به جای OR معمولی به AND تعبیر می شود؟

لطفا توجه داشته باشید که podSelector با خط فاصله شروع نمی شود در YAML این به این معنی است که podSelector و روبرویش ایستاده namespaceSelector به همان عنصر فهرست مراجعه کنید. بنابراین، آنها با AND منطقی ترکیب می شوند.

قبل از اضافه کردن خط فاصله podSelector منجر به ظهور یک عنصر لیست جدید می شود که با عنصر قبلی ترکیب می شود namespaceSelector با استفاده از OR منطقی

برای انتخاب غلاف با یک برچسب خاص در همه فضاهای نام، خالی وارد کنید namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

چندین برچسب با I همکاری می کنند

قوانین یک فایروال با چندین شی (میزبان، شبکه، گروه) با استفاده از OR منطقی ترکیب می شوند. اگر منبع بسته مطابقت داشته باشد، قانون زیر کار خواهد کرد Host_1 OR Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

برعکس، در Kubernetes برچسب های مختلف در podSelector یا namespaceSelector با AND منطقی ترکیب می شوند. برای مثال، قانون زیر غلاف هایی را انتخاب می کند که هر دو برچسب را دارند. role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

منطق یکسانی برای همه انواع عملگرها صدق می کند: انتخابگرهای هدف سیاست، انتخابگرهای pod و انتخابگرهای فضای نام.

زیرشبکه ها و آدرس های IP (IPBlocks)

فایروال ها از VLAN ها، آدرس های IP و زیرشبکه ها برای بخش بندی شبکه استفاده می کنند.

در Kubernetes، آدرس‌های IP به‌طور خودکار به پادها اختصاص داده می‌شوند و می‌توانند مرتباً تغییر کنند، بنابراین از برچسب‌ها برای انتخاب پادها و فضاهای نام در خط‌مشی‌های شبکه استفاده می‌شود.

زیرشبکه ها (ipBlocks) هنگام مدیریت اتصالات خارجی ورودی (ورودی) یا خروجی (خروجی) (شمال-جنوب) استفاده می شود. به عنوان مثال، این خط مشی برای همه پادها از فضای نام باز می شود default دسترسی به سرویس DNS گوگل:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

انتخابگر غلاف خالی در این مثال به معنای «انتخاب همه پادها در فضای نام» است.

این سیاست فقط اجازه دسترسی به 8.8.8.8 را می دهد. دسترسی به هر IP دیگر ممنوع است. بنابراین، در اصل، شما دسترسی به سرویس داخلی Kubernetes DNS را مسدود کرده اید. اگر هنوز می خواهید آن را باز کنید، این را به صراحت نشان دهید.

معمولا ipBlocks и podSelectors متقابلا انحصاری هستند، زیرا آدرس های IP داخلی پادها در آنها استفاده نمی شود ipBlocks. با نشان دادن پادهای IP داخلی، در واقع اجازه اتصال به/از پادها با این آدرس ها را می دهید. در عمل، شما نمی دانید از کدام آدرس IP استفاده کنید، به همین دلیل است که نباید از آنها برای انتخاب پادها استفاده کنید.

به عنوان مثال متقابل، خط مشی زیر شامل تمام IP ها می شود و بنابراین اجازه دسترسی به سایر پادها را می دهد:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

شما می توانید فقط به IP های خارجی دسترسی داشته باشید، به استثنای آدرس های IP داخلی پادها. به عنوان مثال، اگر زیرشبکه غلاف شما 10.16.0.0/14 باشد:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

پورت ها و پروتکل ها

به طور معمول پادها به یک پورت گوش می دهند. این بدان معنی است که شما به سادگی می توانید شماره پورت را در سیاست ها مشخص نکنید و همه چیز را به عنوان پیش فرض بگذارید. با این حال، توصیه می‌شود تا حد امکان سیاست‌ها را محدود کنید، بنابراین در برخی موارد همچنان می‌توانید پورت‌ها را مشخص کنید:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

توجه داشته باشید که انتخابگر ports برای همه عناصر در بلوک اعمال می شود to یا from، که شامل. برای تعیین پورت های مختلف برای مجموعه های مختلف عناصر، تقسیم ingress یا egress به چندین زیربخش با to یا from و در هر یک پورت های خود را ثبت کنید:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی

عملکرد پیش فرض پورت:

  • اگر تعریف پورت را به طور کامل حذف کنید (ports) یعنی همه پروتکل ها و همه پورت ها.
  • اگر تعریف پروتکل را حذف کنید (protocol)، این به معنای TCP است.
  • اگر تعریف پورت را حذف کنید (port) یعنی همه پورت ها.

بهترین روش: به مقادیر پیش فرض تکیه نکنید، آنچه را که نیاز دارید به صراحت مشخص کنید.

لطفاً توجه داشته باشید که باید از پورت‌های پاد استفاده کنید، نه از پورت‌های سرویس (اطلاعات بیشتر در این مورد در پاراگراف بعدی).

آیا خط مشی هایی برای پادها یا خدمات تعریف شده است؟

به طور معمول، پادها در Kubernetes از طریق یک سرویس به یکدیگر دسترسی دارند - یک متعادل کننده بار مجازی که ترافیک را به پادهایی که سرویس را اجرا می کنند هدایت می کند. ممکن است فکر کنید که سیاست های شبکه دسترسی به خدمات را کنترل می کنند، اما اینطور نیست. خط‌مشی‌های شبکه Kubernetes روی پورت‌های پاد کار می‌کنند، نه پورت‌های سرویس.

به عنوان مثال، اگر سرویسی به پورت 80 گوش می دهد، اما ترافیک را به پورت 8080 پادهای خود هدایت می کند، باید دقیقاً 8080 را در خط مشی شبکه مشخص کنید.

چنین مکانیزمی را باید غیربهینه در نظر گرفت: اگر ساختار داخلی سرویس (درگاه هایی که پادها به آن گوش می دهند) تغییر کند، سیاست های شبکه باید به روز شوند.

رویکرد معماری جدید با استفاده از سرویس مش (به عنوان مثال، در مورد ایستیو در زیر نگاه کنید - تقریباً ترجمه شده است.) به شما اجازه می دهد تا با این مشکل کنار بیایید.

آیا ثبت هر دو Ingress و Egress ضروری است؟

پاسخ کوتاه این است که بله، برای اینکه غلاف A با غلاف B ارتباط برقرار کند، باید اجازه ایجاد یک اتصال خروجی را داشته باشد (برای این کار باید یک خط مشی خروج را پیکربندی کنید)، و pod B باید بتواند یک اتصال ورودی را بپذیرد ( برای این، بر این اساس، شما به یک سیاست ورود نیاز دارید).

با این حال، در عمل، برای اجازه دادن به اتصالات در یک یا هر دو جهت، می توانید به سیاست پیش فرض تکیه کنید.

اگر مقداری غلاف-منبع توسط یک یا چند نفر انتخاب خواهد شد خروج کردن-سیاستمداران، محدودیت های اعمال شده بر آن با تفکیک آنها مشخص خواهد شد. در این مورد، باید صریحاً اجازه اتصال به پاد را بدهید -مخاطب. اگر یک پاد توسط هیچ خط مشی انتخاب نشده باشد، ترافیک خروجی (خروجی) آن به طور پیش فرض مجاز است.

به همین ترتیب، سرنوشت غلاف استمخاطب، توسط یک یا چند انتخاب شده است وارد شدن-سیاستمداران، با تفکیک آنها تعیین خواهند شد. در این صورت، باید به صراحت به آن اجازه دهید که ترافیک را از پاد منبع دریافت کند. اگر یک پاد توسط هیچ سیاستی انتخاب نشده باشد، تمام ترافیک ورودی برای آن به طور پیش‌فرض مجاز است.

دولتی یا بدون تابعیت را در زیر ببینید.

سیاهههای مربوط

خط‌مشی‌های شبکه Kubernetes نمی‌توانند ترافیک را ثبت کنند. این امر تعیین اینکه آیا یک خط مشی طبق برنامه کار می کند یا خیر دشوار می کند و تجزیه و تحلیل امنیتی را بسیار پیچیده می کند.

کنترل ترافیک به خدمات خارجی

خط‌مشی‌های شبکه Kubernetes به شما اجازه نمی‌دهد یک نام دامنه کاملاً واجد شرایط (DNS) را در بخش‌های خروج مشخص کنید. این واقعیت هنگام تلاش برای محدود کردن ترافیک به مقصدهای خارجی که آدرس IP ثابتی ندارند (مانند aws.com) باعث ناراحتی قابل توجهی می شود.

بررسی سیاست

فایروال ها به شما هشدار می دهند یا حتی از پذیرش سیاست اشتباه خودداری می کنند. Kubernetes همچنین برخی از تأیید را انجام می دهد. هنگام تنظیم یک خط مشی شبکه از طریق kubectl، Kubernetes ممکن است اعلام کند که نادرست است و از پذیرش آن امتناع کند. در موارد دیگر، Kubernetes خط‌مشی را می‌گیرد و آن را با جزئیات گمشده پر می‌کند. آنها را می توان با استفاده از دستور مشاهده کرد:

kubernetes get networkpolicy <policy-name> -o yaml

به خاطر داشته باشید که سیستم اعتبارسنجی Kubernetes خطاناپذیر نیست و ممکن است برخی از انواع خطاها را از دست بدهد.

اعدام

Kubernetes خود سیاست های شبکه را پیاده سازی نمی کند، بلکه صرفا یک دروازه API است که بار کنترل را به یک سیستم زیربنایی به نام Container Networking Interface (CNI) محول می کند. تنظیم خط‌مشی‌ها در یک خوشه Kubernetes بدون اختصاص CNI مناسب مانند ایجاد خط‌مشی‌ها در سرور مدیریت فایروال بدون نصب آن‌ها بر روی فایروال‌ها است. این به شما بستگی دارد که مطمئن شوید CNI مناسبی دارید یا در مورد پلتفرم های Kubernetes، در فضای ابری میزبانی می کنید. (می توانید لیست ارائه دهندگان را مشاهده کنید اینجا - تقریبا ترانس.)، سیاست های شبکه را فعال کنید که CNI را برای شما تنظیم می کند.

توجه داشته باشید که در صورت تنظیم خط مشی شبکه بدون کمک CNI مناسب، Kubernetes به شما هشدار نخواهد داد.

دارای تابعیت یا بی تابعیت؟

تمام CNI های Kubernetes که من با آنها مواجه شده ام حالت دارند (به عنوان مثال، Calico از conntrack لینوکس استفاده می کند). این به غلاف اجازه می‌دهد تا بدون نیاز به برقراری مجدد، پاسخ‌ها را روی اتصال TCP که شروع کرده است دریافت کند. با این حال، من از استاندارد Kubernetes اطلاعی ندارم که ثابت بودن را تضمین کند.

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

در اینجا چند راه برای بهبود اجرای سیاست امنیتی در Kubernetes وجود دارد:

  1. الگوی معماری Service Mesh از ظروف کناری برای ارائه تله متری دقیق و کنترل ترافیک در سطح خدمات استفاده می کند. به عنوان مثال می توانیم استفاده کنیم ایستیو.
  2. برخی از فروشندگان CNI ابزارهای خود را فراتر از خط مشی های شبکه Kubernetes گسترش داده اند.
  3. توفین اورکا قابلیت مشاهده و اتوماسیون خط مشی های شبکه Kubernetes را فراهم می کند.

بسته Tufin Orca سیاست های شبکه Kubernetes را مدیریت می کند (و منبع اسکرین شات های بالا است).

اطلاعات اضافی

نتیجه

خط‌مشی‌های شبکه Kubernetes مجموعه خوبی از ابزارها را برای تقسیم‌بندی خوشه‌ها ارائه می‌دهند، اما بصری نیستند و ظرافت‌های زیادی دارند. به دلیل این پیچیدگی، من معتقدم بسیاری از خط مشی های خوشه ای موجود باگ هستند. راه حل های ممکن برای این مشکل شامل خودکارسازی تعاریف خط مشی یا استفاده از ابزارهای تقسیم بندی دیگر است.

امیدوارم این راهنما به رفع برخی از سوالات و حل مشکلاتی که ممکن است با آنها برخورد کنید کمک کند.

PS از مترجم

در وبلاگ ما نیز بخوانید:

منبع: www.habr.com

اضافه کردن نظر