通过Istio入口网关的TLS握手失败(tlsMode = passthrough)

时间:2020-09-25 00:32:14

标签: ssl openssl istio

从外部客户端到Kubernetes集群中的服务器的TLS握手失败。这是关于了解原因的原因。

我已将Istio入口网关配置为通过端口15433上接收的TLS,并将其路由到端口433上的服务器。

当客户端尝试进行TLS握手时,入口网关日志显示活动,但服务器日志或istio-proxy日志均未显示。

TLS客户端

openssl s_client \ 
        -connect [redacted]-[redacted].us-west-2.elb.amazonaws.com:15443 \ 
        -servername myservice.mynamespace \ 
        -CAfile /path/to/ca.cert \ 
        -cert /path/to/cert.pem \ 
        -key /path/to/cert.key <<< "Q"

日志

CONNECTED(00000006) 
140090868934296:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177: 
--- 
no peer certificate available 
--- 
No client certificate CA names sent 
--- 
SSL handshake has read 0 bytes and written 298 bytes 
--- 
New, (NONE), Cipher is (NONE) 
Secure Renegotiation IS NOT supported 
Compression: NONE 
Expansion: NONE 
No ALPN negotiated 
SSL-Session: 
    Protocol  : TLSv1.2 
    Cipher    : 0000 
    Session-ID:  
    Session-ID-ctx:  
    Master-Key:  
    Key-Arg   : None 
    PSK identity: None 
    PSK identity hint: None 
    SRP username: None 
    Start Time: 1600987862 
    Timeout   : 300 (sec) 
    Verify return code: 0 (ok) 

Istio入口网关日志:

"- - -" 0 - "-" "-" 298 0 1069 - "-" "-" "-" "-" "192.168.101.136:443" outbound|443||myservice.mynamespace.svc.cluster.local 192.168.115.141:42350 192.168.115.141:15443 192.168.125.206:23298 myservice.mynamespace - 

其中192.168.101.136是myservice pod的IP,而192.168.115.141是ingressgateway pod的IP。

基于IP,这意味着客户端连接已到达网关,网关似乎已应用了虚拟服务路由并记录了将其转发到Pod的情况。看起来很正常,只是Pod上的istio-proxy没有显示任何活动,也没有服务器记录日志(尽管服务器没有记录传输层发生的事件)。

由于以下端口转发的TLS握手成功,因此已经为TLS正确配置了服务器的AFAIK:

kubectl port-forward -n mynamespace service/myservice 4430:443 &
openssl s_client \
        -connect localhost:4430 \
        -CAfile /path/to/ca.cert \ 
        -cert /path/to/cert.pem \ 
        -key /path/to/cert.key <<< "Q"
# I get back a TLS session ID, looks good.

因此,这表明istio的网关或虚拟服务配置存在问题。

网关:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: mygateway
  namespace: mynamespace
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 15443
        name: tls-passthrough
        protocol: TLS
      tls:
        mode: PASSTHROUGH
      hosts:
      - "*"

虚拟服务:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myservice
  namespace: mynamespace
spec:
  hosts:
  - "*" 
  gateways:
  - mygateway
  tls:
    - match:
      - port: 15443
        sniHosts:
        - myservice.mynamespace
      route:
      - destination:
          host: myservice
          port:
            number: 443

Kubernetes服务:

apiVersion: v1
kind: Service
metadata:
  name: myservice
  namespace: mynamespace
  labels:
    app: myservice
spec:
  selector:
    app: myservice
  ports:
    - protocol: TCP
      port: 443
      targetPort: 443
      name: grpc-svc

更新: 实际上,来自客户端的TLS流量确实到达了服务器容器,我通过在服务器容器上执行tcpdump port 443并在运行openssl s_client命令时看到了数据包来确认这一点。不清楚为什么Pod上的istio-proxy没有显示出来,也不能解释握手失败的原因。

我注意到了别的东西。将-msg标志传递给openssl s_client时,我什么也没回来,在“ >>>”之后没有“ <<<”,但是tcpdump显示服务器pod将数据包发送回网关。

1 个答案:

答案 0 :(得分:2)

我的配置中有2个错误:

    我的Kubernetes服务配置中的
  • 。不幸的是,我的TCP端口443的名称为grpc-svc,这破坏了TLS直通。将该端口重命名为tcp-svc可解决问题。

  • 我不应该使用入口端口15443,这似乎是为其他目的保留的。在Ingressgateway上打开另一个端口9444,然后按照我在问题中配置端口15443的方式(即配置TLS直通)完全配置网关上的端口9444,然后将虚拟服务配置为与配置虚拟服务时完全一样,路由9444我的问题中的15433路由。

同时执行这两项操作,将允许外部客户端openssl s_client通过TLS成功将TLS握手通过握手传递到kubernetes服务。