Running Redis in FIPS-Compliant Mode
Redis doesn't have native FIPS TLS support in older versions. CleanStart uses stunnel (a FIPS-capable TLS wrapper) to provide FIPS-compliant encryption for Redis without modifying Redis itself.
Stunnel intercepts Redis connections and applies FIPS-approved TLS before forwarding to Redis.
Architecture
Client → stunnel (FIPS TLS) → Redis (unencrypted) (Crypto operations)Clients connect to stunnel on port 6380 (encrypted), stunnel connects to Redis on port 6379 (local, unencrypted).
Installation and Setup
Install Stunnel with FIPS
# Ubuntu 24.04 (FIPS-enabled)sudo apt-get update && apt-get install -y \ stunnel4 \ redis-server \ openssl-fips # Verify stunnel uses FIPS OpenSSLstunnel -version | grep -i fips# Output: OpenSSL 3.0.10 (FIPS module)Generate FIPS-Compliant Certificates
#!/bin/bash# generate-redis-certs.sh # Create CAopenssl genrsa -out redis-ca.key 2048openssl req -new -x509 \ -key redis-ca.key \ -out redis-ca.crt \ -days 3650 \ -sha256 \ -subj "/CN=Redis-CA" # Create server certificateopenssl genrsa -out redis-server.key 2048openssl req -new \ -key redis-server.key \ -out redis-server.csr \ -subj "/CN=redis.example.com" # Sign with CA (use FIPS SHA-256)openssl x509 -req \ -in redis-server.csr \ -CA redis-ca.crt \ -CAkey redis-ca.key \ -CAcreateserial \ -out redis-server.crt \ -days 365 \ -sha256 # Create client certificateopenssl genrsa -out redis-client.key 2048openssl req -new \ -key redis-client.key \ -out redis-client.csr \ -subj "/CN=redis-client" openssl x509 -req \ -in redis-client.csr \ -CA redis-ca.crt \ -CAkey redis-ca.key \ -CAcreateserial \ -out redis-client.crt \ -days 365 \ -sha256Stunnel Configuration
Server Configuration
# /etc/stunnel/redis.conf [redis]; Listen on FIPS-encrypted portaccept = 0.0.0.0:6380; Forward to local Redisconnect = 127.0.0.1:6379 ; TLS/SSL configurationcert = /etc/stunnel/redis-server.crtkey = /etc/stunnel/redis-server.keyCAfile = /etc/stunnel/redis-ca.crt ; FIPS TLS settingssslVersion = TLSv1.2options = NO_SSLv3 NO_TLSv1 NO_TLSv1_1 ; Require client certificateverifyPeer = yesverifyChain = yes ; FIPS-approved cipher suitesciphers = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256 ; Session cachingsessionCacheSize = 1000sessionCacheTimeout = 300 ; LogginglogFile = /var/log/stunnel/redis.logsyslog = noEnable Stunnel Service
# Enable stunnelsudo systemctl enable stunnel4sudo systemctl restart stunnel4 # Verify listeningsudo netstat -tlnp | grep stunnel# Output: tcp 0 0 0.0.0.0:6380 0.0.0.0:* LISTEN stunnelRedis Configuration
Redis Server (Local Only)
# /etc/redis/redis.conf # Listen only on localhost (stunnel handles network)bind 127.0.0.1port 6379protected-mode yes # Require Redis password for extra securityrequirepass myredispassword # Persistent storagesave 900 1save 300 10save 60 10000Client Connection
Redis CLI with TLS
# Connect via stunnel (FIPS TLS)redis-cli \ -h redis.example.com \ -p 6380 \ --tls \ --cert /etc/redis/redis-client.crt \ --key /etc/redis/redis-client.key \ --cacert /etc/redis/redis-ca.crt \ --insecure # For self-signed (not recommended for production)Python Client with FIPS TLS
import redisimport ssl # Create SSL context (uses FIPS module if available)context = ssl.create_default_context()context.load_cert_chain( certfile='/etc/redis/redis-client.crt', keyfile='/etc/redis/redis-client.key', password=b'keypassword')context.load_verify_locations(cafile='/etc/redis/redis-ca.crt') # Connect with TLSclient = redis.Redis( host='redis.example.com', port=6380, ssl=True, ssl_certfile='/etc/redis/redis-client.crt', ssl_keyfile='/etc/redis/redis-client.key', ssl_ca_certs='/etc/redis/redis-ca.crt', ssl_check_hostname=True, password='myredispassword') # Use clientclient.set('key', 'value')print(client.get('key'))Java Client with FIPS TLS
import redis.clients.jedis.*; // Create SSL context (uses FIPS module)SSLSocketFactory sslSocketFactory = SSLSocketFactory.getDefault(); HostAndPort hostAndPort = new HostAndPort("redis.example.com", 6380); JedisClientConfig config = DefaultJedisClientConfig.builder() .ssl(true) .sslSocketFactory(sslSocketFactory) .password("myredispassword") .build(); UnifiedJedis jedis = new UnifiedJedis(hostAndPort, config); // Use connectionjedis.set("key", "value");System.out.println(jedis.get("key"));Node.js Client with FIPS TLS
const redis = require('redis');const fs = require('fs'); const client = redis.createClient({ host: 'redis.example.com', port: 6380, socket: { tls: true, ca: fs.readFileSync('/etc/redis/redis-ca.crt', 'utf8'), cert: fs.readFileSync('/etc/redis/redis-client.crt', 'utf8'), key: fs.readFileSync('/etc/redis/redis-client.key', 'utf8'), checkServerIdentity: (servername, cert) => { // Hostname verification return null; // No error } }, password: 'myredispassword'}); client.on('connect', () => { client.set('key', 'value', (err, reply) => { if (err) throw err; console.log(reply); });});Docker: Redis with FIPS TLS via Stunnel
# Dockerfile: Redis with FIPS Stunnel FROM ubuntu:24.04-fips # Install Redis, stunnel, and FIPS librariesRUN apt-get update && apt-get install -y \ redis-server \ stunnel4 \ openssl-fips \ ca-certificates # Copy certificatesCOPY redis-ca.crt /etc/stunnel/COPY redis-server.crt /etc/stunnel/COPY redis-server.key /etc/stunnel/ # Copy stunnel configurationCOPY stunnel-redis.conf /etc/stunnel/redis.conf # Copy Redis configurationCOPY redis.conf /etc/redis/ # Set secure permissionsRUN chmod 600 /etc/stunnel/redis-server.keyRUN chmod 644 /etc/stunnel/redis-server.crtRUN chmod 644 /etc/stunnel/redis-ca.crt # Expose FIPS TLS port (not plain redis port)EXPOSE 6380 # Startup scriptCOPY docker-entrypoint.sh /RUN chmod +x /docker-entrypoint.sh ENTRYPOINT ["/docker-entrypoint.sh"]#!/bin/bash# docker-entrypoint.sh # Start Redis in backgroundredis-server /etc/redis/redis.conf --port 6379 & # Start stunnel with FIPS TLSstunnel /etc/stunnel/redis.conf # Keep container runningwaitDocker Compose
version: '3.8' services: redis-fips: build: context: . dockerfile: Dockerfile.redis-fips ports: - "6380:6380" # Only expose FIPS TLS port volumes: - redis-data:/var/lib/redis - ./certs:/etc/stunnel:ro environment: - REDIS_PASSWORD=myredispassword healthcheck: test: ["CMD", "redis-cli", "-p", "6379", "ping"] interval: 10s timeout: 5s retries: 5 volumes: redis-data:FIPS Verification
Verify Stunnel Uses FIPS
# Check stunnel FIPS statusstunnel -version# OpenSSL 3.0.10 (FIPS module 3.0.10 - CMVP Validated) # Test TLS connectionopenssl s_client \ -connect redis.example.com:6380 \ -cert redis-client.crt \ -key redis-client.key \ -CAfile redis-ca.crt # Output should show:# subject=CN = redis.example.com# issuer=CN = Redis-CA# TLSv1.2 or TLSv1.3# Cipher = ECDHE-RSA-AES256-GCM-SHA384 (FIPS-approved)Automated FIPS Verification
# CleanStart FIPS verificationcleanimg-init --fips-verifier --image my-redis:latest # Output:# ✓ Stunnel uses FIPS OpenSSL module# ✓ TLS 1.2/1.3 configured (FIPS-approved)# ✓ FIPS cipher suites only# ✓ Client certificate authentication required# ✓ Server certificate validates against CA# ✓ Redis password authentication enabledMonitoring
Monitor Stunnel
# View stunnel logstail -f /var/log/stunnel/redis.log # Check active connectionsss -tlnp | grep stunnel # Monitor CPU/Memorytop -p $(pgrep stunnel)Redis Memory and Performance
# Connect to local Redis (requires password)redis-cli -p 6379 -a myredispassword # Check memory usageINFO memory # Check TLS traffic stats (if available)INFO statsPerformance Considerations
TLS overhead: 5-10% latency increase (acceptable for compliance). CPU impact: ~5-15% CPU increase from encryption. Throughput: Typically 10-20K ops/sec with TLS (vs 30K+ without).
Troubleshooting
Stunnel Fails to Start
# Check configuration syntaxstunnel -t /etc/stunnel/redis.conf # Look for errors in logstail -f /var/log/stunnel/redis.logTLS Certificate Issues
# Verify certificate validityopenssl x509 -in redis-server.crt -text -noout # Check expirationopenssl x509 -in redis-server.crt -noout -datesClient Cannot Connect
# Test with openssl firstopenssl s_client -connect redis.example.com:6380 \ -cert redis-client.crt -key redis-client.key -CAfile redis-ca.crt # Check Redis listening on localhostredis-cli -p 6379 -a myredispassword ping# Should return: PONGCompliance Mapping
Requirement | Implementation |
|---|---|
FIPS 140-3 | Stunnel with OpenSSL FIPS module |
NIST 800-171 SC-13 | TLS 1.2/1.3, AES-256-GCM, RSA-2048 |
PCI DSS 4.1 | Encryption of data in transit |
HIPAA § 164.312(a)(2)(i) | Encryption with FIPS-approved algorithms |
See Also
FIPS Overview: fips-140-overview.md — FIPS concepts, FIPS PostgreSQL: fips-postgresql.md — Similar TLS patterns, and FIPS Kafka: fips-kafka.md — Message broker TLS.
