Apache 2.4如何拒绝非预期Host头并返回403 Forbidden?
问题描述
我想拒绝所有非预期的Host头请求,以此阻止mod_pagespeed缓存文件夹生成大量无效目录(示例如下):
/var/cache/mod_pagespeed/v3/mysite.com/https,3A/,2Fdemo.mysite.com/%2C2Fwp-content /var/cache/mod_pagespeed/v3/mysite.com/https,3A/,2Fdemo.mysite.com/%2C2Fwp-includes ...
参考Nginx的配置思路,我在Apache 2.4服务器的/etc/apache2/sites-enabled/000-default-le-ssl.conf文件顶部添加了如下配置:
<VirtualHost *:80> ServerName catchall <Location /> Require all denied </Location> <Location /var/www/html/> Require all denied </Location> </VirtualHost>
执行测试命令:
wget --header="Host: example.com" http://demo.mysite.com
得到的响应是301永久重定向而非403 Forbidden,还出现了重定向循环。请问为何会出现这种情况?如何配置才能让所有未知Host头请求返回403?
更新后的配置
我按照建议修改了配置文件,当前两个配置文件内容如下:
/etc/apache2/sites-enabled/000-default.conf
# Added to mitigate CVE-2017-8295 vulnerability UseCanonicalName On <VirtualHost *:80> ServerName catchall </VirtualHost> <VirtualHost *:443> ServerName catchall SSLCertificateFile /etc/letsencrypt/live/demo.mysite.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/demo.mysite.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf </VirtualHost>
/etc/apache2/sites-enabled/001-demo.mysite.com.conf
<VirtualHost *:80> ServerName demo.mysite.com ServerAlias demo.mysite.com <Directory /var/www/html/> Options FollowSymLinks AllowOverride All Require all granted </Directory> RewriteEngine on RewriteCond %{SERVER_NAME} =demo.mysite.com [OR] RewriteCond %{SERVER_NAME} =www.demo.mysite.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@localhost ServerName demo.mysite.com ServerAlias www.demo.mysite.com UseCanonicalName On UseCanonicalPhysicalPort On Protocols h2 http/1.1 DocumentRoot /var/www/html <Directory /var/www/html/> Options FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined SSLCertificateFile /etc/letsencrypt/live/demo.mysite.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/demo.mysite.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf </VirtualHost> </IfModule>
问题分析与解决方案
为什么出现301重定向循环?
- 虚拟主机匹配优先级问题:Apache会优先匹配最具体的虚拟主机配置,你初始配置中的catchall主机没有被优先匹配——请求先落到了
demo.mysite.com的80端口虚拟主机上,触发了HTTPS重写规则返回301。当重定向后的HTTPS请求仍带着非法Host头时,又无法匹配到正确的SSL虚拟主机,进而再次被重定向,形成循环。 Location配置错误:<Location /var/www/html/>是错误写法,Location指令基于URL路径而非文件系统路径,控制文件系统目录权限应该用<Directory>指令。
正确配置方案
要让所有未知Host头请求返回403,需确保catchall虚拟主机是Apache匹配的第一个虚拟主机(Apache会把第一个匹配端口的虚拟主机作为默认主机),并在其中明确拒绝所有请求,同时覆盖HTTP和HTTPS两种端口。
调整后的完整配置
1. 默认catchall主机(000-default.conf)
该文件需以000开头确保加载顺序优先,作为未匹配Host头请求的默认处理:
# 启用规范名称,避免Host头伪造带来的路径问题 UseCanonicalName On # HTTP 80端口默认主机:拒绝所有请求 <VirtualHost *:80> ServerName catchall # 直接拒绝所有请求 Require all denied </VirtualHost> # HTTPS 443端口默认主机:拒绝所有请求 <VirtualHost *:443> ServerName catchall # Apache要求SSL虚拟主机必须配置证书,可复用现有站点证书 SSLCertificateFile /etc/letsencrypt/live/demo.mysite.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/demo.mysite.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf # 拒绝所有请求 Require all denied </VirtualHost>
2. 业务站点主机(001-demo.mysite.com.conf)
保留原有HTTPS重定向和站点配置,确保只有匹配合法Host头的请求才进入该虚拟主机:
<VirtualHost *:80> ServerName demo.mysite.com ServerAlias www.demo.mysite.com <Directory /var/www/html/> Options FollowSymLinks AllowOverride All Require all granted </Directory> # 仅对合法Host头的请求做HTTPS重定向 RewriteEngine on RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@localhost ServerName demo.mysite.com ServerAlias www.demo.mysite.com UseCanonicalName On UseCanonicalPhysicalPort On Protocols h2 http/1.1 DocumentRoot /var/www/html <Directory /var/www/html/> Options FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined SSLCertificateFile /etc/letsencrypt/live/demo.mysite.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/demo.mysite.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf </VirtualHost> </IfModule>
关键注意事项
- 加载顺序:确保catchall配置文件(
000开头)在业务站点配置文件之前加载,Apache按文件名顺序加载sites-enabled下的配置,000会先于001被加载,成为对应端口的默认虚拟主机。 - SSL证书:HTTPS的catchall虚拟主机必须配置SSL证书,否则Apache启动会失败,可复用现有站点证书或生成自签证书。
UseCanonicalName:启用该指令会让Apache忽略请求中的Host头,使用配置的ServerName生成链接,进一步减少mod_pagespeed基于非法Host头生成缓存的可能。
测试验证
执行以下命令测试非法Host头请求:
# 测试HTTP请求 wget --header="Host: example.com" http://demo.mysite.com # 测试HTTPS请求 wget --header="Host: example.com" https://demo.mysite.com
正常情况下应返回403 Forbidden,不会出现重定向。
内容的提问来源于stack exchange,提问作者wheretheresawill
相关产品推荐
相关产品推荐

