guide/configuration/ssl.md
SSL/TLS Configuration
To secure WebSocket connections using wss://
(WebSocket Secure), you need to configure Sockudo with an SSL/TLS certificate. This encrypts the data transmitted between clients and your Sockudo server, protecting it from eavesdropping and tampering.
When to Use SSL/TLS
It is highly recommended to use SSL/TLS for all production deployments of Sockudo. Unencrypted ws://
connections are vulnerable and should only be used for local development or in trusted network environments where traffic is otherwise secured.
Browsers also enforce stricter rules for wss://
, often requiring it for features like Service Workers or when the main page is served over https://
.
Configuration in config.json
SSL/TLS settings are configured via the ssl
object within your config.json
. The WebSocket server will automatically use wss://
if SSL is enabled.
{
"ssl": {
"enabled": true,
"cert_path": "/etc/sockudo/certs/fullchain.pem",
"key_path": "/etc/sockudo/certs/privkey.pem",
"passphrase": null,
"ca_path": null,
"redirect_http": true,
"http_port": 80
},
"port": 6001
}
SSL Configuration Options
ssl.enabled
- JSON Key:
enabled
- Environment Variable:
SSL_ENABLED
(Set totrue
or1
) - Type:
boolean
- Description: Enables or disables SSL/TLS. If
true
, you must provide paths to your certificate and private key. - Default Value:
false
ssl.cert_path
- JSON Key:
cert_path
- Environment Variable:
SSL_CERT_PATH
- Type:
string
- Description: The absolute or relative path to your SSL certificate file. This is typically a PEM-encoded file containing the server's certificate, and potentially intermediate certificates.
- Default Value:
"/app/ssl/cert.pem"
- Required: Yes, if
ssl.enabled
istrue
.
ssl.key_path
- JSON Key:
key_path
- Environment Variable:
SSL_KEY_PATH
- Type:
string
- Description: The absolute or relative path to your SSL private key file. This key must correspond to the certificate specified in
cert_path
. - Default Value:
"/app/ssl/key.pem"
- Required: Yes, if
ssl.enabled
istrue
.
ssl.passphrase
- JSON Key:
passphrase
- Environment Variable:
SSL_PASSPHRASE
- Type:
string
(optional) - Description: The passphrase for your SSL private key, if the key is encrypted. If your key is not encrypted, omit this option or set it to
null
. - Default Value:
null
(None)
ssl.ca_path
- JSON Key:
ca_path
- Environment Variable:
SSL_CA_PATH
- Type:
string
(optional) - Description: Path to a file containing trusted CA certificates in PEM format. This can be used for features like client certificate authentication (mTLS).
- Default Value:
null
(None)
ssl.redirect_http
- JSON Key:
redirect_http
- Environment Variable:
SSL_REDIRECT_HTTP
(Set totrue
or1
) - Type:
boolean
- Description: If
ssl.enabled
istrue
, setting this totrue
will also start a basic HTTP server on the port specified byssl.http_port
. This HTTP server will automatically redirect all incoming HTTP requests to their HTTPS equivalents. - Default Value:
false
ssl.http_port
- JSON Key:
http_port
- Environment Variable:
SSL_HTTP_PORT
- Type:
integer
(u16, optional) - Description: The port number for the HTTP redirect server if
ssl.redirect_http
istrue
. - Default Value:
80
Example Configurations
Basic SSL Configuration
{
"ssl": {
"enabled": true,
"cert_path": "/etc/ssl/certs/sockudo.crt",
"key_path": "/etc/ssl/private/sockudo.key"
}
}
SSL with HTTP Redirect
{
"ssl": {
"enabled": true,
"cert_path": "/etc/letsencrypt/live/yourdomain.com/fullchain.pem",
"key_path": "/etc/letsencrypt/live/yourdomain.com/privkey.pem",
"redirect_http": true,
"http_port": 80
}
}
SSL with Encrypted Private Key
{
"ssl": {
"enabled": true,
"cert_path": "/etc/ssl/certs/sockudo.crt",
"key_path": "/etc/ssl/private/sockudo.key",
"passphrase": "yourSecretPrivateKeyPassword"
}
}
SSL with Client Certificate Authentication
{
"ssl": {
"enabled": true,
"cert_path": "/etc/ssl/certs/sockudo.crt",
"key_path": "/etc/ssl/private/sockudo.key",
"ca_path": "/etc/ssl/certs/ca-bundle.crt"
}
}
Environment Variable Configuration
export SSL_ENABLED=true
export SSL_CERT_PATH="/etc/ssl/certs/sockudo.crt"
export SSL_KEY_PATH="/etc/ssl/private/sockudo.key"
export SSL_REDIRECT_HTTP=true
export SSL_HTTP_PORT=80
Obtaining SSL/TLS Certificates
Let's Encrypt (Recommended for public servers)
Let's Encrypt provides free, automated SSL certificates. Use Certbot to obtain and manage certificates:
# Install Certbot
sudo apt-get update
sudo apt-get install certbot
# Obtain certificate (HTTP challenge)
sudo certbot certonly --standalone -d yourdomain.com
# Certificate files will be located at:
# /etc/letsencrypt/live/yourdomain.com/fullchain.pem
# /etc/letsencrypt/live/yourdomain.com/privkey.pem
Configure automatic renewal:
# Add to crontab
sudo crontab -e
# Add line for automatic renewal (runs twice daily)
0 12 * * * /usr/bin/certbot renew --quiet
Commercial Certificate Authorities
Purchase certificates from providers like:
- DigiCert
- Comodo
- GlobalSign
- GeoTrust
Self-Signed Certificates (Development/Testing ONLY)
# Generate private key
openssl genpkey -algorithm RSA -out privkey.pem -pkeyopt rsa_keygen_bits:2048
# Generate certificate signing request
openssl req -new -key privkey.pem -out cert.csr
# Answer prompts - use "localhost" for Common Name if testing locally
# Generate self-signed certificate
openssl x509 -req -days 365 -in cert.csr -signkey privkey.pem -out fullchain.pem
# Clean up
rm cert.csr
Warning: Self-signed certificates will show security warnings in browsers and should never be used in production.
Docker SSL Configuration
Volume Mount for Certificates
services:
sockudo:
image: sockudo/sockudo:latest
ports:
- "443:6001"
- "80:80"
volumes:
- /etc/letsencrypt:/etc/letsencrypt:ro
environment:
- SSL_ENABLED=true
- SSL_CERT_PATH=/etc/letsencrypt/live/yourdomain.com/fullchain.pem
- SSL_KEY_PATH=/etc/letsencrypt/live/yourdomain.com/privkey.pem
- SSL_REDIRECT_HTTP=true
Using Docker Secrets
version: '3.8'
services:
sockudo:
image: sockudo/sockudo:latest
ports:
- "443:6001"
secrets:
- ssl_cert
- ssl_key
environment:
- SSL_ENABLED=true
- SSL_CERT_PATH=/run/secrets/ssl_cert
- SSL_KEY_PATH=/run/secrets/ssl_key
secrets:
ssl_cert:
file: ./ssl/cert.pem
ssl_key:
file: ./ssl/key.pem
Reverse Proxy SSL Termination
In many production setups, you might terminate SSL/TLS at a reverse proxy and communicate with Sockudo over plain HTTP internally.
Nginx SSL Termination Example
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://localhost:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_connect_timeout 60s;
proxy_send_timeout 86400s;
proxy_read_timeout 86400s;
proxy_buffering off;
}
}
With this setup, configure Sockudo without SSL:
{
"ssl": {
"enabled": false
},
"host": "127.0.0.1",
"port": 6001
}
HAProxy SSL Termination Example
global
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2
frontend sockudo_frontend
bind *:443 ssl crt /etc/ssl/certs/sockudo.pem
bind *:80
redirect scheme https if !{ ssl_fc }
default_backend sockudo_backend
backend sockudo_backend
balance roundrobin
option httpchk GET /usage
server sockudo1 127.0.0.1:6001 check
server sockudo2 127.0.0.1:6002 check
SSL Certificate Management
Certificate Monitoring
Monitor certificate expiration:
# Check certificate expiration
openssl x509 -in /etc/ssl/certs/sockudo.crt -noout -dates
# Check certificate from remote server
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates
Automated Certificate Renewal
For Let's Encrypt with Certbot:
#!/bin/bash
# /etc/cron.daily/certbot-renew
# Renew certificates
/usr/bin/certbot renew --quiet
# Reload Sockudo if certificates were renewed
if [ $? -eq 0 ]; then
# Send SIGHUP to reload certificates (if Sockudo supports it)
# Or restart the service
systemctl reload sockudo
fi
Certificate Validation Script
#!/bin/bash
# validate-ssl.sh
DOMAIN="yourdomain.com"
PORT="6001"
# Check if certificate is valid
echo | openssl s_client -connect ${DOMAIN}:${PORT} -servername ${DOMAIN} 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
# Check certificate chain
echo | openssl s_client -connect ${DOMAIN}:${PORT} -servername ${DOMAIN} 2>/dev/null | \
openssl x509 -noout -text | grep -A1 "X509v3 Subject Alternative Name"
Security Best Practices
Certificate Security
- Keep private keys secure with restrictive file permissions (600 or 640)
- Use strong key lengths (2048-bit RSA minimum, 4096-bit recommended)
- Implement proper certificate chain including intermediate certificates
- Monitor certificate expiration and automate renewal
SSL/TLS Configuration
- Disable weak protocols (SSLv3, TLSv1.0, TLSv1.1)
- Use strong cipher suites and prefer server cipher order
- Enable HTTP Strict Transport Security (HSTS)
- Implement certificate transparency monitoring
File Permissions
# Set proper permissions for SSL files
sudo chown root:sockudo /etc/ssl/private/sockudo.key
sudo chmod 640 /etc/ssl/private/sockudo.key
sudo chown root:root /etc/ssl/certs/sockudo.crt
sudo chmod 644 /etc/ssl/certs/sockudo.crt
Performance Considerations
SSL Performance Optimization
- Use hardware acceleration if available (AES-NI)
- Enable SSL session resumption
- Use OCSP stapling to reduce handshake time
- Consider TLS 1.3 for improved performance
Load Balancing with SSL
When using multiple Sockudo instances with SSL:
{
"ssl": {
"enabled": true,
"cert_path": "/shared/ssl/cert.pem",
"key_path": "/shared/ssl/key.pem"
}
}
Ensure certificates are accessible to all instances via shared storage.
Troubleshooting SSL Issues
Common Problems
Certificate Not Found
# Check if files exist and are readable
ls -la /etc/ssl/certs/sockudo.crt
ls -la /etc/ssl/private/sockudo.key
# Check file permissions
sudo -u sockudo cat /etc/ssl/private/sockudo.key
Certificate/Key Mismatch
# Compare certificate and key
openssl x509 -noout -modulus -in /etc/ssl/certs/sockudo.crt | md5sum
openssl rsa -noout -modulus -in /etc/ssl/private/sockudo.key | md5sum
# Should produce identical hashes
Certificate Chain Issues
# Verify certificate chain
openssl verify -CAfile /etc/ssl/certs/ca-bundle.crt /etc/ssl/certs/sockudo.crt
# Check certificate chain completeness
echo | openssl s_client -connect yourdomain.com:6001 -servername yourdomain.com
SSL Handshake Failures
# Test SSL connection
openssl s_client -connect localhost:6001 -servername localhost
# Test with specific TLS version
openssl s_client -connect localhost:6001 -tls1_2
openssl s_client -connect localhost:6001 -tls1_3
Debug Commands
# Check Sockudo SSL configuration
curl -k https://localhost:6001/usage
# Test WebSocket SSL connection
wscat -c wss://localhost:6001/app/demo-key
# Check certificate details
openssl x509 -in /etc/ssl/certs/sockudo.crt -text -noout
# Validate private key
openssl rsa -in /etc/ssl/private/sockudo.key -check
# Test SSL configuration
nmap --script ssl-enum-ciphers -p 6001 localhost
SSL Health Check Script
#!/bin/bash
# ssl-health-check.sh
DOMAIN="localhost"
PORT="6001"
echo "Checking SSL configuration for ${DOMAIN}:${PORT}"
# Check if port is listening
if ! nc -z ${DOMAIN} ${PORT}; then
echo "ERROR: Port ${PORT} is not listening"
exit 1
fi
# Check SSL certificate
CERT_INFO=$(echo | openssl s_client -connect ${DOMAIN}:${PORT} 2>/dev/null | openssl x509 -noout -dates 2>/dev/null)
if [ $? -eq 0 ]; then
echo "SSL certificate information:"
echo "${CERT_INFO}"
# Check expiration
EXPIRY=$(echo "${CERT_INFO}" | grep "notAfter" | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "${EXPIRY}" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_UNTIL_EXPIRY=$(( (EXPIRY_EPOCH - CURRENT_EPOCH) / 86400 ))
echo "Days until expiration: ${DAYS_UNTIL_EXPIRY}"
if [ ${DAYS_UNTIL_EXPIRY} -lt 30 ]; then
echo "WARNING: Certificate expires in less than 30 days"
fi
else
echo "ERROR: Could not retrieve SSL certificate"
exit 1
fi
echo "SSL configuration check completed"
Important Considerations
Certificate Formats
- PEM Format: Most common, ASCII-encoded
- DER Format: Binary-encoded
- PKCS#12: Combined certificate and key file
Sockudo expects PEM format certificates.
Certificate Chain Order
Ensure proper certificate chain order in your certificate file:
- Server certificate (first)
- Intermediate certificates
- Root certificate (optional, usually not included)
Wildcard Certificates
Wildcard certificates (*.yourdomain.com) can be used with Sockudo:
{
"ssl": {
"enabled": true,
"cert_path": "/etc/ssl/certs/wildcard.yourdomain.com.crt",
"key_path": "/etc/ssl/private/wildcard.yourdomain.com.key"
}
}
Multi-Domain Certificates (SAN)
Subject Alternative Name (SAN) certificates supporting multiple domains work seamlessly with Sockudo.
By following these SSL/TLS configuration guidelines, you can ensure secure, encrypted communication between your clients and Sockudo server while maintaining optimal performance and security standards.