BLOG POSTS
    MangoHost Blog / How to Connect to Managed Redis Over TLS with Stunnel and Redis CLI
How to Connect to Managed Redis Over TLS with Stunnel and Redis CLI

How to Connect to Managed Redis Over TLS with Stunnel and Redis CLI

Connecting to managed Redis instances over TLS can be tricky, especially when you’re dealing with SSL/TLS encryption requirements and want to use the standard Redis CLI. While Redis 6+ has native TLS support, many scenarios still require tunneling encrypted connections through tools like Stunnel. This guide walks you through setting up a secure TLS connection to managed Redis using Stunnel as a proxy, covering everything from basic configuration to troubleshooting common connection issues you’ll inevitably encounter.

How TLS Tunneling Works with Redis

Stunnel acts as a TLS termination proxy that sits between your Redis CLI and the managed Redis instance. It handles the SSL/TLS encryption/decryption while presenting a plain TCP interface to your local Redis CLI. The flow looks like this:

Redis CLI (plain TCP) β†’ Stunnel (localhost:6380) β†’ TLS Encryption β†’ Managed Redis (TLS endpoint:6380)

This approach is particularly useful when:

  • Your managed Redis provider requires TLS but you’re using Redis CLI versions below 6.0
  • You need to connect legacy applications that don’t support Redis TLS natively
  • You want to simplify certificate management in containerized environments
  • You’re working with Redis clusters where TLS configuration gets complex

Installing and Configuring Stunnel

First, install Stunnel on your system. The installation process varies by OS:

# Ubuntu/Debian
sudo apt-get update && sudo apt-get install stunnel4

# CentOS/RHEL
sudo yum install stunnel

# macOS
brew install stunnel

# Enable stunnel service on Ubuntu
sudo systemctl enable stunnel4

Create a Stunnel configuration file at /etc/stunnel/redis-tls.conf:

# Basic TLS tunnel configuration for Redis
pid = /var/run/stunnel/redis-tls.pid
debug = 4
output = /var/log/stunnel/redis-tls.log

[redis-tls]
accept = 127.0.0.1:6380
connect = your-redis-endpoint.cache.amazonaws.com:6380
cert = /etc/ssl/certs/redis-client.crt
key = /etc/ssl/private/redis-client.key
CAfile = /etc/ssl/certs/ca-bundle.crt
verify = 2
checkHost = your-redis-endpoint.cache.amazonaws.com

For basic TLS without client certificates (common with AWS ElastiCache), use this simplified version:

[redis-tls]
accept = 127.0.0.1:6380
connect = your-redis-endpoint.cache.amazonaws.com:6380
# No client cert required for basic TLS
verify = 1

Step-by-Step Connection Setup

Here’s the complete process to establish your TLS connection:

Step 1: Verify your managed Redis endpoint details

# Test basic connectivity (this will fail with TLS endpoints)
telnet your-redis-endpoint.cache.amazonaws.com 6380

# Check TLS certificate details
openssl s_client -connect your-redis-endpoint.cache.amazonaws.com:6380 -servername your-redis-endpoint.cache.amazonaws.com

Step 2: Start Stunnel with your configuration

# Start stunnel manually for testing
sudo stunnel /etc/stunnel/redis-tls.conf

# Or start as service
sudo systemctl start stunnel4
sudo systemctl status stunnel4

Step 3: Test the local tunnel connection

# Verify stunnel is listening locally
netstat -tlnp | grep 6380
ss -tlnp | grep 6380

# Test plain connection to local tunnel
telnet 127.0.0.1 6380

Step 4: Connect with Redis CLI

# Basic connection
redis-cli -h 127.0.0.1 -p 6380

# With authentication
redis-cli -h 127.0.0.1 -p 6380 -a your-auth-token

# Test connection
redis-cli -h 127.0.0.1 -p 6380 ping
redis-cli -h 127.0.0.1 -p 6380 info server

Real-World Configuration Examples

Here are configurations for popular managed Redis providers:

AWS ElastiCache (In-Transit Encryption)

[elasticache-redis]
accept = 127.0.0.1:6380
connect = master.your-cluster.abc123.cache.amazonaws.com:6380
verify = 1
checkHost = master.your-cluster.abc123.cache.amazonaws.com
sslVersion = TLSv1.2

Azure Cache for Redis (SSL)

[azure-redis]
accept = 127.0.0.1:6380
connect = your-cache.redis.cache.windows.net:6380
verify = 2
checkHost = your-cache.redis.cache.windows.net
sslVersion = TLSv1.2

Google Cloud Memorystore (TLS)

[gcp-memorystore]
accept = 127.0.0.1:6380
connect = 10.x.x.x:6380
cert = /path/to/client-cert.pem
key = /path/to/client-key.pem
CAfile = /path/to/server-ca.pem
verify = 2

