Exposing Services in Kubernetes
Reading time: 7 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
Існує різні способи експонування сервісів у Kubernetes, щоб як внутрішні, так і зовнішні кінцеві точки могли до них отримати доступ. Ця конфігурація Kubernetes є досить критичною, оскільки адміністратор може надати доступ зловмисникам до сервісів, до яких вони не повинні мати доступ.
Automatic Enumeration
Перед тим, як почати перераховувати способи, які K8s пропонує для експонування сервісів публічно, знайте, що якщо ви можете перерахувати простори імен, сервіси та інгреси, ви можете знайти все, що експоновано публічно за допомогою:
kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
echo "Namespace: $ns"
kubectl get service -n "$ns"
kubectl get ingress -n "$ns"
echo "=============================================="
echo ""
echo ""
done | grep -v "ClusterIP"
# Remove the last '| grep -v "ClusterIP"' to see also type ClusterIP
ClusterIP
Служба ClusterIP є за замовчуванням службою Kubernetes. Вона надає вам службу всередині вашого кластера, до якої можуть отримати доступ інші додатки всередині вашого кластера. Зовнішнього доступу немає.
Однак до неї можна отримати доступ за допомогою Kubernetes Proxy:
kubectl proxy --port=8080
Тепер ви можете переходити через Kubernetes API, щоб отримати доступ до сервісів, використовуючи цю схему:
http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/
Наприклад, ви можете використовувати наступне URL:
http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/
щоб отримати доступ до цього сервісу:
apiVersion: v1
kind: Service
metadata:
name: my-internal-service
spec:
selector:
app: my-app
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
Цей метод вимагає, щоб ви запускали kubectl
як авторизований користувач.
Список всіх ClusterIPs:
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP
NodePort
Коли використовується NodePort, призначений порт стає доступним на всіх вузлах (які представляють віртуальні машини). Трафік, спрямований на цей конкретний порт, систематично перенаправляється на сервіс. Зазвичай цей метод не рекомендується через його недоліки.
Список усіх NodePort:
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort
Приклад специфікації NodePort:
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
spec:
selector:
app: my-app
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
Якщо ви не вкажете nodePort у yaml (це порт, який буде відкритий), буде використано порт у діапазоні 30000–32767.
LoadBalancer
Відкриває Сервіс зовні за допомогою балансувальника навантаження постачальника хмари. У GKE це запустить Network Load Balancer, який надасть вам одну IP-адресу, що буде пересилати весь трафік до вашого сервісу. У AWS це запустить Load Balancer.
Вам потрібно платити за LoadBalancer за кожен відкритий сервіс, що може бути дорого.
Список усіх LoadBalancers:
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer
External IPs
tip
Зовнішні IP-адреси відкриті службами типу Load Balancers і зазвичай використовуються, коли використовується зовнішній Cloud Provider Load Balancer.
Щоб їх знайти, перевірте навантажувачі з значеннями в полі EXTERNAL-IP
.
Трафік, який входить у кластер з зовнішнім IP (як цільовий IP), на порту служби, буде направлений на одну з кінцевих точок служби. externalIPs
не керуються Kubernetes і є відповідальністю адміністратора кластера.
У специфікації служби externalIPs
можуть бути вказані разом з будь-яким з ServiceTypes
. У наведеному нижче прикладі, "my-service
" може бути доступний клієнтами на "80.11.12.10:80
" (externalIP:port
)
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
externalIPs:
- 80.11.12.10
ExternalName
З документації: Сервіси типу ExternalName відображають Сервіс на DNS-ім'я, а не на типовий селектор, такий як my-service
або cassandra
. Ви вказуєте ці Сервіси за допомогою параметра spec.externalName
.
Це визначення Сервісу, наприклад, відображає Сервіс my-service
в просторі імен prod
на my.database.example.com
:
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
Коли ви шукаєте хост my-service.prod.svc.cluster.local
, служба DNS кластера повертає запис CNAME
зі значенням my.database.example.com
. Доступ до my-service
працює так само, як і з іншими службами, але з важливою різницею, що перенаправлення відбувається на рівні DNS, а не через проксування або пересилання.
Перерахуйте всі ExternalNames:
kubectl get services --all-namespaces | grep ExternalName
Ingress
На відміну від усіх наведених вище прикладів, Ingress НЕ є типом служби. Натомість, він знаходиться попереду кількох служб і діє як “розумний маршрутизатор” або точка входу у ваш кластер.
Ви можете робити багато різних речей з Ingress, і існує багато типів контролерів Ingress, які мають різні можливості.
Контролер Ingress за замовчуванням GKE створить для вас HTTP(S) Load Balancer. Це дозволить вам здійснювати маршрутизацію як на основі шляху, так і на основі піддомену до бекенд-служб. Наприклад, ви можете надіслати все на foo.yourdomain.com до служби foo, а все під шляхом yourdomain.com/bar/ до служби bar.
YAML для об'єкта Ingress на GKE з L7 HTTP Load Balancer може виглядати так:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: other
servicePort: 8080
rules:
- host: foo.mydomain.com
http:
paths:
- backend:
serviceName: foo
servicePort: 8080
- host: mydomain.com
http:
paths:
- path: /bar/*
backend:
serviceName: bar
servicePort: 8080
Список всіх вхідних точок:
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'
Хоча в цьому випадку краще отримувати інформацію про кожен окремо, щоб легше її читати:
kubectl get ingresses --all-namespaces -o=yaml
Посилання
- https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0
- https://kubernetes.io/docs/concepts/services-networking/service/
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.