Korzen
Bot Protection

Kubernetes

Kubernetes 上のアプリから Bot Protection を使います。Secret としての API key、ロードバランサーと ingress-nginx を通した訪問者の IP、egress を説明します。

Kubernetes では、サーバーからの呼び出しについて 3 つの点が変わります。API key をどこに置くか、訪問者のアドレスをロードバランサーと ingress の先までどう保つか、そして Pod がそもそも korzen.dev に到達できるかどうかです。呼び出しそのものはフレームワーク次第なので、お使いのスタックのガイドを参照してください。

キー

API key はイメージや ConfigMap には入れず、必ず Secret に保管し、環境変数としてコンテナに渡してください。

kubectl create secret generic korzen --from-literal=api-key=ak_your_key
# deployment.yaml, in your app's container
env:
  - name: KORZEN_API_KEY
    valueFrom:
      secretKeyRef:
        name: korzen
        key: api-key

訪問者の IP

デフォルトでは、クラウドのロードバランサーが訪問者を自分のアドレスの裏に隠してしまい、ingress も同様です。これを防ぐ設定が 2 つあります。ingress コントローラーの Service に externalTrafficPolicy: Local を設定することと、ロードバランサーが追加するヘッダーを ingress-nginx に信頼させることです。こうすると、アプリケーションは ingress-nginx が設定する X-Real-IP か、X-Forwarded-For の最後の値を読めます。Cloudflare の背後なら CF-Connecting-IP です。

# The ingress controller's Service: keep the visitor's address on the way in.
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
# ingress-nginx's ConfigMap: trust the load balancer in front, pass the address on.
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
  use-forwarded-headers: "true"     # only if a load balancer you control is in front
  compute-full-forwarded-for: "true"
  # use-proxy-protocol: "true"      # instead, if your cloud's load balancer speaks PROXY protocol

Egress

クラスターが namespace からの外向きトラフィックをデフォルトでブロックしている場合は、Pod がポート 443 に到達できるよう許可する必要があります。

# Only if your cluster blocks egress by default: let the app reach HTTPS.
# A plain NetworkPolicy matches addresses, not names, and korzen.dev answers from
# Cloudflare's ranges; with Cilium, an FQDN rule can name korzen.dev itself.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-egress-https
spec:
  podSelector:
    matchLabels:
      app: shop
  policyTypes: [Egress]
  egress:
    - ports:
        - port: 443
          protocol: TCP
    - ports:
        - port: 53
          protocol: UDP

運用

  • HTTP クライアントは Pod ごとに 1 つ、接続を維持して使います。レプリカごとに接続が開かれますが、問題ありません。
  • readiness probe や liveness probe を Bot Protection に依存させないでください。Bot Protection が遅延しているときも、Pod はサービスを続け、fail-open で動く必要があります。
  • SDK のタイムアウトは、クラスターの所在地を基準に選びます。米国西部のクラスターなら約 300 ms が必要です。

よくある間違い

  • ingress 自身のアドレスを訪問者のアドレスとして送る。すべての判定が 1 つの IP を共有し、Bot Protection にはとても忙しい訪問者が 1 人いるように見えます。
  • 前段に自分で管理するものが何もないのに use-forwarded-headers をオンにする。訪問者が X-Forwarded-For を書き込み、自分のアドレスを好きに選べてしまいます。
  • キーを ConfigMap に入れる、またはイメージに埋め込む。namespace やレジストリの読み取り権限を持つ人なら誰でも見られてしまいます。