1

最近,我一直在为基于物联网的项目评估不同的 API 网关 (API GW) 选项。这样做的目的是找到一个足够好的解决方案来执行设备和 API GW 的相互 TLS (mTLS) 身份验证。

我尝试过的大多数解决方案似乎都在 TLS 握手期间执行 mTLS,如此处所示。所以这就是我所理解的OSI 第 4 层 (TCP/IP)身份验证方法。

但是,Kong API 网关似乎在OSI 第 7 层(应用程序)上执行此操作。基本上,在 TLS 握手阶段没有客户端身份验证,而是应用层验证对等证书。因此它能够发送带有 401 状态和一些有效负载的响应(如果 TLS 握手失败,这是不可能的)。例子

√ poc-mtls-local-env % make test-fail-wrong-cert                              master 
curl -v --cacert certs/gen/ca-chain.crt \
        --key certs/gen/device.key \
        --cert certs/gen/device.crt \
        https://mtls.auth.local.com/echo
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to mtls.auth.local.com (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: certs/gen/ca.crt
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=NY; L=NYC; O=Sample; OU=UDS; CN=local.com
*  start date: Jul 29 12:10:25 2021 GMT
*  expire date: Jul 29 12:10:25 2022 GMT
*  subjectAltName: host "mtls.auth.local.com" matched cert's "mtls.auth.local.com"
*  issuer: C=US; ST=NY; O=Sample; OU=UDS; CN=Sample Intermediate CA; emailAddress=it@sample.com
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fc0dd808200)
> GET /echo HTTP/2
> Host: mtls.auth.local.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 401 
< date: Tue, 10 Aug 2021 06:46:13 GMT
< content-type: application/json; charset=utf-8
< content-length: 49
< x-kong-response-latency: 4
< server: kong/2.4.1.1-enterprise-edition
< 
* Connection #0 to host mtls.auth.local.com left intact
{"message":"TLS certificate failed verification"}* Closing connection 0

我们可以清楚地看到请求成功通过了 TLS 握手,应用层形成了 401 响应{"message": "TLS certificate failed verification"}

这让我想到了以下几个问题:

  • 形式上来说,Kong在这里做的也可以叫mTLS吗?
  • 这种方法有什么潜在的陷阱吗?
4

1 回答 1

3

我尝试过的大多数解决方案似乎都在 TLS 握手期间执行 mTLS,如此处所示。所以这就是我所理解的 OSI 第 4 层 (TCP/IP) 身份验证方法。

由于 TLS 在 OSI 第 4 层之上,因此身份验证也在第 4 层之上。但除了 OSI 层(无论如何,这与今天在第 4 层之上的现实还不够匹配),您基本上会问相互身份验证发生在什么阶段。

TLS 中的相互身份验证分两个阶段进行:请求客户端证书和验证证书是否符合要求。请求证书总是在 TLS 握手中完成,尽管它不需要是连接的初始 TLS 握手。

验证证书可以在 TLS 握手内部、外部或两者的组合中完成。通常在握手中检查证书是由某个受信任的证书颁发机构颁发的,但对特定主题的进一步检查可能是特定于应用程序的,因此将在应用程序内部的 TLS 握手之后完成。但也可能是在 TLS 握手内部或外部完成了完整的验证。

接受 TLS 握手内的任何证书并仅在握手之外验证证书,其优点是可以在已建立的 TLS 连接内向客户端返回有用的错误消息。TLS 握手中的验证错误反而会导致神秘错误,例如握手错误警报或只是关闭连接,这对调试问题没有多大帮助。

于 2021-08-10T07:41:18.417 回答