How to Log SSL/TLS Protocol and Cipher Suite in Nginx for Security Monitoring


1 views

When securing web traffic with SSL/TLS, it's crucial to monitor which protocols and cipher suites are actually being used in production. While Mozilla's TLS configuration guide provides excellent recommendations, real-world client behavior may differ. Logging this information helps identify:
- Clients using outdated protocols (TLS 1.0/1.1)
- Weak cipher suite negotiations
- Clients without Perfect Forward Secrecy (PFS) support

Nginx provides built-in variables that expose SSL/TLS connection details:


$ssl_protocol - The negotiated SSL/TLS protocol version
$ssl_cipher - The negotiated cipher suite
$ssl_session_id - The SSL session identifier
$ssl_session_reused - Whether session was reused

To log these details, modify your nginx configuration by adding these variables to your log format:


log_format ssl_log '$remote_addr - $remote_user [$time_local] '
                  '"$ssl_protocol" "$ssl_cipher" '
                  '"$request" $status $body_bytes_sent '
                  '"$http_referer" "$http_user_agent"';

server {
    listen 443 ssl;
    # ... existing SSL configuration ...
    access_log /var/log/nginx/ssl_access.log ssl_log;
}

With this configuration, your logs will show entries like:


203.0.113.42 - - [15/Jan/2023:14:32:15 +0000] "TLSv1.2" "ECDHE-RSA-AES256-GCM-SHA384" "GET / HTTP/1.1" 200 1432 "-" "Mozilla/5.0"
192.0.2.17 - - [15/Jan/2023:14:33:22 +0000] "TLSv1.1" "ECDHE-RSA-AES256-SHA" "GET / HTTP/1.1" 200 1432 "-" "OldBrowser/1.0"

For more detailed monitoring:


# Separate log file for SSL handshake failures
log_format ssl_errors '$remote_addr [$time_local] $ssl_protocol $ssl_cipher '
                     '$ssl_handshake_time $ssl_early_data';

server {
    # ... existing configuration ...
    error_log /var/log/nginx/ssl_errors.log ssl_errors;
}

Consider using tools like GoAccess or custom scripts to parse these logs:


# Sample awk command to count protocol usage
awk '{print $5}' /var/log/nginx/ssl_access.log | sort | uniq -c | sort -rn

Remember that logging sensitive information requires proper security measures:
- Restrict log file permissions (chmod 640)
- Consider omitting sensitive data from logs
- Implement log rotation to prevent disk exhaustion


When hardening your nginx SSL/TLS configuration using guidelines like Mozilla's Server Side TLS recommendations, it's crucial to verify what protocols and cipher suites are actually being negotiated in production. Without proper logging, you're essentially flying blind regarding your TLS security posture.

Nginx provides several built-in variables that expose SSL/TLS connection details:

$ssl_protocol - The negotiated protocol (e.g., TLSv1.2)
$ssl_cipher - The negotiated cipher suite (e.g., ECDHE-RSA-AES256-GCM-SHA384)
$ssl_early_data - Indicates if TLS 1.3 early data was used
$ssl_session_id - The SSL session identifier
$ssl_session_reused - Whether session was reused

Here's how to modify your nginx configuration to include these details in your access logs:

log_format ssl_log '$remote_addr - $remote_user [$time_local] '
                  '"$ssl_protocol $ssl_cipher" '
                  '"$request" $status $body_bytes_sent '
                  '"$http_referer" "$http_user_agent"';

server {
    listen 443 ssl;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_dhparam /path/to/dhparam.pem;
    
    access_log /var/log/nginx/ssl_access.log ssl_log;
    
    # Your existing SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:...';
    ssl_prefer_server_ciphers on;
}

For more detailed security auditing, consider this enhanced log format:

log_format detailed_ssl_log '$remote_addr - $remote_user [$time_local] '
                          'ssl_proto="$ssl_protocol" ssl_cipher="$ssl_cipher" '
                          'ssl_session="$ssl_session_id" ssl_reused="$ssl_session_reused" '
                          'request="$request" status=$status bytes=$body_bytes_sent '
                          'referer="$http_referer" agent="$http_user_agent"';

Once implemented, you can use tools like awk or specialized log analyzers to parse the data:

# Count protocol usage
awk '{print $5}' /var/log/nginx/ssl_access.log | sort | uniq -c | sort -nr

# Find clients using weak ciphers
grep -E 'RC4|DES|CBC' /var/log/nginx/ssl_access.log

# Monitor TLS 1.0/1.1 usage (deprecated protocols)
grep -E 'TLSv1|TLSv1\.1' /var/log/nginx/ssl_access.log

Remember that logging sensitive security information requires proper handling:

  • Restrict access to SSL log files (chmod 600)
  • Consider hashing or masking sensitive fields if needed
  • Implement log rotation to prevent disk space issues
  • Be mindful of privacy regulations when logging user agent strings