我正在使用.Net(C#)gRPC构建示例客户端-服务器测试应用程序。 我正在使用DiDiSoft库在代码中生成SSL证书。 证书是使用“服务器”计算机名称生成的。
使用机器名连接服务器和客户端应用程序时,握手可以正常工作。 如果我使用IP地址,则不会。 在我的阅读中,不建议使用IPAddresses生成证书。 使用SSL证书设置gRPC连接时,我是否只能使用计算机名称?
设置证书的示例代码:
var serverKeypair = rsa.GenerateRsaKeyPair(KeyLength.Length4096);
serverKeypair.Private.Save(Path.Combine(certsPath, "server.key"));
X509Name serverCertificateProperties = new X509Name()
{
C = "US",
ST = "VA",
O = "SomeName",
OU = "gRPCAPI",
CN = "MACHINE-NAME",
};
var serverCert = Certificate.CreateCertificate(serverKeypair.Public,
newca.CACertificate.SubjectPublicKey,
newca.CAPrivateKey,
serverCertificateProperties,
newca.CAProperties,
null,
"01",
newca.CACertificate.SerialNumber,
true,
new[] { KeyUsages.DigitalSignature },
DateTime.Now, DateTime.Now.AddYears(1));
serverCert.Save(Path.Combine(certsPath, "server.crt"));
用于启动gRPC服务器的代码段:
// "Server" App
ServerServiceDefinition serverDef = new ServerDefinitionFoo();
var sslCredentials = GetCerts();
var server = new Server()
{
Services = { serverDef },
Ports = { new ServerPort("192.168.1.", port, sslCredentials) }
};
server.Start();
用于设置gRPC客户端的代码段:
// Client App
static SslCredentials GetSslCredentials()
{
var certsFolder = Path.Combine(Environment.CurrentDirectory, "Certs");
var cacert = File.ReadAllText(Path.Combine(certsFolder, "newca.crt"));
var cert = File.ReadAllText(Path.Combine(certsFolder, "client.crt"));
var key = File.ReadAllText(Path.Combine(certsFolder, "client.key"));
var keyPair = new KeyCertificatePair(cert, key);
var Creds = new SslCredentials(cacert, keyPair);
return Creds;
}
var sslCredentials = GetSslCredentials();
var channel = new Channel("MACHINE-NAME:30052", sslCredentials);
var apiProvider = new UtilitiesApi(new UtilitiesService.UtilitiesServiceClient(channel));
var retVal = apiProvider.SomeServiceCall("Test Data");
以上情况成功完成。
如果我更改以下代码段:
var channel = new Channel("192.168.1.9:30052", sslCredentials);
我在客户端上遇到以下异常:
Grpc.Core.RpcException:Status(StatusCode =“ Unavailable”, Detail =“无法连接到所有地址”, DebugException =“ Grpc.Core.Internal.CoreErrorDetailException: {“创建”:“ @ 1605192569.522000000”,“描述”:“无法选择 子频道”,“文件”
我在服务器控制台上(通过日志记录)收到以下错误消息。
E1112 09:49:29.510018 0 T:\ src \ github \ grpc \ workspace_csharp_ext_windows_x64 \ src \ core \ tsi \ ssl_transport_security.cc:1807: 找不到与服务器名称192.168.1.9匹配的内容。
启动客户端-服务器握手时,我应该能够使用IP地址吗?
谢谢JohnB
答案 0 :(得分:0)
这按预期工作,并且您的证书配置不正确。您遇到的问题很简单,就像您尝试创建与服务器的TLS连接一样,并且该服务器的名称与客户端期望的名称不同。因此,TLS连接失败-这是为了避免中间人攻击。
每当客户端想要创建TLS连接时,客户端都会使用URL中使用的名称(在您的情况下为计算机名称或IP地址),并对照服务器提供的证书中的规范名称进行检查。如果它们不匹配,则假定客户端正在与假服务器对话,并且连接被拒绝。
想象一下您想与服务器foo.com进行通信的情况,但是在连接之后,服务器将无法出示证书,证明它是真正的foo.com后端(基于您提供的信任根)。当然,正确的措施是停止连接,而不是开始将潜在的敏感数据(例如身份验证信息)发送到错误的服务器。