Rocky Linux 9 上的 Apache 网络服务器,具有从 LetsEncrypt 获得的 SSL 证书。这是特定虚拟主机“myvhost”的配置,但我的服务器上的所有虚拟主机都出现了问题:
/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
(由 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>
命令curl -i http://myvhost.example.org
返回:
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>
为什么会这样?除其他外,HTTP 错误 400 阻止certbot renew
验证域和更新证书。
值得注意的是,在 CentOS Stream 8 上完全相同的配置并没有导致这个问题。
编辑:命令的输出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
运行此程序并检查输出:
Debian 衍生版本需要更改
/etc/httpd/conf.d/*.conf
为/etc/apache2/sites-enabled/*.conf
它将向您显示 (非常) 精简的配置表示。您正在寻找端口 80 上的虚拟主机 ( vHost ),其中包含 SSL 指令或 vHost 部分之外的 SSL 指令。
看到你的输出后,第二种情况确实如此:
(大概也存在,尽管注释
SSLEngine on
中的原始代码省略了那一行。)实际情况是,这些指令的存在
SSLEngine on
会启用 SSL(足够合理)。因此,当它在特定虚拟主机内时,只有该虚拟主机启用了 SSL。但是由于您全局拥有这些指令,因此在任何虚拟主机之外,SSL 在所有地方都启用。然后,您应该使用指令禁用正在侦听端口 80 的虚拟主机的 SSLSSLEngine off
。