Kubernetesにおけるサービスの公開

Reading time: 10 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

Kubernetesには、内部エンドポイントと外部エンドポイントの両方がアクセスできるようにサービスを公開するさまざまな方法があります。このKubernetesの設定は非常に重要であり、管理者が攻撃者にアクセスしてはいけないサービスへのアクセスを与える可能性があります。

自動列挙

K8sがサービスを公開する方法を列挙する前に、名前空間、サービス、イングレスをリストできる場合、次のコマンドを使用して公開されているすべてのものを見つけることができることを知っておいてください:

bash
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 プロキシを使用してアクセスできます:

bash
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/

このサービスにアクセスするために:

yaml
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 を実行する必要があります。

ClusterIPの一覧を表示します:

bash
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をリストします:

bash
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仕様の例:

yaml
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

もしyamlでnodePort指定しない場合(開かれるポートです)、30000–32767の範囲内のポートが使用されます

LoadBalancer

クラウドプロバイダーのロードバランサーを使用してサービスを外部に公開します。GKEでは、Network Load Balancerが起動され、サービスへのすべてのトラフィックを転送する単一のIPアドレスが提供されます。AWSでは、ロードバランサーが起動されます。

公開されたサービスごとにロードバランサーの料金が発生し、高額になる可能性があります。

すべてのロードバランサーをリストします:

bash
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 Balancerタイプのサービスによって公開され、一般的に外部Cloud Provider Load Balancerが使用されるときに使用されます。

それらを見つけるには、EXTERNAL-IPフィールドに値があるロードバランサーを確認してください。

クラスターに入るトラフィックが外部IP宛先IP)で、サービスポートである場合、サービスエンドポイントの1つにルーティングされますexternalIPsはKubernetesによって管理されず、クラスター管理者の責任です。

サービス仕様では、externalIPsは任意のServiceTypesと共に指定できます。以下の例では、"my-service"はクライアントによって"80.11.12.10:80"(externalIP:port)でアクセスできます。

yaml
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

From the docs: ExternalNameタイプのサービスは、サービスをDNS名にマッピングしますmy-servicecassandraのような典型的なセレクタにはマッピングしません。これらのサービスはspec.externalNameパラメータで指定します。

このサービス定義は、例えば、prodネームスペースのmy-serviceサービスをmy.database.example.comにマッピングします:

yaml
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サービスは値my.database.example.comを持つCNAMEレコードを返します。my-serviceへのアクセスは他のサービスと同様に機能しますが、重要な違いはリダイレクションがDNSレベルで行われるということです。

すべてのExternalNamesをリストします:

bash
kubectl get services --all-namespaces | grep ExternalName

Ingress

上記のすべての例とは異なり、Ingressはサービスの一種ではありません。代わりに、複数のサービスの前に位置し、「スマートルーター」として機能します、またはクラスターへのエントリーポイントです。

Ingressを使用すると、さまざまなことができます。また、異なる機能を持つ多くのタイプのIngressコントローラーがあります

デフォルトのGKE Ingressコントローラーは、HTTP(S) Load Balancerを自動的に作成します。これにより、パスベースおよびサブドメインベースのルーティングをバックエンドサービスに対して行うことができます。たとえば、foo.yourdomain.comのすべてをfooサービスに送信し、yourdomain.com/bar/パスの下のすべてをbarサービスに送信できます。

GKE上のL7 HTTP Load Balancerを使用したIngressオブジェクトのYAMLは次のようになります:

yaml
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

すべてのイングレスをリストします:

bash
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'

この場合、各情報を一つずつ取得して、より良く読む方が良いです:

bash
kubectl get ingresses --all-namespaces -o=yaml

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする