I can successfully connect to a company server using openssl:
openssl s_client -connect {ip_address}:{tcp_port} -cert client.pem -key client.key -CAfile ca.cer
The output shows the negotiated protocol is TLS 1.2.
I'd like to implement this connection in C#. Here is my current attempt. Note that I provide the client's certificate and private key, but I does not check the server certificate:
var clientPrivateKey = RSA.Create();
clientPrivateKey.ImportFromPem(File.ReadAllText("client.key"));
var clientCertificate = new X509Certificate2("client.pem").CopyWithPrivateKey(clientPrivateKey);
var clientCertificates = new X509Certificate2Collection(clientCertificate);
using (var tcpClient = new TcpClient(ipAddress, tcpPort))
using (var sslStream = new SslStream(tcpClient.GetStream()))
{
sslStream.AuthenticateAsClient(new SslClientAuthenticationOptions
{
AllowRenegotiation = true,
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13,
CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
ClientCertificates = clientCertificates,
TargetHost = ipAddress, // ???
RemoteCertificateValidationCallback = (_, _, _, _) => true
});
}
Unfortunately sslStream.AuthenticateAsClient
throws this error:
Received an unexpected EOF or 0 bytes from the transport stream. (System.IO.IOException)
I have read everything about this problem on MSDN, StackOverflow etc. Some observations:
Although the openssl command line says the protocol is TLS 1.2, I tried other values, and also tried not setting the EnabledSslProtocols
value, but nothing helped. I also tried changing or omitting AllowRenegotiation
and CertificateRevocationCheckMode
, but that did not help either.
The TargetHost
value cannot be null, but I don't know what it should be. I tried an empty string, the CN from the server's certificate, even the server's IP address, but nothing helped. Interestingly, the openssl command line above says Can't use SSL_get_servername
, which is suspicious but I don't know what it means exactly.
-- Thank you for your help in advance!
UPDATE: I checked the traffic using tcpdump. In case of the C# code, there is a SYN/SYN-ACK/ACK, a FIN-ACK/ACK initiated by the server at 5 seconds, and a Client Hello
from the client at 30 seconds. The client not only waits for 30 seconds, but also tries to use TLS 1.0, whatever settings I use.