Running FIPS-Compliant Nginx
Nginx serves as a TLS termination point, handling encryption for applications. FIPS compliance requires that Nginx uses FIPS-validated cryptographic modules and only FIPS-approved ciphers.
Compiling Nginx with OpenSSL FIPS module and configuring secure TLS settings enables FIPS-compliant encryption.
Prerequisites
OpenSSL 3.0+ FIPS module (CMVP #4949), Nginx 1.24+ (good OpenSSL 3.x support), and FIPS-enabled Linux system.
Compiling Nginx with FIPS OpenSSL
Build Nginx Against FIPS OpenSSL
# Install FIPS OpenSSL and build toolssudo apt-get update && apt-get install -y \ libssl3-fips \ openssl-fips \ build-essential \ libpcre3-dev \ zlib1g-dev # Download Nginx sourcecd /tmpwget http://nginx.org/download/nginx-1.26.1.tar.gztar xzf nginx-1.26.1.tar.gzcd nginx-1.26.1 # Configure with FIPS OpenSSL./configure \ --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --modules-path=/usr/lib64/nginx/modules \ --with-http_ssl_module \ --with-openssl=/usr/lib/fips \ --with-openssl-opt="fips shared" \ --with-http_gzip_static_module \ --with-http_v2_module # Build and installmakesudo make install # Verify FIPS modulenginx -vldd /usr/sbin/nginx | grep ssl# libssl.so => /usr/lib/fips/libssl.soDocker: Nginx with FIPS
# Dockerfile: Nginx with FIPS OpenSSL FROM ubuntu:24.04-fips # Install build dependencies and FIPS OpenSSLRUN apt-get update && apt-get install -y \ build-essential \ libpcre3-dev \ zlib1g-dev \ libssl3-fips \ openssl-fips # Download and build Nginx with FIPSRUN cd /tmp && \ wget http://nginx.org/download/nginx-1.26.1.tar.gz && \ tar xzf nginx-1.26.1.tar.gz && \ cd nginx-1.26.1 && \ ./configure \ --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --with-http_ssl_module \ --with-openssl=/usr/lib/fips \ --with-openssl-opt="fips shared" \ --with-http_v2_module && \ make && make install # Verify FIPSRUN nginx -v 2>&1 | grep -i nginx && \ ldd /usr/sbin/nginx | grep fips EXPOSE 443 80CMD ["nginx", "-g", "daemon off;"]FIPS TLS Configuration
Generate FIPS-Compliant Certificates
#!/bin/bash# generate-nginx-certs.sh # Generate 2048-bit RSA key (FIPS minimum)openssl genrsa -out private.key 2048 # Generate certificate signing requestopenssl req -new \ -key private.key \ -out server.csr \ -subj "/CN=example.com/O=Company/C=US" # Self-sign with SHA-256 (FIPS-approved)openssl x509 -req \ -in server.csr \ -signkey private.key \ -out server.crt \ -days 365 \ -sha256 # Create combined PEM for some clientscat server.crt private.key > server.pemchmod 600 private.key server.pem # Move to Nginx directorysudo mv server.crt server.pem /etc/nginx/certs/sudo chown nginx:nginx /etc/nginx/certs/*Nginx Configuration with FIPS TLS
# /etc/nginx/nginx.conf user nginx;worker_processes auto;error_log /var/log/nginx/error.log warn; events { worker_connections 1024;} http { # HTTPS server server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; # FIPS-compliant certificates ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/private.key; # FIPS TLS versions only ssl_protocols TLSv1.2 TLSv1.3; # FIPS-approved cipher suites ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256'; # Cipher ordering ssl_prefer_server_ciphers on; # Session configuration ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; # HSTS (force TLS) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # Other security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; # Application location location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } # HTTP to HTTPS redirect server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://$server_name$request_uri; }}Cipher Suites Breakdown
All configured ciphers are FIPS-approved. ECDHE-RSA-AES256-GCM-SHA384 uses Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) for key exchange, RSA for authentication, 256-bit AES encryption, Galois/Counter Mode (GCM) for authenticated encryption, and SHA384 as the hash function for the pseudo-random function (PRF).
ECDHE-RSA-AES128-GCM-SHA256 follows the same structure but uses 128-bit AES and 256-bit SHA2 hashing.
DHE-RSA-AES256-GCM-SHA384 substitutes Diffie-Hellman Ephemeral (DHE) as an alternative to ECDHE for key exchange while maintaining the same encryption and authentication approach.
All configured ciphers provide forward secrecy through ephemeral keys, authenticated encryption through GCM mode, and rely exclusively on FIPS-approved algorithms.
Client Certificate Authentication (Optional)
# /etc/nginx/nginx.conf - Client certificate auth server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/private.key; # Client certificate verification ssl_client_certificate /etc/nginx/certs/ca.crt; ssl_verify_client on; ssl_verify_depth 2; location / { proxy_pass http://localhost:8080; # Pass client cert info proxy_set_header SSL-Client-Cert $ssl_client_cert; proxy_set_header SSL-Client-Verify $ssl_client_verify; }}FIPS Verification
Verify Nginx Uses FIPS OpenSSL
# Check Nginx version and OpenSSLnginx -v# Output: nginx/1.26.1 # Verify TLS modulesnginx -V 2>&1 | grep ssl# Output: --with-http_ssl_module # Check OpenSSL linkageldd /usr/sbin/nginx | grep libssl# libssl.so.3 => /usr/lib/fips/libssl.so.3 (FIPS) # Verify FIPS module is activeopenssl version# OpenSSL 3.0.10 (FIPS module 3.0.10 - CMVP Validated)Test TLS Configuration
# Test SSL/TLS configurationopenssl s_client \ -connect example.com:443 \ -tls1_2 # Output should show:# subject=CN = example.com# issuer=... (certificate authority)# Protocol: TLSv1.2# Cipher: ECDHE-RSA-AES256-GCM-SHA384 (or similar FIPS cipher)Nginx SSL Test
# Use online SSL test (Qualys)curl "https://api.ssllabs.com/api/v3/analyze?host=example.com" # Or local testingopenssl s_client -connect example.com:443 -tls1_3# Should successfully handshake with TLS 1.3Automated FIPS Verification
# CleanStart FIPS verificationcleanimg-init --fips-verifier --image my-nginx:latest # Output:# Nginx is linked against FIPS OpenSSL# TLS 1.2/1.3 is configured# Only FIPS-approved ciphers are enabled# No deprecated algorithms detected (RC4, DES, etc.)# HSTS is enabled for production# Perfect Forward Secrecy (PFS) is enabled# FIPS compliance verifiedPerformance Optimization
Hardware Acceleration
# Use hardware crypto acceleration (if available)ssl_engine openssl; # OpenSSL 3.x auto-detects hardwareSession Caching
# Shared memory cache (10 MB, 10 minute timeout)ssl_session_cache shared:SSL:10m;ssl_session_timeout 10m; # Disable session tickets (more secure but less performant)ssl_session_tickets off;Common Configuration Issues
Issue: Old TLS Versions Enabled
# BAD: Allows deprecated TLSssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; # GOOD: FIPS-approved onlyssl_protocols TLSv1.2 TLSv1.3;Issue: Non-FIPS Ciphers
# BAD: Includes non-FIPS ciphersssl_ciphers 'ALL:!aNULL'; # GOOD: Only FIPS-approvedssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:...';Issue: Weak Key Size
# BAD: 1024-bit RSAopenssl genrsa -out key.pem 1024 # GOOD: 2048-bit RSA (FIPS minimum)openssl genrsa -out key.pem 2048 # Better: 4096-bit for extended securityopenssl genrsa -out key.pem 4096Monitoring
Check TLS Handshake Success
# Monitor handshakestail -f /var/log/nginx/access.log | grep "SSL" # Check error logtail -f /var/log/nginx/error.log | grep "ssl"Performance Metrics
# CPU usage (TLS is CPU-intensive)top -p $(pgrep nginx) # Connection statsss -s | grep TCPCompliance Mapping
Requirement | Implementation |
|---|---|
FIPS 140-3 | OpenSSL 3.0 FIPS module #4949 |
NIST 800-171 SC-13 | TLS 1.2/1.3, RSA-2048, AES-256-GCM |
PCI DSS 4.1 | Strong encryption in transit |
HIPAA § 164.312(a)(2)(i) | FIPS-approved encryption |
SOC 2 CC6.2 | Cryptographic controls |
See Also
FIPS Overview: fips-140-overview.md — FIPS principles, FIPS PostgreSQL: fips-postgresql.md — Database TLS patterns, and FIPS Kafka: fips-kafka.md — Message broker TLS.
