.net - 为什么 C# Google.Cloud.Firestore 库无法与企业 MITM 防火墙连接?
问题描述
来自库的特定错误消息
CompletedListGrpc.Core.RpcException:状态(状态代码=不可用,详细信息=“连接失败”)
- 我特别指的是这个库:https ://github.com/googleapis/google-cloud-dotnet/tree/master/apis/Google.Cloud.Firestore
- 我特别遇到了 google-cloud-firestore 服务的问题(尽管该问题可能发生在另一个依赖库中,也许是身份验证)
- 有问题的防火墙是 Palo Alto Networks。它具有安装在企业工作站上且受信任的企业证书。防火墙本质上充当 MITM 来解密流量以更深入地分析 TLS 流量。
当 firestore.googleapis.com 的防火墙 MITM 功能被禁用时,该库可以正常工作。启用 MITM 功能后,它不起作用。
子问题:
1)图书馆代码是否有硬编码证书检查?(我找不到一个)
public static gaxgrpc::ServiceEndpoint DefaultEndpoint { get; } = new gaxgrpc::ServiceEndpoint("firestore.googleapis.com", 443);
- 对证书进行硬编码是没有意义的,因为证书是更新的,有时旧的证书会被吊销。
- grpc 是非常标准的,并且无法被 Google 共享(参见https://grpc.io/)。
- 假设 grpc 不包含下游依赖项的显式证书是合理的
- 如果 firestore 要声明一个证书,那么可以合理地假设这将在这行代码以及 URL 上完成
2a) .Net Framework 是否自动信任 Windows 信任库中的证书?是否需要任何代码才能完成这项工作?
.Net Framework 似乎适用于 Windows 证书存储 - 请参阅https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/working-with-certificates
2b)也许证书只是受信任的,但交互式用户,而不是整个机器,因此服务帐户看不到该证书 - 我会检查这个......
3)如果这是“连接失败”的原因,图书馆是否会有关于证书的特定错误?
解决方案
这可能是 GRPC 和 Windows 证书存储之间的问题。无论这是 GRPC(而不是 .Net)的基本问题还是由于在不同的帐户下运行它,将防火墙的正确根 CA 硬编码到应用程序中肯定会让您完全控制。
您可能能够覆盖 DefaultEndpoint/Channel 以使用您自己的 ServicePoint,其中还包括硬编码证书
var cacert = File.ReadAllText(@"../ca.crt");
var clientcert = File.ReadAllText(@"../client.crt");
var clientkey = File.ReadAllText(@"../client.key");
var ssl = new SslCredentials(cacert, new KeyCertificatePair(clientcert, clientkey));
var channel = new Channel("firestore.googleapis.com", 443, ssl);
//etc..
创建您自己的端点,然后显式提供它,以便它覆盖 DefaultEndpoint。这是您将使用您的频道调用的函数。(见https://github.com/googleapis/google-cloud-dotnet/blob/master/apis/Google.Cloud.Firestore.V1/Google.Cloud.Firestore.V1/FirestoreClient.cs#L550)
public static FirestoreClient Create(grpccore::Channel channel, FirestoreSettings settings = null)
{
gax::GaxPreconditions.CheckNotNull(channel, nameof(channel));
return Create(new grpccore::DefaultCallInvoker(channel), settings);
}
另外,好好看看 SslCredentialsTest 代码 - https://github.com/grpc/grpc/blob/master/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
注意:通常会使用 s_channelPool 创建一个通道。如果您手动创建它,它可能不会使用池 - 可能没有办法做到这一点。这对你来说可能是也可能不是问题。
您可以扩展它以在运行时按名称从 Windows 证书存储中手动读取公共证书信息,选择最新的。这意味着您可以使用 app.config 分配证书的 CN 以从 Windows 证书存储区获取,然后您无需手动发送软件的更新版本。
此链接似乎表明默认情况下“公共受信任的根”是受信任的:https ://forum.predix.io/questions/30875/event-hub-c-client-how-to-deal-with-the-tls-证书.html
var channel = new Channel("greeter.googleapis.com", new SslCredentials()); // Use publicly trusted roots.
这意味着尽管 firestore 没有“硬编码”的特定证书,但它通常不会与 Windows 证书存储集成,因此任何自定义安装的根 CA 都不受信任。
更仔细地查看库源代码 [ https://github.com/googleapis/gax-dotnet/blob/master/Google.Api.Gax.Grpc/ChannelPool.cs]:
public Channel GetChannel(ServiceEndpoint endpoint, IEnumerable<ChannelOption> channelOptions)
{
GaxPreconditions.CheckNotNull(endpoint, nameof(endpoint));
var credentials = _lazyScopedDefaultChannelCredentials.Value.ResultWithUnwrappedExceptions();
return GetChannel(endpoint, channelOptions, credentials);
}
凭据参数是自动填充的,在 , 之后_lazyScopedDefaultChannelCredentials
,GoogleCredential.GetApplicationDefaultAsync()
我们最终CreateDefaultCredentialAsync
会指向您的 Google 服务文件,该文件可能是您从某处的 firebase 下载的。
笔记:
这个答案很有可能只会导致自定义客户端凭据,而不是为自定义服务器端根 CA 提供硬编码凭据的能力。
推荐阅读
- android - Androidx MutliDex:一个.dex文件中的方法引用数不能超过64K
- python - Matplotlib / Imshow / 透明层无处不在,但某些点
- tfs - 有没有一种快速的方法来添加带有子链接的工作项?
- wordpress - 在用户创建时添加自定义字段
- django - 在 Django 中显示来自 ForeignKey 的对象时出现问题
- angular - Angular 2 - 延迟加载组件的路由器实例
- python - 有没有办法让 tkinter 按钮没有圆角
- c++ - C++ 构造函数具有内部链接但未定义 [-Wundefined-internal]
- flutter - 在键盘可见时执行 Navigator.pop() 会导致渲染 flex 错误
- javascript - 显示错误消息时更改 div 的大小