For development environments on VPS instances, you might want multiple Redis connections:

# Multiple Redis instances configuration
[redis-prod]
accept = 127.0.0.1:6380
connect = prod-redis.example.com:6380

[redis-staging]
accept = 127.0.0.1:6381
connect = staging-redis.example.com:6380

[redis-dev]
accept = 127.0.0.1:6382
connect = dev-redis.example.com:6380

Performance and Security Considerations

Here’s how different approaches compare:

Connection Method Latency Overhead Setup Complexity Security Level Compatibility
Direct TLS (Redis 6+) ~2-5ms Low High Redis 6+ only
Stunnel Proxy ~5-10ms Medium High All Redis versions
SSH Tunnel ~10-15ms Medium High All versions
Plain Connection ~1ms Very Low None All versions

Security best practices for production deployments:

  • Always use certificate pinning in production environments
  • Limit Stunnel accept interface to localhost only (127.0.0.1)
  • Set appropriate file permissions on certificate files (600 for private keys)
  • Use separate certificates for different environments
  • Enable connection logging for security auditing
  • Configure proper firewall rules on your dedicated servers

Troubleshooting Common Issues

Connection Refused Errors

# Check if stunnel is running
ps aux | grep stunnel
sudo systemctl status stunnel4

# Verify configuration syntax
stunnel -test /etc/stunnel/redis-tls.conf

# Check logs for detailed errors
tail -f /var/log/stunnel/redis-tls.log

Certificate Verification Failures

# Test certificate chain manually
openssl s_client -connect your-redis-endpoint:6380 -CAfile /etc/ssl/certs/ca-bundle.crt

# Bypass certificate verification for testing (insecure)
verify = 0

Authentication Issues

# Test authentication through tunnel
redis-cli -h 127.0.0.1 -p 6380
127.0.0.1:6380> AUTH your-password
127.0.0.1:6380> PING

# Check for NOAUTH errors
redis-cli -h 127.0.0.1 -p 6380 --no-auth-warning -a your-password ping

Common configuration mistakes and fixes:

Error Symptom Solution
Port already in use stunnel fails to start Change accept port or kill conflicting process
Permission denied Can’t read certificate files Check file ownership and permissions
SSL handshake failure Connection drops immediately Verify TLS version compatibility
DNS resolution issues Can’t connect to endpoint Use IP addresses or fix DNS settings

Advanced Configuration and Automation

For automated deployments, create a startup script:

#!/bin/bash
# redis-tls-tunnel.sh

STUNNEL_CONF="/etc/stunnel/redis-tls.conf"
STUNNEL_PID="/var/run/stunnel/redis-tls.pid"

start_tunnel() {
    if [ -f "$STUNNEL_PID" ]; then
        echo "Tunnel already running (PID: $(cat $STUNNEL_PID))"
        return 1
    fi
    
    stunnel "$STUNNEL_CONF"
    sleep 2
    
    if netstat -tlnp | grep -q ":6380.*LISTEN"; then
        echo "Redis TLS tunnel started successfully"
        return 0
    else
        echo "Failed to start tunnel"
        return 1
    fi
}

stop_tunnel() {
    if [ -f "$STUNNEL_PID" ]; then
        kill $(cat "$STUNNEL_PID")
        rm -f "$STUNNEL_PID"
        echo "Tunnel stopped"
    else
        echo "No tunnel running"
    fi
}

case "$1" in
    start) start_tunnel ;;
    stop) stop_tunnel ;;
    restart) stop_tunnel && sleep 2 && start_tunnel ;;
    *) echo "Usage: $0 {start|stop|restart}" ;;
esac

For Docker environments, create a sidecar container:

# Dockerfile.stunnel
FROM alpine:latest
RUN apk add --no-cache stunnel
COPY redis-tls.conf /etc/stunnel/
EXPOSE 6380
CMD ["stunnel", "/etc/stunnel/redis-tls.conf"]

Performance monitoring script:

#!/bin/bash
# Monitor tunnel performance and connectivity

REDIS_HOST="127.0.0.1"
REDIS_PORT="6380"

monitor_connection() {
    while true; do
        start_time=$(date +%s.%N)
        redis-cli -h $REDIS_HOST -p $REDIS_PORT ping > /dev/null 2>&1
        end_time=$(date +%s.%N)
        
        if [ $? -eq 0 ]; then
            latency=$(echo "$end_time - $start_time" | bc)
            echo "$(date): PING successful - Latency: ${latency}s"
        else
            echo "$(date): PING failed - Connection issue"
        fi
        
        sleep 10
    done
}

monitor_connection

This setup provides a robust, secure way to connect to managed Redis instances over TLS. The Stunnel approach offers excellent compatibility with existing tools and applications while maintaining strong security standards. For additional resources, check the official Stunnel documentation and Redis TLS guide.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked