Apache Serving Up Wrong Certs

This seems to be a common problem, and apparently most people give up and buy an IP address for each individual domain. How can virtual domains be so broken for years?

I go to quantum-equities.com and get:
Bad Request
Your browser sent a request that this server could not understand.
Reason: You’re speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

So I go to https://quantum-equities.com and get:
Your connection is not secure
The owner of quantum-equities.com has configured their website improperly. To protect your information from being stolen, Firefox has not connected to this website.

I check the cert it’s using and it’s the server’s local self-signed cert at /etc/pki/tls/certs/localhost.crt rather than the LetsEncrypt cert for this site.

Huh? I’ve set the cert properly and it exists there. I’ve carefully walked down
/etc/letsencrypt/archive/quantum-equities.com/* and granted Apache group permission to enter the directories and read files. I’ve disabled selinux. There are no errors in /var/log/httpd/ssl_error_log


<VirtualHost *>
        ServerAdmin postmaster@quantum-equities.com
        DocumentRoot "/srv/www/QE"
        <Directory "/srv/www/QE">
                Options Indexes FollowSymLinks
                AllowOverride None
                # Allow open access:
                Require all granted
        </Directory>
        ServerName quantum-equities.com
        ServerAlias www.quantum-equities.com
        ServerAlias mail.quantum-equities.com
        SSLEngine On
        SSLCertificateFile /etc/letsencrypt/live/quantum-equities.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/quantum-equities.com/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/quantum-equities.com/chain.pem
        SSLProtocol All -SSLv2
        SSLCipherSuite HIGH:MEDIUM:!aNULL:+MD5
        ErrorLog logs/QE-ssl_error_log
        TransferLog logs/QE-ssl_access_log
        LogLevel warn
        ErrorLog "/var/log/httpd/quantum-equities-error_log"
        CustomLog "/var/log/httpd/quantum-equities-access_log" common
</VirtualHost>

Has anyone solved this? I am about to give up on all this.

This is probably because of the <VirtualHost *>. It doesn't specify a port, so it matches both HTTP (port 80) and HTTPS (port 443). You've therefore enabled HTTPS on port 80 as well as port 443, which is why http://quantum-equities.com doesn't work. Use <VirtualHost *:443> instead.

EDIT: to clarify, you need a <VirtualHost *:443> for the HTTPS version of your site, and a separate <VirtualHost *:80> for the HTTP version (even if it's just a redirect).

This is probably because of a conflict between different VirtualHosts in your Apache configuration. Try something like this to help identify the problem:

grep -riE 'virtualhost|server(name|alias)' /etc/httpd
2 Likes

Thanks, but I’ve found the exact solution here:

All I had to do was edit /etc/httpd/conf.d/ssl.conf and comment out everything to do with {Virtualhost} there. Using {VirtualHost *} in my file works just fine.
https://quantum-equities.com

Yes, your HTTPS site is working fine now, and if you’re happy with just that, that’s great :slight_smile: but http://quantum-equities.com/ is still broken - anyone visiting it will receive the same 400 error as before. You might want to fix that and add a redirect instead.

2 Likes

That’s what I’ve just been trying. I used to use an .htaccess redirect, but it doesn’t work now for some reason.

RewriteEngine on

Enable https (LetsEncrypt.com)

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.) https://%{HTTP_HOST}:443%{REQUEST_URI}
RewriteCond %{HTTP_HOST} !^(www.)?quantum-equities.com$ [NC]
RewriteRule ^(.
)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

@jmorahan already explained why in his first reply.

Right, it doesn’t work because of the <VirtualHost *>. The server is listening for HTTPS on port 80, rather than HTTP. You can confirm this by visiting https://quantum-equities.com:80 to connect to port 80 over HTTPS.

So you want to change your <VirtualHost *> to <VirtualHost *:443>, and add a new <VirtualHost *:80> just for HTTP, with no SSL directives in it.

Also…

  • I don’t think you need the :443 in the first RewriteRule
  • and the second one doesn’t seem to do anything useful… perhaps you meant %{SERVER_NAME} rather than %{HTTP_HOST}?

I see now, thanks.

I would much rather have the redirect in my virt hosts file (rather than .htaccess), and to have ‘AllowOverride None’ for security reasons.

Twerks now.

Do I still need ‘ServerAlias mail.quantum-equities.com’ now that I have my certs working?


<VirtualHost *:80>
ServerName quantum-equities.com
DocumentRoot "/srv/www/QE"
Redirect / https://quantum-equities.com/

<VirtualHost *:443>
DocumentRoot “/srv/www/QE”
<Directory “/srv/www/QE”>
Options Indexes FollowSymLinks
AllowOverride None
# Allow open access:
Require all granted

ServerName quantum-equities.com
ServerAlias www.quantum-equities.com
ServerAlias mail.quantum-equities.com
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/quantum-equities.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/quantum-equities.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/quantum-equities.com/chain.pem
SSLProtocol All -SSLv2
SSLCipherSuite HIGH:MEDIUM:!aNULL:+MD5
LogLevel warn
ErrorLog logs/QE-ssl_error_log
TransferLog logs/QE-ssl_access_log


Hmm... probably not. If you remove it, you can test if renewal still works correctly by using certbot renew --dry-run. Usually it should, unless the rest of your configuration is very unusual.

I could only do a certonly as I can’t get certs for one of my domains. But it does work without “ServerAlias mail.quantum-equities.com

But something else I learned is that my renewal file may not work as I have it:


[Unit]
Description=Service for SSL cert renewals

[Service]
#EnvironmentFile=/etc/sysconfig/certbot
Type=oneshot
ExecStart=/usr/bin/certbot renew -d quantum-equities.com,www.quantum-equities.com,mail.quantum-equities.com
ExecStart=/usr/bin/certbot renew -d quantum-sci.com,www.quantum-sci.com,mail.quantum-sci.com
ExecStart=/usr/bin/certbot renew -d delphi-real-estate.com,www.delphi-real-estate.com,mail.delphi-real-estate.com --apache

Security

PrivateTmp=yes
InaccessibleDirectories=/bin /boot /home /media /mnt /opt /root /sbin /sys
ReadOnlyDirectories=/lib /lib64 /usr
CapabilityBoundingSet=~CAP_SYS_PTRACE
DeviceAllow=/dev/null rw
NoNewPrivileges=yes


Seems that you’re not supposed to name the domains for renewal, but how else would it know all my SANs?

It extracts the information from your existing certificates :slight_smile:
And you only need to run it once (per cron or timer run); it will examine all your certificates and determine automatically which ones need to be renewed. You also don’t need to specify --apache as the plugin that was used is also remembered. This information is stored in /etc/letsencrypt/renewal.

Oh, OK, I was told when I asked about this specifically, that certbot does not restart apache.

The way I originally got the certs is with certonly, and option 2, so the Apache plugin was not used. Don’t I need --apache then?

You shouldn't try to change the plugin when renewing with certbot renew; if you're not happy with the plugin that was used before, you can renew with certonly --force-renew and change the plugin at that time.

certonly never restarts Apache because it doesn't use an installer at all. In order to use an installer plugin, you would need to have used the (default) run command instead of certonly. (The meaning of certonly is "I only want the certificate, I don't want Certbot to install it for me".)

If you want to restart Apache when using a different plugin and/or using certonly, you can add a --deploy-hook option (which doesn't need to be respecified every time) for a service apache reload or similar command.

1 Like

Here’s a simple Apache config example for you.

# PORT 443 SSL CONFIG
# *******************

<IfModule mod_ssl.c>
<VirtualHost *:443>
DocumentRoot /var/www/mysite/
ServerName mysite.com
ServerAlias www.mysite.com
ErrorLog ${APACHE_LOG_DIR}/mysite-error.log
CustomLog ${APACHE_LOG_DIR}/mysite-access.log

<Directory "/var/www/mysite/">
Options +Includes
Options +FollowSymLinks -Indexes
</Directory>

SSLCertificateFile /etc/letsencrypt/live/mysite.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mysite.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /etc/letsencrypt/live/mysite.com/chain.pem
</VirtualHost>
</IfModule>

# PORT 80 REDIRECT CONFIG
# ***********************

<VirtualHost *:80>
ServerName mysite.com
ServerAlias www.mysite.com
ErrorLog ${APACHE_LOG_DIR}/mysite-error.log
CustomLog ${APACHE_LOG_DIR}/mysite-access.log
Redirect permanent / https://mysite.com/
</VirtualHost>

Oh, I was told to use certonly, but maybe that was for troubleshooting.

I've heard back from my registrar, and I don't understand why delphi-real-estate.com was represented as DNSSEC (as opposed to the others), but to solve it he just turned DNSSEC on. His explanation isn't clear, but I now have my delphi cert and all domains are now cranking.


"_After reviewing your domain configurations, The domain was not signed with DNSSEC, even though you had your Delegation Signer Records. By turning on DNSSEC is the DNS Configuration panel, it added the DNSKEY and RRSIGs to the domain. And synchronized properly. I was able to verify that DNSSEC is working through verisignlab's DNSSEC debugger, you can also check with the link below. _
_DNSSEC Analyzer - delphi-real-estate.com_"


Somehow he's enabled DNSSEC -- I'd thought that DNSSEC required the domain's cert, but I haven't gotten to that part yet so maybe I'm wrong. The certbot renew --dry-run now works perfectly. I've removed the cron entry and made a systemd timer for it:


[Unit]
Description=Timer for SSL cert renewals

[Timer]
# Realtime timer
OnCalendar=05:20,12:20
Persistent=true

[Install]
WantedBy=timers.target

CentOS7's certbot package comes with a certbot-renew.service and certbot-renew.timer, but both are inadequate to me. So in /usr/local/lib/systemd/systemd I made a letsencrypt.timer (above) and letsencrypt.service. The .service must have the same name as the .timer, and you 'systemctl enable/start' the timer, not the service. Systemd timers are intended to eventually replace cron's.

I've now changed all the certs to rely on the Apache plugin, thanks Schoen.

Nice, thanks Mitchell. Your config actually redirects www. correctly, as opposed to mine. I've converted everything to your format. There is some problem with the CustomLog entry but I'll figure that out.

1 Like

If the custom log settings are giving you hassles you can just specify the full path /var/log/apache2/mywebsite-access.log and same for error log.

I made it simple as:
CustomLog /var/log/httpd/delphi-real-estate-access.log “%H %m %t %h %a %u %U”

Sorry, I did mean using certonly as well, so I probably should have said certbot certonly --force-renew :slight_smile:

Nope, DNSSEC is independent of certificates. You can have a certificate for a domain that has never used DNSSEC, and you can have DNSSEC for a domain that has never used a certificate.

Certificates confirm a site's public key for TLS connections, while DNSSEC cryptographically confirms the validity of any DNS entry, most importantly reflecting the site's IP address. So they are typically providing different information and also issued by different authorities.

There are a couple of sort-of interactions between them:

  • If your DNSSEC records are invalid or don't verify, Let's Encrypt won't issue you a new certificate until the problem is fixed. However, you aren't required to use DNSSEC at all in order to get a certificate.
  • There's another protocol called DANE if you want to declare public key information directly in DNS records, which is used in conjunction with DNSSEC. DNS-based Authentication of Named Entities - Wikipedia However, the use of DANE is also optional and it is not very widely supported on the client side yet.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.