Exposing Services in Kubernetes

Impara l'hacking di AWS da zero a esperto con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks:

Ci sono diversi modi per esporre i servizi in Kubernetes in modo che entrambi gli endpoint interni ed esterni possano accedervi. Questa configurazione di Kubernetes è piuttosto critica in quanto l'amministratore potrebbe dare accesso a attaccanti a servizi a cui non dovrebbero poter accedere.

Enumerazione automatica

Prima di iniziare a enumerare i modi in cui K8s offre per esporre i servizi al pubblico, sappi che se puoi elencare i namespace, i servizi e gli ingressi, puoi trovare tutto ciò che è esposto al pubblico con:

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

Un servizio ClusterIP è il servizio predefinito di Kubernetes. Ti fornisce un servizio all'interno del tuo cluster a cui altre applicazioni all'interno del cluster possono accedere. Non c'è accesso esterno.

Tuttavia, è possibile accedervi utilizzando il Proxy di Kubernetes:

kubectl proxy --port=8080

Ora, puoi navigare attraverso l'API di Kubernetes per accedere ai servizi utilizzando questo schema:

http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/

Ad esempio, potresti utilizzare l'URL seguente:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

per accedere a questo servizio:

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

Questo metodo richiede di eseguire kubectl come un utente autenticato.

NodePort

Quando viene utilizzato NodePort, viene creato una porta designata su tutti i Nodi (che rappresentano le macchine virtuali). Il traffico diretto a questa porta specifica viene quindi instradato al servizio in modo sistematico. Tipicamente, questo metodo non è consigliato a causa dei suoi svantaggi.

Un esempio di specifica 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

Se non specifici il nodePort nel file yaml (è la porta che verrà aperta) verrà utilizzata una porta nell'intervallo 30000-32767.

LoadBalancer

Espone il servizio esternamente utilizzando un bilanciatore di carico del provider cloud. Su GKE, questo creerà un Network Load Balancer che ti fornirà un singolo indirizzo IP che inoltrerà tutto il traffico al tuo servizio.

Dovrai pagare un LoadBalancer per ogni servizio esposto, il che può diventare costoso.

ExternalName

Dalla documentazione: I servizi di tipo ExternalName mappano un servizio a un nome DNS, non a un selettore tipico come my-service o cassandra. Specifici questi servizi con il parametro spec.externalName.

Ad esempio, questa definizione di servizio mappa il servizio my-service nel namespace prod a my.database.example.com:

apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com

Quando si cerca l'host my-service.prod.svc.cluster.local, il servizio DNS del cluster restituisce un record CNAME con il valore my.database.example.com. L'accesso a my-service funziona allo stesso modo degli altri servizi, ma con la differenza cruciale che il reindirizzamento avviene a livello DNS anziché tramite proxy o inoltro.

Indirizzi IP esterni

Il traffico che entra nel cluster con l'IP esterno (come IP di destinazione), sulla porta del servizio, verrà instradato verso uno degli endpoint del servizio. Gli externalIPs non sono gestiti da Kubernetes e sono responsabilità dell'amministratore del cluster.

Nella specifica del servizio, gli externalIPs possono essere specificati insieme a uno dei ServiceTypes. Nell'esempio seguente, "my-service" può essere accessibile dai client su "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

Ingress

A differenza di tutti gli esempi precedenti, Ingress NON è un tipo di servizio. Invece, si trova di fronte a più servizi e agisce come un "router intelligente" o punto di ingresso nel tuo cluster.

Puoi fare molte cose diverse con un Ingress, e ci sono molti tipi di controller Ingress che hanno capacità diverse.

Il controller di ingress predefinito di GKE creerà un HTTP(S) Load Balancer per te. Questo ti permetterà di fare routing basato sia su percorsi che su sottodomini verso i servizi di backend. Ad esempio, puoi inviare tutto su foo.tuodominio.com al servizio foo, e tutto sotto il percorso tuodominio.com/bar/ al servizio bar.

Il YAML per un oggetto Ingress su GKE con un L7 HTTP Load Balancer potrebbe apparire così:

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

Riferimenti

Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks:

Last updated