Expondo Serviços no Kubernetes
Reading time: 8 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Existem diferentes maneiras de expor serviços no Kubernetes para que tanto endpoints internos quanto endpoints externos possam acessá-los. Esta configuração do Kubernetes é bastante crítica, pois o administrador pode dar acesso a atacantes a serviços que eles não deveriam conseguir acessar.
Enumeração Automática
Antes de começar a enumerar as maneiras que o K8s oferece para expor serviços ao público, saiba que se você pode listar namespaces, serviços e ingresses, pode encontrar tudo exposto ao público com:
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
Um serviço ClusterIP é o padrão do Kubernetes. Ele fornece um serviço interno no seu cluster que outros aplicativos dentro do seu cluster podem acessar. Não há acesso externo.
No entanto, isso pode ser acessado usando o Proxy do Kubernetes:
kubectl proxy --port=8080
Agora, você pode navegar pela API do Kubernetes para acessar serviços usando este esquema:
http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/
Por exemplo, você poderia usar a seguinte URL:
http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/
para acessar este serviço:
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
Este método requer que você execute kubectl
como um usuário autenticado.
Liste todos os 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
Quando NodePort é utilizado, uma porta designada é disponibilizada em todos os Nós (representando as Máquinas Virtuais). O tráfego direcionado a esta porta específica é então sistematicamente routed to the service. Normalmente, este método não é recomendado devido às suas desvantagens.
Liste todos os NodePorts:
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
Um exemplo de especificação 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 você não especificar o nodePort no yaml (é a porta que será aberta), uma porta na faixa de 30000–32767 será usada.
LoadBalancer
Expõe o Serviço externamente usando o balanceador de carga de um provedor de nuvem. No GKE, isso irá iniciar um Network Load Balancer que lhe dará um único endereço IP que encaminhará todo o tráfego para seu serviço. No AWS, ele lançará um Load Balancer.
Você tem que pagar por um LoadBalancer por serviço exposto, o que pode ser caro.
Liste todos os 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
IPs externos são expostos por serviços do tipo Load Balancers e geralmente são usados quando um Load Balancer de Provedor de Nuvem externo está sendo utilizado.
Para encontrá-los, verifique os load balancers com valores no campo EXTERNAL-IP
.
O tráfego que ingressa no cluster com o IP externo (como IP de destino), na porta do Serviço, será routado para um dos endpoints do Serviço. externalIPs
não são gerenciados pelo Kubernetes e são de responsabilidade do administrador do cluster.
Na especificação do Serviço, externalIPs
podem ser especificados junto com qualquer um dos ServiceTypes
. No exemplo abaixo, "my-service
" pode ser acessado por clientes em "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
Da documentação: Serviços do tipo ExternalName mapeiam um Serviço para um nome DNS, não para um seletor típico como my-service
ou cassandra
. Você especifica esses Serviços com o parâmetro spec.externalName
.
Esta definição de Serviço, por exemplo, mapeia o Serviço my-service
no namespace prod
para my.database.example.com
:
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
Ao procurar o host my-service.prod.svc.cluster.local
, o Serviço DNS do cluster retorna um registro CNAME
com o valor my.database.example.com
. Acessar my-service
funciona da mesma forma que outros Serviços, mas com a diferença crucial de que a redireção acontece no nível DNS em vez de via proxy ou encaminhamento.
Liste todos os ExternalNames:
kubectl get services --all-namespaces | grep ExternalName
Ingress
Ao contrário de todos os exemplos acima, Ingress NÃO é um tipo de serviço. Em vez disso, ele fica na frente de vários serviços e atua como um “roteador inteligente” ou ponto de entrada para o seu cluster.
Você pode fazer muitas coisas diferentes com um Ingress, e existem muitos tipos de controladores de Ingress que têm diferentes capacidades.
O controlador de ingress padrão do GKE irá criar um HTTP(S) Load Balancer para você. Isso permitirá que você faça roteamento baseado em caminho e subdomínio para serviços de backend. Por exemplo, você pode enviar tudo em foo.yourdomain.com para o serviço foo, e tudo sob o caminho yourdomain.com/bar/ para o serviço bar.
O YAML para um objeto Ingress no GKE com um L7 HTTP Load Balancer pode parecer assim:
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
Liste todos os ingressos:
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'
Embora neste caso seja melhor obter as informações de cada um individualmente para lê-las melhor:
kubectl get ingresses --all-namespaces -o=yaml
Referências
- 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
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.