Reputation: 711
How to scan and verify the version of TLS for a website?
I was hunting for solutions which can automatically scan all the endpoint website domain in our company. SSL Labs had a manual online solution
https://www.ssllabs.com/ssltest/index.html
How can this feature be achieved programmatically?
Upvotes: 1
Views: 2593
Reputation: 319
I had same issue. Created free and open-source project on GitHub https://github.com/JocysCom/SslScanner, which contains:
Test_SSL_Support.cs have 'TestTCP' method which returns 'true' if connection supports specified protocol version:
static bool TestTCP(string host, int port, SslProtocols protocol, out bool connected)
{
var success = false;
var client = new TcpClient();
var asyncResult = client.BeginConnect(host, port, null, null);
// 5 seconds timeout.
connected = asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5));
// Connected.
if (connected)
{
var stream = client.GetStream();
// Don't dispose underlying stream.
using (var sslStream = new SslStream(stream, true, ValidateServerCertificate))
{
sslStream.ReadTimeout = 15000;
sslStream.WriteTimeout = 15000;
sslStream.AuthenticateAsClient(host, null, protocol, false);
result.UpdateFromSslStream(sslStream);
success = true;
}
client.EndConnect(asyncResult);
}
return success;
}
Test_SSL_Support.cs supports StartTLS protocol too. Look for method:
static bool TestStarTLS(string host, int port, SslProtocols protocol, out bool connected)
You can add multiple hosts and ports to Test_SSL_Support.bat for scan:
:: Test SSL/TLS.
CALL:PS www.google.com 443
:: Test StartTLS.
CALL:PS mail.jocys.com 110
Command line results are represented as:
172.217.169.4 www.google.com:443
Ssl2 = False | The client and server cannot communicate, because they do not possess a common algorithm
Ssl3 = False | The client and server cannot communicate, because they do not possess a common algorithm
Tls = True | Exchange = ECC-256 | Cipher = AES128 | Hash = SHA1
Tls11 = True | Exchange = ECC-256 | Cipher = AES128 | Hash = SHA1
Tls12 = True | Exchange = ECC-256 | Cipher = AES128 | Hash = SHA256
Tls13 = True | Exchange = ECC-256 | Cipher = AES256 | Hash = SHA384
62.30.149.144 mail.jocys.com:110
Ssl2 = False | The client and server cannot communicate, because they do not possess a common algorithm
Ssl3 = False | The client and server cannot communicate, because they do not possess a common algorithm
Tls = False | Authentication failed because the remote party has closed the transport stream.
Tls11 = False | Authentication failed because the remote party has closed the transport stream.
Tls12 = True | Exchange = ECC-384 | Cipher = AES256 | Hash = SHA384
Tls13 = False | Authentication failed because the remote party has closed the transport stream.
Upvotes: 1
Reputation: 52250
Use HttpClient... force it to use TLS 1.2... see if it fails... profit.
public async Task<bool> SupportsTls12(string url)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new HttpClient();
try
{
var response = await client.GetAsync(url);
return true;
}
catch(HttpRequestException)
{
return false;
}
}
If you find this gives you false positive/negatives, you may have to modify the exception handler to inspect the specific error that is returned. But this is the general idea.
Upvotes: 0
Reputation: 711
SSLLabsAPI seems to work
using SslLabsLib.Enums;
using SslLabsLib;
public static void TLSChecker(string urlString)
{
SslLabsClient client = new SslLabsClient();
// Get ipaddress and host
var analysis = client.GetAnalysis(urlString, 24, AnalyzeOptions.Publish);
Console.WriteLine(analysis.Host);
foreach (var item in analysis.Endpoints)
{
Console.WriteLine(item.IpAddress);
var endpointanalysis = client.GetCachedEndpointAnalysis(analysis.Host, IPAddress.Parse(item.IpAddress));
// get protocol list
foreach (var protocol in endpointanalysis.Details.Protocols)
{
Console.WriteLine(protocol.Id);
Console.WriteLine(protocol.Name);
Console.WriteLine(protocol.Version);
}
}
Upvotes: 0