Introduction to SSL Labs
SSL Labs, operated by Qualys, is the industry-standard suite of tools for assessing the security configuration of SSL/TLS web servers. Since its inception, it has become the de facto reference point for developers, system administrators, and security engineers who need to verify that their cryptographic deployments meet modern security expectations. The platform combines a free public web interface, a REST API, command-line tooling, and a library of documentation that together form a complete assessment ecosystem.
At its core, SSL Labs answers a simple but critical question: is my server's TLS configuration secure, and does it follow current best practices? The answer is delivered as a letter grade from A+ to F, accompanied by a detailed breakdown of certificate validity, protocol support, cipher strength, and known vulnerabilities. This tutorial walks through what SSL Labs measures, how to set up automated scanning, how to interpret results, and how to remediate common issues.
Why SSL/TLS Assessment Matters
TLS is the backbone of trust on the web. A misconfigured server can expose users to downgrade attacks, man-in-the-middle interception, or outright decryption of supposedly private traffic. The threat landscape evolves continuously — protocols that were considered safe a decade ago, such as SSLv3 and TLS 1.0, are now deprecated, and cipher suites once thought robust have fallen to advances in cryptanalysis.
Regular assessment matters for several reasons:
- Compliance: PCI DSS, HIPAA, and GDPR-aligned frameworks require demonstrable encryption controls.
- Browser trust: Modern browsers actively warn users away from sites with weak TLS configurations.
- Vulnerability management: High-profile flaws like Heartbleed, POODLE, BEAST, and ROBOT were all detectable through configuration review.
- Performance: Modern cipher suites and protocols such as TLS 1.3 reduce handshake latency.
- Client compatibility: Understanding which clients can connect helps balance security with reach.
Understanding the SSL Labs Grading Model
The SSL Labs grading algorithm evaluates a server across multiple dimensions and produces a composite score. The grade is not a simple average — it is the result of weighted scoring with cap and bonus rules. Understanding this model helps you prioritize remediation efforts.
Key Assessment Categories
- Certificate: Validates chain trust, signature algorithm, key strength, expiration, hostname match, and revocation status.
- Protocol Support: Checks which TLS/SSL protocol versions are enabled and whether deprecated versions are present.
- Cipher Strength: Evaluates the strongest and weakest cipher suites negotiated, weighted by key exchange parameters.
- Key Exchange: Assesses the strength of the key exchange mechanism, including forward secrecy support.
- Vulnerabilities: Tests for known issues including POODLE, BEAST, CRIME, BREACH, Heartbleed, ROBOT, DROWN, and TLS_FALLBACK_SCSV.
Grade Modifiers
The base score is derived from the categories above, but several modifiers can raise or lower the final grade:
- Servers supporting only TLS 1.2 and 1.3 with strong ciphers and forward secrecy receive an A.
- An A+ requires HTTP Strict Transport Security (HSTS) with a sufficiently long max-age value.
- Servers vulnerable to known attacks are capped at F regardless of other strengths.
- Servers supporting TLS 1.0 or 1.1 are capped at B under current criteria.
- Weak key sizes (e.g., RSA below 2048 bits) cap the grade at B or lower.
Using the SSL Labs Web Interface
The simplest way to begin is the public scanner at https://www.ssllabs.com/ssltest/. Enter a hostname, optionally disable public results, and submit. The scan typically takes one to three minutes and produces a detailed report.
The report is organized into collapsible sections. The top of the page shows the overall grade and a summary chart of protocol and cipher support. Below that, you will find:
- Authentication details, including the full certificate chain and trust paths to common root stores.
- Per-protocol configuration tables showing which cipher suites are offered and in what order.
- Handshake simulation results for dozens of real-world clients, from modern browsers to legacy Java runtimes.
- Protocol details including session resumption, OCSP stapling, and ALPN support.
- Vulnerability findings with severity indicators and remediation guidance.
Automating Scans with the SSL Labs API
For continuous monitoring, the SSL Labs REST API is the preferred tool. The API is free for low-volume use and follows a polling model: you submit a scan request, then poll for results until the status indicates completion.
API Endpoints
The base URL for the v3 API is https://api.ssllabs.com/api/v3. The primary endpoints are:
/analyze— initiates and retrieves scans/getRootCertsRaw— returns the trusted root store used by SSL Labs/getStatus— returns overall service status and message banners
Initiating a Scan
To start a new scan, issue a GET request with the startNew parameter set to on:
curl "https://api.ssllabs.com/api/v3/analyze?host=example.com&startNew=on&publish=off"
The response is a JSON object containing the scan status. Initially, the status will be DNS or IN_PROGRESS. You must wait and poll again:
{
"status": "IN_PROGRESS",
"host": "example.com",
"startTime": 1700000000000,
"engineVersion": "2.1.0",
"criteriaVersion": "2009q",
"endpoints": []
}
Polling for Results
Once a scan is in progress, drop the startNew parameter and poll periodically. SSL Labs recommends waiting at least 5 seconds between polls to avoid rate limiting:
curl "https://api.ssllabs.com/api/v3/analyze?host=example.com&publish=off"
When the status becomes READY, the endpoints array will be populated with per-IP results. Each endpoint object includes the grade, certificate details, and vulnerability flags:
{
"status": "READY",
"host": "example.com",
"endpoints": [
{
"ipAddress": "93.184.216.34",
"statusMessage": "Ready",
"grade": "A",
"gradeTrustIgnored": "A",
"hasWarnings": false,
"isExceptional": false,
"progress": 100,
"duration": 45000,
"delegation": 1,
"details": {
"protocols": [
{"id": 771, "name": "TLS", "version": "1.2"},
{"id": 772, "name": "TLS", "version": "1.3"}
],
"forwardSecrecy": 4,
"rc4Only": false,
"heartbeat": false,
"poodleTls": 1,
"fallbackScsv": true
}
}
]
}
Python Wrapper Example
For production automation, a small Python script can handle the polling loop and result parsing. The following example uses only the standard library:
import json
import time
import urllib.request
API_BASE = "https://api.ssllabs.com/api/v3"
def scan_host(hostname, publish=False, max_wait=300):
"""Run an SSL Labs scan and return the complete result."""
params = f"host={hostname}&publish={'on' if publish else 'off'}"
# Start a new scan
url = f"{API_BASE}/analyze?{params}&startNew=on"
with urllib.request.urlopen(url) as resp:
data = json.loads(resp.read())
start_time = time.time()
while data.get("status") not in ("READY", "ERROR"):
if time.time() - start_time > max_wait:
raise TimeoutError("Scan did not complete within the time limit")
time.sleep(5)
url = f"{API_BASE}/analyze?{params}"
with urllib.request.urlopen(url) as resp:
data = json.loads(resp.read())
return data
def summarize(result):
"""Print a concise summary of scan results."""
print(f"Host: {result['host']}")
print(f"Status: {result['status']}")
for ep in result.get("endpoints", []):
ip = ep.get("ipAddress", "unknown")
grade = ep.get("grade", "N/A")
warnings = ep.get("hasWarnings", False)
print(f" {ip}: Grade {grade} (warnings: {warnings})")
if __name__ == "__main__":
result = scan_host("example.com")
summarize(result)
Rate Limits and Etiquette
The public API is shared infrastructure. To keep it available for everyone, observe these limits:
- Maximum of 25 new scans per 15-minute window per source IP.
- At least 5 seconds between poll requests.
- Avoid redundant scans — cache results and reuse them when appropriate.
- For higher volume, contact Qualys about enterprise access or self-host the open-source assessment tools.
Command-Line Scanning with ssllabs-scan
The open-source ssllabs-scan tool, maintained on GitHub, wraps the API in a convenient Go binary. It is ideal for batch scanning and CI/CD integration.
Installation
Download the latest release binary for your platform from the project's GitHub releases page, or build from source:
git clone https://github.com/ssllabs/ssllabs-scan.git
cd ssllabs-scan
go build
Basic Usage
# Scan a single host and print JSON to stdout
./ssllabs-scan example.com
# Scan multiple hosts from a file
./ssllabs-scan -hostfile=hosts.txt
# Save results to a JSON file
./ssllabs-scan -jsonfile=results.json example.com
# Use a specific API endpoint (useful for testing)
./ssllabs-scan -api=api.ssllabs.com example.com
CI/CD Integration
You can integrate SSL Labs scans into a deployment pipeline to catch regressions before they reach production. The following shell snippet scans a host and fails if the grade drops below A:
#!/usr/bin/env bash
set -euo pipefail
HOST="${1:?Usage: $0 <hostname>}"
MIN_GRADE="A"
RESULT=$(./ssllabs-scan -quiet -jsonfile=/dev/stdout "$HOST" 2>/dev/null)
GRADE=$(echo "$RESULT" | jq -r '.[0].endpoints[0].grade')
echo "SSL Labs grade for $HOST: $GRADE"
if [[ "$GRADE" < "$MIN_GRADE" ]]; then
echo "FAIL: Grade $GRADE is below required $MIN_GRADE"
exit 1
fi
echo "PASS: Meets minimum grade requirement"
Configuring Your Server for an A+ Grade
Achieving a top grade requires attention to four areas: certificate quality, protocol selection, cipher suite ordering, and HSTS. The following sections provide concrete configurations for the most common web servers.
Nginx Configuration
Place these directives in your server block. This configuration targets TLS 1.2 and 1.3 only, prioritizes AEAD ciphers, enables OCSP stapling, and enforces HSTS:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
# Certificate and chain
ssl_certificate /etc/ssl/certs/example.com.fullchain.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Protocols: disable everything below TLS 1.2
ssl_protocols TLSv1.2 TLSv1.3;
# Cipher suites for TLS 1.2 (TLS 1.3 ciphers are managed separately)
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
# Session settings
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
# HSTS — required for A+
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Security headers that complement TLS posture
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
}
Apache Configuration
The equivalent Apache directives achieve the same posture. Place them in your VirtualHost block or a shared include:
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.fullchain.pem
SSLCertificateKeyFile /etc/ssl/private/example.com.key
# Disable legacy protocols
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# Strong cipher suites with server preference
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder on
SSLSessionTickets off
# OCSP stapling
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# HTTP/2 support
Protocols h2 http/1.1
</VirtualHost>
HAProxy Configuration
For load balancers terminating TLS, HAProxy supports modern TLS settings through its bind directive:
frontend https_in
bind *:443 ssl crt /etc/ssl/certs/example.com.pem alpn h2,http/1.1 ssl-min-ver TLSv1.2 no-sslv3 no-tlsv10 no-tlsv11
http-response set-header Strict-Transport-Security max-age=63072000;\ includeSubDomains;\ preload
default_backend app_servers
Best Practices Checklist
Use the following checklist as a recurring audit framework. Review it quarterly or whenever you change your TLS stack:
Certificate Hygiene
- Use RSA keys of at least 2048 bits, or preferably ECDSA P-256 keys for better performance.
- Ensure the full certificate chain is served, including all intermediate certificates.
- Set renewal reminders at least 30 days before expiration; automate renewal with ACME clients like certbot.
- Use SHA-256 or stronger signature algorithms; never use SHA-1.
- Enable OCSP stapling to reduce client-side latency and improve privacy.
- Consider Certificate Transparency monitoring to detect unauthorized issuance for your domains.
Protocol and Cipher Hardening
- Disable SSLv2, SSLv3, TLS 1.0, and TLS 1.1 entirely.
- Enable TLS 1.2 and TLS 1.3; prefer TLS 1.3 for its simplified, more secure handshake.
- Prioritize AEAD cipher suites (GCM and ChaCha20-Poly1305).
- Ensure all enabled suites provide forward secrecy via ECDHE key exchange.
- Disable NULL, anonymous, export, and RC4 cipher suites.
- Disable TLS compression to mitigate the CRIME attack.
HTTP Hardening
- Enable HSTS with a max-age of at least 31536000 (one year); 63072000 (two years) is recommended.
- Include
includeSubDomainsonly if all subdomains are HTTPS-ready. - Submit your domain to the HSTS preload list at
https://hstspreload.orgafter careful testing. - Redirect all HTTP traffic to HTTPS with a 301 status code.
- Avoid mixed content — load all subresources over HTTPS.
Operational Practices
- Run SSL Labs scans after every certificate renewal and every server configuration change.
- Monitor certificate expiration with automated alerts; do not rely on manual checks.
- Keep your TLS library (OpenSSL, BoringSSL, LibreSSL) patched and current.
- Maintain an inventory of all TLS endpoints, including internal services and APIs.
- Document your cipher suite and protocol decisions so future administrators understand the rationale.
- Test client compatibility before disabling older protocols — use the SSL Labs handshake simulation data to identify affected clients.
Interpreting and Fixing Common Findings
Chain Issues: "Chain issues: Incomplete"
This means your server is not sending the intermediate certificate(s) needed to link your leaf certificate to a trusted root. Fix it by concatenating your certificate and intermediate certificates into a single fullchain file. With Let's Encrypt, the fullchain.pem file already includes the intermediates — use it instead of cert.pem.
Weak Key: "RSA key strength below 2048 bits"
Generate a new key with sufficient strength. For RSA:
openssl req -new -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr
For ECDSA, which offers equivalent security with smaller keys:
openssl ecparam -genkey -name prime256v1 -noout -out example.com.key
openssl req -new -key example.com.key -out example.com.csr
POODLE (SSLv3) Vulnerability
Disable SSLv3 on all servers. In Nginx, ensure your ssl_protocols directive does not include SSLv3. In Apache, use SSLProtocol all -SSLv3. Also enable TLS_FALLBACK_SCSV to prevent forced downgrade attacks — modern versions of OpenSSL, Apache, and Nginx include this by default.
Missing HSTS
Without HSTS, users who type example.com without the scheme are vulnerable to a downgrade attack on their first request. Add the HSTS header as shown in the server configurations above. Verify it appears in responses:
curl -sI https://example.com | grep -i strict-transport-security
BEAST Vulnerability
BEAST exploits TLS 1.0 CBC mode. The fix is to disable TLS 1.0 and prefer AEAD ciphers. If you must support legacy clients temporarily, enable server-side cipher preference and prioritize GCM suites.
ROBOT Vulnerability
ROBOT affects servers using RSA key exchange with certain implementations. Switch to ECDHE-based cipher suites and disable static RSA key exchange. Test with the ROBOT-specific tool at https://robotattack.org if your SSL Labs report flags it.
DROWN Vulnerability
DROWN exploits servers that still support SSLv2, even on a different port or service. Disable SSLv2 everywhere, including on SMTP, IMAP, and other TLS-enabled services on the same infrastructure.
Continuous Monitoring Strategy
A one-time scan is insufficient. TLS configurations drift as servers are patched, certificates are renewed, and new vulnerabilities are discovered. Build a monitoring pipeline that combines scheduled scans with alerting.
Scheduled Scan with Cron
# Run weekly SSL Labs scan and email results if grade drops
0 6 * * 1 /opt/scripts/ssllabs-check.sh example.com >> /var/log/ssllabs.log 2>&1
Integration with Monitoring Systems
You can feed SSL Labs grades into Prometheus, Datadog, or Nagios by parsing the API output and exporting a numeric metric. For example, map grades to numbers (A+ = 6, A = 5, B = 4, C = 3, D = 2, E = 1, F = 0) and alert when the value drops below your threshold. This transforms a point-in-time assessment into an ongoing compliance signal.
Certificate Expiration Monitoring
Separately from grade monitoring, track certificate expiration dates. A simple check using OpenSSL can run daily:
#!/usr/bin/env bash
HOST="${1:?Usage: $0 <hostname>}"
WARN_DAYS=30
EXPIRY=$(echo | openssl s_client -servername "$HOST" -connect "$HOST":443 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null \
| cut -d= -f2)
if [ -z "$EXPIRY" ]; then
echo "ERROR: Could not retrieve certificate for $HOST"
exit 2
fi
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -lt "$WARN_DAYS" ]; then
echo "WARNING: Certificate for $HOST expires in $DAYS_LEFT days"
exit 1
fi
echo "OK: Certificate for $HOST expires in $DAYS_LEFT days"
Conclusion
SSL Labs provides an indispensable lens for evaluating and maintaining the security of your TLS deployments. By understanding the grading model, automating scans through the API or command-line tools, and applying the configuration patterns and best practices outlined in this tutorial, you can consistently achieve strong grades and, more importantly, provide genuine cryptographic protection for your users. TLS security is not a one-time setup task — it is an ongoing discipline that requires regular assessment, prompt patching, and vigilance against an evolving threat landscape. Make SSL Labs scans a routine part of your deployment pipeline and operational reviews, and you will catch regressions before they become incidents.