Servidor web Apache no Rocky Linux 9, com certificados SSL obtidos da LetsEncrypt. Esta é a configuração de um host virtual específico "myvhost", mas o problema surge para todos os vhosts no meu servidor:
/etc/httpd/conf.d/myvhost.conf
:
<VirtualHost *:80>
ServerName myvhost.example.org
DocumentRoot "/var/www/html/myvhost"
RewriteEngine on
RewriteCond %{SERVER_NAME} =myvhost.example.org
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
/etc/httpd/conf.d/myvhost-le-ssl.conf
(gerado automaticamente por LetsEncrypt):
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName myvhost.example.org
DocumentRoot "/var/www/html/myvhost"
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
TraceEnable off
SSLCertificateFile /etc/letsencrypt/live/example.org-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.org-0001/privkey.pem
</VirtualHost>
</IfModule>
O comando curl -i http://myvhost.example.org
retorna:
HTTP/1.1 400 Bad Request
Date: Wed, 19 Jun 2024 12:39:10 GMT
Server: Apache
Content-Length: 362
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
</p>
</body></html>
Por que ele está fazendo isso? Entre outras coisas, o erro HTTP 400 impede certbot renew
a verificação do domínio e a renovação do certificado.
É importante notar que exatamente a mesma configuração no CentOS Stream 8 não resultou neste problema.
EDIT: saída do comando for f in $(grep -l -e SSLCertificate -e :80 /etc/httpd/conf.d/*.conf); do printf '\n== %s ==\n' "$f"; grep -hE 'SSLCertificate|VirtualHost|Server(Name|Alias)' "$f" | sed -e 's/#.*//' -e '/^[[:space:]]*$/d'; done | less
:
== /etc/httpd/conf.d/main-le-ssl.conf ==
<VirtualHost *:443>
ServerName example.org
SSLCertificateFile /etc/letsencrypt/live/example.org-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.org-0001/privkey.pem
</VirtualHost>
== /etc/httpd/conf.d/main.conf ==
<VirtualHost *:80>
ServerName example.org
</VirtualHost>
== /etc/httpd/conf.d/myvhost-le-ssl.conf ==
<VirtualHost *:443>
ServerName myvhost.example.org
SSLCertificateFile /etc/letsencrypt/live/example.org-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.org-0001/privkey.pem
</VirtualHost>
== /etc/httpd/conf.d/myvhost.conf ==
<VirtualHost *:80>
ServerName myvhost.example.org
</VirtualHost>
== /etc/httpd/conf.d/anothervhost-le-ssl.conf ==
<VirtualHost *:443>
ServerName anothervhost.example.org
SSLCertificateFile /etc/letsencrypt/live/example.org-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.org-0001/privkey.pem
</VirtualHost>
== /etc/httpd/conf.d/anothervhost.conf ==
<VirtualHost *:80>
ServerName anothervhost.example.org
</VirtualHost>
== /etc/httpd/conf.d/ssl.conf ==
SSLCertificateFile /etc/letsencrypt/live/example.org-0001/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.org-0001/privkey.pem
Execute isto e inspecione a saída:
Os derivados do Debian precisarão mudar
/etc/httpd/conf.d/*.conf
para/etc/apache2/sites-enabled/*.conf
Ele mostrará uma representação (muito) reduzida de sua configuração. Você está procurando um Host Virtual ( vHost ) na porta 80 que contém diretivas SSL ou diretivas SSL fora de uma seção vHost.
Ao ver sua saída, esta segunda situação foi realmente o caso:
(Presumivelmente
SSLEngine on
também presente, embora o código original em um comentário tenha omitido essa linha específica.)O que acontece é que a presença das
SSLEngine on
diretivas habilita o SSL (razoavelmente). Portanto, quando está dentro de um Host Virtual específico, é apenas aquele vHost que está habilitado para SSL. Mas como você tinha as diretivas globalmente, fora de qualquer vHost, o SSL estava habilitado em todos os lugares. Você deveria então ter desabilitado o SSL para os vHosts que estavam escutando na porta 80 com a diretivaSSLEngine off
.