Hyperledger Fabric 网络配置问题

时间:2021-02-17 12:15:48

标签: hyperledger-fabric hyperledger

关于 Hyperledger Fabric 中的 SAN 和 SNI,我想澄清两件事:

a) 启用双向 TLS(具有客户端身份验证的 TLS)时,客户端证书中的通用名称 (CN) 或主题备用名称 (SAN) 是否由服务器验证? (例如,通过解析 DNS 名称并将连续的 IP 地址与客户端的 IP 地址(TCP/IP 连接源)进行比较)?

我们已经测试了这个场景,发现无论是否启用客户端身份验证,作为服务器的对等方都会验证 TLS 证书哈希。以下是支持我们结论的对等日志示例:

2021-02-16 08:54:17.491 UTC [common.deliver] Handle -> DEBU 660f7 Attempting to read seek info message from 10.250.26.32:46320
2021-02-16 08:54:17.491 UTC [common.deliver] deliverBlocks -> WARN 660f8 error parsing envelope from 10.250.26.32:46320: **claimed TLS cert hash is** [235 124 10 219 135 57 10 64 94 166 44 162 123 25 91 195 202 31 164 34 51 5 12 238 77 39 197 171 135 246 12 244] **but actual TLS cert hash is** [185 32 246 230 116 37 63 240 4 9 236 246 210 42 59 45 198 22 209 194 183 117 64 137 153 68 27 56 143 39 211 118]
2021-02-16 08:54:17.492 UTC [orderer.common.server] func1 -> DEBU 660f9 Closing Deliver stream
2021-02-16 08:54:17.492 UTC [comm.grpc.server] 1 -> INFO 660fa streaming call completed grpc.service=orderer.AtomicBroadcast grpc.method=Deliver grpc.peer_address=10.250.26.32:46320 grpc.peer_subject="CN=proxy,OU=peer,O=Hyperledger,ST=North Carolina,C=US" grpc.code=OK grpc.call_duration=239.612µs

我们还在 github 上发现了一个据称对这种行为负责的源代码 (https://github.com/hyperledger/fabric/blob/master/internal/pkg/comm/util.go):

// mutualTLSBinding enforces the client to send its TLS cert hash in the message,
// and then compares it to the computed hash that is derived
// from the gRPC context.
// In case they don't match, or the cert hash is missing from the request or
// there is no TLS certificate to be excavated from the gRPC context,
// an error is returned.
func mutualTLSBinding(ctx context.Context, claimedTLScertHash []byte) error {
if len(claimedTLScertHash) == 0 {
return errors.Errorf("client didn't include its TLS cert hash")
}
actualTLScertHash := ExtractCertificateHashFromContext(ctx)
if len(actualTLScertHash) == 0 {
return errors.Errorf("client didn't send a TLS certificate")
}
if !bytes.Equal(actualTLScertHash, claimedTLScertHash) {
return errors.Errorf("claimed TLS cert hash is %v but actual TLS cert hash is %v", claimedTLScertHash, actualTLScertHash)
}
return nil
}

是否可以关闭此验证?您对我们如何在组织之间使用 gRPC 反向代理配置 HLF 网络(用于传入连接)有任何建议。在我们的测试中,我们假设代理作为客户端使用由 HLF 组织(对等组织)的 CA 颁发的自己的证书?

b) 1.4.1 版上的结构对等点是否支持 SNI(服务器名称指示器)?问题是是否可以使用代理在单个 IP 上托管多个 https 服务器?

我们已经使用 nginx 代理对此进行了测试,这部分通信似乎有效。但问题是,作为客户端的对等方是否会将 SNI 发送到服务器(在我们的例子中是 nginx 代理)以通知它它的目标是什么 DNS?多亏了它,我们可以仅使用 IP 地址在代理上运行许多虚拟服务器。

1 个答案:

答案 0 :(得分:0)

a) 当然不是,当客户端到达时,服务器不会验证客户端证书 SAN 或 CN。

您收到的错误是从应用层 (Fabric) 内部调用的,因此这意味着您实际上通过了 TLS 握手。

返回此错误可能是因为:

  1. 双向 TLS(客户端身份验证)已在对等本地配置中打开。当双向 TLS 被打开时,Fabric 客户端在它发送给对等方的请求中发送其 TLS 证书哈希,对等方检查 TLS 哈希是否与它从流中检测到的 TLS 证书的哈希匹配。这样做是为了防止重放攻击,该攻击将使恶意对等方重复使用相同的请求来向对等方请求块,而恶意对等方没有资格接收这些块。
  2. 您的对等方位于 TLS 终止代理之后。在这种情况下,对等方会收到来自代理而非客户端的 TLS 握手,并且代理具有不同的 TLS 证书,因此会拒绝该证书。
<块引用>

您对我们如何在组织之间使用 gRPC 反向代理配置 HLF 网络(用于传入连接)有任何建议。

您需要您的代理在“直通模式”下工作(使用您最喜欢的代理在谷歌上搜索 TLS 直通会产生结果)。

b)

<块引用>

1.4.1 版本上的结构对等点是否支持 SNI(服务器名称指示器)?问题是是否可以使用代理在单个 IP 上托管多个 https 服务器?

如果你的反向代理支持,你可以这样做,它与 Fabric 无关。您所需要的只是您的代理能够读取 TLS 握手的客户端问候中的 SNI,并在不终止 TLS 会话的情况下路由到正确的端口/主机。