Step 2: Running Scan Commands Against a Server¶
Every type of scan that SSLyze can run against a server (supported cipher suites, Heartbleed, etc.) is
represented by a ScanCommand
. Once a ScanCommand
is run against a server, it returns a “result” object with
attributes containing the results of the scan command.
All the available ScanCommands
and corresponding results are described in Appendix: Scan Commands.
The main class for running these commands is the Scanner
class, which uses a pool of workers to run
ScanCommand
concurrently. It is very fast when scanning a large number of servers, and it has a rate-limiting
mechanism to avoid DOS-ing a single server against which multiple ScanCommand
are run at the same time.
The commands can be queued by passing a ServerScanRequest
to the Scanner.queue_scan()
method.
The results can later be retrieved using the Scanner.get_results()
method, which returns an iterable of
ServerScanResult
. Each result is returned as soon as the server scan was completed.
Basic Example¶
A simple example on how to run some scan commands follows:
def basic_example() -> None:
# Define the server that you want to scan
server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup("www.google.com", 443)
# Do connectivity testing to ensure SSLyze is able to connect
try:
server_info = ServerConnectivityTester().perform(server_location)
except ConnectionToServerFailed as e:
# Could not connect to the server; abort
print(f"Error connecting to {server_location}: {e.error_message}")
return
# Then queue some scan commands for the server
scanner = Scanner()
server_scan_req = ServerScanRequest(
server_info=server_info, scan_commands={ScanCommand.CERTIFICATE_INFO, ScanCommand.SSL_2_0_CIPHER_SUITES},
)
scanner.queue_scan(server_scan_req)
# Then retrieve the results
for server_scan_result in scanner.get_results():
print(f"\nResults for {server_scan_result.server_info.server_location.hostname}:")
# SSL 2.0 results
ssl2_result = server_scan_result.scan_commands_results[ScanCommand.SSL_2_0_CIPHER_SUITES]
print(f"\nAccepted cipher suites for SSL 2.0:")
for accepted_cipher_suite in ssl2_result.accepted_cipher_suites:
print(f"* {accepted_cipher_suite.cipher_suite.name}")
# Certificate info results
certinfo_result = server_scan_result.scan_commands_results[ScanCommand.CERTIFICATE_INFO]
print("\nCertificate info:")
for cert_deployment in certinfo_result.certificate_deployments:
print(f"Leaf certificate: \n{cert_deployment.received_certificate_chain_as_pem[0]}")
Advanced Usage¶
The following script provides an example of running scan commands against multiple servers, and processing the results:
def main() -> None:
# First validate that we can connect to the servers we want to scan
servers_to_scan = []
for hostname in ["cloudflare.com", "google.com"]:
server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(hostname, 443)
try:
server_info = ServerConnectivityTester().perform(server_location)
servers_to_scan.append(server_info)
except ConnectionToServerFailed as e:
print(f"Error connecting to {server_location.hostname}:{server_location.port}: {e.error_message}")
return
scanner = Scanner()
# Then queue some scan commands for each server
for server_info in servers_to_scan:
server_scan_req = ServerScanRequest(
server_info=server_info, scan_commands={ScanCommand.CERTIFICATE_INFO, ScanCommand.SSL_2_0_CIPHER_SUITES},
)
scanner.queue_scan(server_scan_req)
# Then retrieve the result of the scan commands for each server
for server_scan_result in scanner.get_results():
print(f"\nResults for {server_scan_result.server_info.server_location.hostname}:")
# Scan commands that were run with no errors
try:
ssl2_result = server_scan_result.scan_commands_results[ScanCommand.SSL_2_0_CIPHER_SUITES]
print(f"\nAccepted cipher suites for SSL 2.0:")
for accepted_cipher_suite in ssl2_result.accepted_cipher_suites:
print(f"* {accepted_cipher_suite.cipher_suite.name}")
except KeyError:
pass
try:
certinfo_result = server_scan_result.scan_commands_results[ScanCommand.CERTIFICATE_INFO]
print("\nCertificate info:")
for cert_deployment in certinfo_result.certificate_deployments:
print(f"Leaf certificate: \n{cert_deployment.received_certificate_chain_as_pem[0]}")
except KeyError:
pass
# Scan commands that were run with errors
for scan_command, error in server_scan_result.scan_commands_errors.items():
print(f"\nError when running {scan_command}:\n{error.exception_trace}")