Skip to main content
CleanStart

Knowledge Hub

FIPS-Compliant Redis: TLS Configuration via Stunnel

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 \  -sha256

Stunnel 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 = no

Enable 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  stunnel

Redis 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 10000

Client 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 runningwait

Docker 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 enabled

Monitoring

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 stats

Performance 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.log

TLS Certificate Issues

# Verify certificate validityopenssl x509 -in redis-server.crt -text -noout # Check expirationopenssl x509 -in redis-server.crt -noout -dates

Client 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: PONG

Compliance 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.