Istio:如何重定向到除 /.well-known/acme-challenge 之外的 HTTPS

Istio: How to redirect to HTTPS except for /.well-known/acme-challenge

我希望将作为 HTTP 进入我的集群的流量重定向到 HTTPS。但是,集群会收到来自数百个动态更改的域的请求(使用证书管理器创建新证书)。所以我希望重定向仅在 URI 没有前缀 /.well-known/acme-challenge

时发生

我正在使用监听 443 的网关和监听 80 的其他网关并将 HTTP 发送到 acme-solver 虚拟服务。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: default-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - site1.com
    port:
      name: https-site1.com
      number: 443
      protocol: HTTPS
    tls:
      credentialName: cert-site1.com
      mode: SIMPLE
  - hosts:
    - site2.com
    port:
      name: https-site2.com
      number: 443
      protocol: HTTPS
    tls:
      credentialName: cert-site2.com
      mode: SIMPLE
  ...
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: acme-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: acme-solver
  namespace: istio-system
spec:
  hosts:
  - "*"
  gateways:
  - acme-gateway
  http:
  - match:
    - uri:
        prefix: /.well-known/acme-challenge
    route:
    - destination:
        host: acme-solver.istio-system.svc.cluster.local
        port:
          number: 8089
  - redirect:
      authority: # Should redirect to https://$HOST, but I don't know how to get the $HOST

我如何使用 istio 做到这一点?

查看文档:

  • HTTP-01 质询只能在端口 80 上进行。允许客户端指定任意端口会降低质询的安全性,因此 ACME 标准不允许这样做。

解决方法:

  1. 请考虑使用 DNS-01 质询:

a) 只有当您的 DNS 供应商有 API 可用于自动化 updates.

时,使用 DNS-01 质询才有意义

b) 使用这种方法,您应该考虑 docs:

中所述的额外安全风险

优点: 您可以使用此质询来颁发包含通配符域名的证书。 即使您有多个网络服务器,它也能正常工作。

缺点: *在您的 Web 服务器上保留 API 凭据是有风险的。 您的 DNS 提供商可能不提供 API。 您的 DNS API 可能不提供有关传播时间的信息。

如前所述here

In order to be automatic, though, the software that requests the certificate will also need to be able to modify the DNS records for that domain. In order to modify the DNS records, that software will also need to have access to the credentials for the DNS service (e.g. the login and password, or a cryptographic token), and those credentials will have to be stored wherever the automation takes place. In many cases, this means that if the machine handling the process gets compromised, so will the DNS credentials, and this is where the real danger lies.


  1. 我还建议另一种使用一些简单的 nginx pod 的方法,它将所有 http 流量重定向到 https。

有一个关于 medium 的教程,您可以尝试使用 nginx 配置。

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
    server {
      listen 80 default_server;
      server_name _;
      return 301 https://$host$request_uri;
    }
---
apiVersion: v1
kind: Service
metadata:
  name: redirect
  labels:
    app: redirect
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: redirect
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redirect
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redirect
  template:
    metadata:
      labels:
        app: redirect
    spec:
      containers:
      - name: redirect
        image: nginx:stable
        resources:
          requests:
            cpu: "100m"
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /etc/nginx/conf.d
          name: config
      volumes:
      - name: config
        configMap:
          name: nginx-config

此外,您必须更改虚拟服务以将除 prefix: /.well-known/acme-challenge 之外的所有流量发送到 nginx。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: acme-solver
  namespace: istio-system
spec:
  hosts:
  - "*"
  gateways:
  - acme-gateway
  http:
  - name: "acmesolver"
    match:
    - uri:
        prefix: /.well-known/acme-challenge
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        port:
          number: 8089
  - name: "nginx"
    route:
    - destination:
        host: nginx