How to Fix “Connection Refused” HTTPS Error in Apache: SSL Configuration Debugging Guide


2 views

When your Apache server returns "Connection Refused" for HTTPS requests while HTTP works fine, you're typically facing one of these scenarios:

1. Local connection works but external fails
2. Telnet to port 443 times out
3. Apache logs show SSL handshake errors
4. Server responds to HTTP but not HTTPS

First, verify these fundamental settings in your Apache configuration:

# Check if SSL module is loaded
apachectl -M | grep ssl

# Verify port listening
netstat -tulnp | grep 443
ss -tulnp | grep 443

# Test SSL handshake externally
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com

Your VirtualHost configuration should include these essential elements:

<VirtualHost *:443>
    ServerName api.example.com
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/privkey.pem
    SSLCertificateChainFile /path/to/chain.pem
    
    # Modern SSL configuration (adjust for your needs)
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5:!RC4
    SSLHonorCipherOrder on
    
    # Other directives...
</VirtualHost>

Check these system-level configurations that might block HTTPS traffic:

# Check iptables rules
iptables -L -n -v | grep 443

# For UFW (Ubuntu)
ufw status verbose

# For firewalld (CentOS/RHEL)
firewall-cmd --list-all

# Test connectivity bypassing local firewall
curl -vk https://localhost

Validate your certificate chain with these commands:

# Verify certificate file
openssl x509 -in api_my_site_com.crt -text -noout

# Verify private key matches certificate
openssl x509 -noout -modulus -in api_my_site_com.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5

# Test full chain
openssl verify -CAfile apimysite.com-bundle api_my_site_com.crt

Increase log verbosity to pinpoint SSL handshake failures:

# In your VirtualHost configuration
LogLevel debug
ErrorLog /var/log/apache2/ssl_error.log
CustomLog /var/log/apache2/ssl_access.log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

For modern browsers and multiple SSL sites on one IP:

# Ensure this appears before any VirtualHost blocks
NameVirtualHost *:443

# Each VirtualHost needs its own ServerName and certificates
<VirtualHost *:443>
    ServerName site1.example.com
    SSLCertificateFile /path/to/site1.crt
    # ... other directives
</VirtualHost>

<VirtualHost *:443>
    ServerName site2.example.com
    SSLCertificateFile /path/to/site2.crt
    # ... other directives
</VirtualHost>

After making changes, perform these final checks:

# Check configuration syntax
apachectl configtest

# Graceful restart
systemctl reload apache2
# or
service apache2 reload

# External validation tools
# SSL Labs test: https://www.ssllabs.com/ssltest/

When you encounter a "Connection Refused" error for HTTPS while Apache appears to be running correctly with SSL configured, we need to examine several technical aspects systematically. The error logs showing "SSL library error 1 in handshake" and "unknown protocol speaking not SSL to HTTPS port" indicate a protocol negotiation failure.

# Verify Apache SSL module status
apache2ctl -M | grep ssl_module
# Should output: ssl_module (shared)

# Check port binding
netstat -tulnp | grep 443
# Should show Apache listening on 443:
# tcp6 0 0 :::443 :::* LISTEN 1234/apache2

The certificate file paths need absolute verification:

# Check certificate files exist
ls -la /etc/ssl/ssl.key/server.key
ls -la /etc/ssl/ssl.crt/api_my_site_com.crt
ls -la /etc/ssl/ssl.crt/apimysite.com-bundle

For Apache 2.4+, some directives need adjustment:

<VirtualHost *:443>
    ServerName api.example.com
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/privkey.pem
    SSLCertificateChainFile /path/to/chain.pem
    
    # Modern security settings
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLHonorCipherOrder on
</VirtualHost>

Common network-related issues to verify:

# Check local firewall rules
iptables -L -n -v | grep 443
ufw status | grep 443

# Test connectivity from another server
telnet your-server-ip 443
openssl s_client -connect your-domain.com:443 -servername your-domain.com

Proper certificate chain configuration is crucial. Here's how to verify:

openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /etc/ssl/ssl.crt/api_my_site_com.crt

# Or for full chain verification
cat /etc/ssl/ssl.crt/api_my_site_com.crt /etc/ssl/ssl.crt/apimysite.com-bundle > fullchain.pem
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt fullchain.pem

Use curl for detailed SSL handshake analysis:

curl -vI https://api.example.com
# Look for:
# * SSL connection using TLS_...
# * Server certificate verification

Ensure your virtual host includes these essential elements:

Listen 443 https
<VirtualHost _default_:443>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLCertificateFile      /path/to/signed_cert_plus_intermediates
    SSLCertificateKeyFile   /path/to/private/key
    SSLCertificateChainFile /path/to/intermediate_certificate
    
    # HSTS for modern security
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
</VirtualHost>
  • Certificate file permissions: Ensure Apache user has read access to all certificate files
  • Protocol mismatch: Modern browsers may reject older SSL protocols - disable SSLv3
  • Chain certificate order: Intermediate certificates must be in correct order in bundle file
  • Mixed content: Page elements loading over HTTP will trigger browser warnings

For deeper troubleshooting:

# Check Apache's SSL configuration
apache2ctl -t -D DUMP_VHOSTS -D DUMP_RUN_CFG

# Test SSL configuration remotely
testssl.sh api.example.com

# Verify certificate expiration
openssl x509 -noout -dates -in /etc/ssl/ssl.crt/api_my_site_com.crt