无法通过 Ingress Nginx 控制器进行 SSL 传递

问题描述

我有一个 Java Spring Boot Application 并且我已将服务器配置为在 SSL 上运行,这是强制性的。

server:
  port: 8443
  ssl:
    enabled: true
    key-store-type: pkcs12
    key-store: ${KEYSTORE}
    key-password: ${KEYSTORE_PASSWORD}
    key-store-password: ${KEYSTORE_PASSWORD}
    client-auth: need

我已经从 LetsEncrypt 证书为我的域 *.kahootali.com 创建了一个证书,并通过运行为密钥库创建了一个 p12 文件

openssl pkcs12 -export -CAfile ca.crt -in cert.pem -inkey key.pem -certfile cert.pem -out kstore.p12

我想使用 Ingress Nginx Controller 在 Kubernetes 上公开它,所以我创建了秘密

kubectl create secret generic store --from-file=kstore.p12

我已经部署了应用程序,可以看到 deployment files,,当我将本地 8443 端口转发到其服务的 8443 并运行时

curl -iv --cacert ca.crt --cert mediator_cert.pem --key mediator_key.pem --resolve 'spring-app.kahootali.com:8443:127.0.0.1' https://spring-app.kahootali.com:8443/

它工作正常并返回

* Added spring-app.kahootali.com:8444:127.0.0.1 to DNS cache
* Hostname spring-app.kahootali.com was found in DNS cache
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to spring-app.kahootali.com (127.0.0.1) port 8444 (#0)
* ALPN,offering h2
* ALPN,offering http/1.1
* successfully set certificate verify locations:
*   CAfile: ca.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT),TLS handshake,Client hello (1):
* TLSv1.3 (IN),Server hello (2):
* TLSv1.2 (IN),Certificate (11):
* TLSv1.2 (IN),Server key exchange (12):
* TLSv1.2 (IN),Request CERT (13):
* TLSv1.2 (IN),Server finished (14):
* TLSv1.2 (OUT),Certificate (11):
* TLSv1.2 (OUT),Client key exchange (16):
* TLSv1.2 (OUT),CERT verify (15):
* TLSv1.2 (OUT),TLS change cipher,Client hello (1):
* TLSv1.2 (OUT),Finished (20):
* TLSv1.2 (IN),Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN,server did not agree to a protocol
* Server certificate:
*  subject: CN=*.kahootali.com
*  start date: Feb 11 10:27:47 2021 GMT
*  expire date: May 12 10:27:47 2021 GMT
*  subjectAltName: host "spring-app.kahootali.com" matched cert's "*.kahootali.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: spring-app.kahootali.com:8444
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 404 
HTTP/1.1 404 
< X-Application-Context: application:8443
X-Application-Context: application:8443
< Content-Type: application/json;charset=UTF-8
Content-Type: application/json;charset=UTF-8
< transfer-encoding: chunked
transfer-encoding: chunked
< Date: Sun,14 Feb 2021 14:29:47 GMT
Date: Sun,14 Feb 2021 14:29:47 GMT

< 
* Connection #0 to host spring-app.kahootali.com left intact
{"timestamp":1613312987350,"status":404,"error":"Not Found","message":"No message available","path":"/"}

但是当我为它创建一个 Ingress 并通过 ssl-passthrough 时

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
Metadata:
  name: spring-monitoring-app
  labels:
    app: spring-monitoring-app
  annotations:
    ingress.kubernetes.io/force-ssl-redirect: "true"
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: Nginx
    Nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  rules:
    - host: spring-app.kahootali.com
      http:
        paths:
          - path: /
            backend:
              serviceName: spring-monitoring-app
              servicePort: http
  tls:
    - hosts:
      - spring-app.kahootali.com
      secretName: tls-cert

它在浏览器和应用调试级别的日志中给出 ERR_BAD_SSL_CLIENT_AUTH_CERT,它给出

Error during SSL handshake
java.io.IOException: EOF during handshake.
The SNI host name extracted for this connection was [spring-app.kahootali.com]
Handshake Failed during wrap
javax.net.ssl.SSLHandshakeException: Empty server certificate chain

解决方法

我发布我的评论是为了提高知名度:

根据 the docs SSL Passthrough 功能默认处于禁用状态。为了启用它,您需要使用 --enable-ssl-passthrough 标志启动 nginx-ingress 控制器。确保你没有忘记它。

您还可以查看此 troubleshooting steps 以验证您的 nginx-ingress 控制器 配置。

如果有帮助,请告诉我。