AWS- 子域不支持 HSTS
AWS- subdomain doesn't support HSTS
我正在使用 Semrush,我收到了一条通知,它真的很困扰我,我想摆脱它。 1 个子域不支持子域的 HSTS:www.domain.com,这是我的 .htdocs 文件:
Options -Indexes
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/ [L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_USER_AGENT} ^(.+)$
RewriteCond %{SERVER_NAME} ^example\.com$
RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Header add Strict-Transport-Security "max-age=300"
</IfModule>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header always set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
我把这部分加在最后:
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header always set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
但是还是没有,我哪里做错了?
您是否尝试过通过 DNS 记录和 .vconfig 文件修复此问题?对于我的网站,我有:
- 主域的 DNS A 记录 (
A domain.com 123.123.123.123
)
- www 的第二个 DNS A 记录 (
A www 123.123.123.123
)
然后在 domain.com.vhost:
<VirtualHost *:80>
DocumentRoot /var/www/path_to_root
ServerName domain.com
ServerAlias domain.com
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
</VirtualHost>
重写规则强制使用 HTTPS。
如果您想为特定域强制使用 HTTPS,无论是在 .vhost 还是 .htaccess 中,您都可以使用:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain1.com [NC]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
对于特定文件夹:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(folder1|folder2|folder3) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
确保将文件夹引用更改为实际目录名称。
如果您能够通过 Cloudflare 路由您的 DNS(即使是他们的免费计划),您将能够通过单击按钮启用 HSTS(包括子域)。在速度和安全性方面还有很多其他好处,这也可能有助于您的 SEMRush 报告
Options -Indexes
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/ [L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_USER_AGENT} ^(.+)$
RewriteCond %{SERVER_NAME} ^example\.com$
RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Header add Strict-Transport-Security "max-age=300"
</IfModule>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header always set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
这里有许多问题会阻止 HSTS 正常工作,并且应该进行一些额外的优化。
您没有将 http://www.example.com
(即 www 子域)重定向到 HTTPS。您需要将 HTTP+WWW 重定向到 HTTPS+WWW 才能符合 HSTS。
您正在重定向 http://example.com/
(即 HTTP + non-www)到 HTTPS + WWW。为了符合 HSTS,您需要先在 同一主机 上重定向到 HTTPS。 IE。 http://example.com/
到 https://example.com/
到 https://www.example.com
(是的,这是两个重定向,但它也很少见,并且每个 user-agent 最多只会出现一次,因为 STS header 返回)。
您的指令顺序错误。您的规范重定向(即 HTTP 到 HTTPS 和 non-www 到 www)需要 before 您的 front-controller 重写(第一条规则)。通过将它们放在 front-controller 之后,除了主页、目录和静态资源之外,它们永远不会被处理。例如。 http://example.com/<some-url>
永远不会被所写的规则重定向。不确定您如何测试 HSTS 与 SEMrush 的合规性,但是使用当时编写的指令 http://example.com/<some-url>
会失败,因为它没有被重定向。
您应该删除第一个 Header
指令 - 这与第二个(正确的)Header
指令直接冲突。 always
条件(在第二个实例中使用)是必需的,以便将 header 设置为
HTTPS 301 重定向(即非 2xx 响应)从 non-www 到 www.
您应该在 Strict-Transport-Security
header 中包含 includeSubDomains
指令,以便在请求域顶点时覆盖 www 子域。不过,所有 子域现在都将被隐式包含在内。否则,需要明确请求 www 子域。 (好吧,无论如何你都将在下一个请求中重定向到 www。)
您应该删除 <IfModule>
包装器;他们不是必需的。这些指令是强制性的,它们不是 可选的 (这些包装器的存在暗示了这一点)。如果 mod_rewrite 不可用,您的站点可能会失败,并且您将不符合 HSTS。
有关此问题的更多信息,请参阅 my answer 网站管理员堆栈中的以下问题:
Is Checking for mod_rewrite Really Necessary?
我从早期的 HTTP + non-www 重定向假设你不在管理你的 SSL 的 front-end 代理(或负载平衡器)后面,在这种情况下检查for %{HTTP:X-Forwarded-Proto}
in the later <If>
expression should be removed.如果您不在“代理”后面,则可以伪造请求以防止 STS
header 被发回(用户不应该这样做)。
相反,如果您在“代理”后面,那么检查 %{REQUEST_SCHEME} == 'https'
是多余的 - 但不会造成任何伤害。顺便说一句,REQUEST_SCHEME
的使用假定您使用的是 Apache 2.4+(我希望您是),但是,如果您仍在使用 Apache 2.2,则此检查将失败并且 STS header 将不会设置。
所以,考虑到以上几点,你的.htaccess
文件应该这样写:
Options +FollowSymLinks -Indexes
RewriteEngine On
# Redirect HTTP to HTTPS on the same host (requirement of HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect non-www to www (HTTPS only)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Front-controller
RewriteRule ^index\.php/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/ [L]
<If "%{REQUEST_SCHEME} == 'https'>
# The "always" condition is required to set the header on the HTTPS redirect
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</If>
补充说明:
我使用 HTTP_HOST
而不是 SERVER_NAME
因为您 需要 请求中的主机名。默认情况下 SERVER_NAME
与 HTTP_HOST
相同,但这可能因服务器配置而异。
没有理由仅在请求中存在 non-empty User-Agent 字符串时才应用规范重定向(恶意请求可能会抑制 User-Agent string) 和原来一样,所以我删除了这个条件。如果有的话,你会阻止这样的请求。
RewriteRule
模式中的正则表达式^
比.*
更优化,因为它只需要成功 - 它实际上不需要 匹配 任何东西,因为它以后不会被使用。
“front-controller”之前的附加 RewriteRule ^index\.php/ - [L]
指令只是一种优化,可防止重写的 URL 不必要地通过随后的文件系统检查。
参考/另请参阅:
请参阅 my answer 网站管理员堆栈中的相关问题:
HSTS implementation in .htaccess when using www subdomain
参见 my answer 代码审查的相关问题:
HSTS Recommendations in .htaccess
HSTS预加载列表提交(基本要求相同)https://hstspreload.org/
RFC6797 - HTTP 严格传输安全 (HSTS):https://datatracker.ietf.org/doc/html/rfc6797
更新: 请尝试以下操作。由于您在 AWS 上,您可能需要检查 X-Forwarded-Proto
HTTP 请求 header 而不是 HTTPS
Apache 服务器变量以确定对客户端的请求是否安全或没有。
需要更改的是 HTTP 到 HTTPS 重定向(第一条规则)和末尾的 <If>
表达式。
Options +FollowSymLinks -Indexes
RewriteEngine On
# Redirect HTTP to HTTPS on the same host (requirement of HSTS)
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect non-www to www (HTTPS only)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Front-controller
RewriteRule ^index\.php/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/ [L]
<If "%{HTTP:X-Forwarded-Proto} == 'https'>
# The "always" condition is required to set the header on the HTTPS redirect
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</If>
我正在使用 Semrush,我收到了一条通知,它真的很困扰我,我想摆脱它。 1 个子域不支持子域的 HSTS:www.domain.com,这是我的 .htdocs 文件:
Options -Indexes
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/ [L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_USER_AGENT} ^(.+)$
RewriteCond %{SERVER_NAME} ^example\.com$
RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Header add Strict-Transport-Security "max-age=300"
</IfModule>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header always set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
我把这部分加在最后:
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header always set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
但是还是没有,我哪里做错了?
您是否尝试过通过 DNS 记录和 .vconfig 文件修复此问题?对于我的网站,我有:
- 主域的 DNS A 记录 (
A domain.com 123.123.123.123
) - www 的第二个 DNS A 记录 (
A www 123.123.123.123
)
然后在 domain.com.vhost:
<VirtualHost *:80>
DocumentRoot /var/www/path_to_root
ServerName domain.com
ServerAlias domain.com
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
</VirtualHost>
重写规则强制使用 HTTPS。
如果您想为特定域强制使用 HTTPS,无论是在 .vhost 还是 .htaccess 中,您都可以使用:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain1.com [NC]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
对于特定文件夹:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(folder1|folder2|folder3) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
确保将文件夹引用更改为实际目录名称。
如果您能够通过 Cloudflare 路由您的 DNS(即使是他们的免费计划),您将能够通过单击按钮启用 HSTS(包括子域)。在速度和安全性方面还有很多其他好处,这也可能有助于您的 SEMRush 报告
Options -Indexes <IfModule mod_rewrite.c> Options +FollowSymLinks RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/ [L] RewriteCond %{HTTPS} !=on RewriteCond %{HTTP_USER_AGENT} ^(.+)$ RewriteCond %{SERVER_NAME} ^example\.com$ RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L] Header add Strict-Transport-Security "max-age=300" </IfModule> <IfModule mod_headers.c> <If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'"> Header always set Strict-Transport-Security "max-age=31536000" </If> </IfModule>
这里有许多问题会阻止 HSTS 正常工作,并且应该进行一些额外的优化。
您没有将
http://www.example.com
(即 www 子域)重定向到 HTTPS。您需要将 HTTP+WWW 重定向到 HTTPS+WWW 才能符合 HSTS。您正在重定向
http://example.com/
(即 HTTP + non-www)到 HTTPS + WWW。为了符合 HSTS,您需要先在 同一主机 上重定向到 HTTPS。 IE。http://example.com/
到https://example.com/
到https://www.example.com
(是的,这是两个重定向,但它也很少见,并且每个 user-agent 最多只会出现一次,因为 STS header 返回)。您的指令顺序错误。您的规范重定向(即 HTTP 到 HTTPS 和 non-www 到 www)需要 before 您的 front-controller 重写(第一条规则)。通过将它们放在 front-controller 之后,除了主页、目录和静态资源之外,它们永远不会被处理。例如。
http://example.com/<some-url>
永远不会被所写的规则重定向。不确定您如何测试 HSTS 与 SEMrush 的合规性,但是使用当时编写的指令http://example.com/<some-url>
会失败,因为它没有被重定向。您应该删除第一个
Header
指令 - 这与第二个(正确的)Header
指令直接冲突。always
条件(在第二个实例中使用)是必需的,以便将 header 设置为 HTTPS 301 重定向(即非 2xx 响应)从 non-www 到 www.您应该在
Strict-Transport-Security
header 中包含includeSubDomains
指令,以便在请求域顶点时覆盖 www 子域。不过,所有 子域现在都将被隐式包含在内。否则,需要明确请求 www 子域。 (好吧,无论如何你都将在下一个请求中重定向到 www。)您应该删除
<IfModule>
包装器;他们不是必需的。这些指令是强制性的,它们不是 可选的 (这些包装器的存在暗示了这一点)。如果 mod_rewrite 不可用,您的站点可能会失败,并且您将不符合 HSTS。有关此问题的更多信息,请参阅 my answer 网站管理员堆栈中的以下问题:
Is Checking for mod_rewrite Really Necessary?我从早期的 HTTP + non-www 重定向假设你不在管理你的 SSL 的 front-end 代理(或负载平衡器)后面,在这种情况下检查for
%{HTTP:X-Forwarded-Proto}
in the later<If>
expression should be removed.如果您不在“代理”后面,则可以伪造请求以防止STS
header 被发回(用户不应该这样做)。相反,如果您在“代理”后面,那么检查
%{REQUEST_SCHEME} == 'https'
是多余的 - 但不会造成任何伤害。顺便说一句,REQUEST_SCHEME
的使用假定您使用的是 Apache 2.4+(我希望您是),但是,如果您仍在使用 Apache 2.2,则此检查将失败并且 STS header 将不会设置。
所以,考虑到以上几点,你的.htaccess
文件应该这样写:
Options +FollowSymLinks -Indexes
RewriteEngine On
# Redirect HTTP to HTTPS on the same host (requirement of HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect non-www to www (HTTPS only)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Front-controller
RewriteRule ^index\.php/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/ [L]
<If "%{REQUEST_SCHEME} == 'https'>
# The "always" condition is required to set the header on the HTTPS redirect
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</If>
补充说明:
我使用
HTTP_HOST
而不是SERVER_NAME
因为您 需要 请求中的主机名。默认情况下SERVER_NAME
与HTTP_HOST
相同,但这可能因服务器配置而异。没有理由仅在请求中存在 non-empty User-Agent 字符串时才应用规范重定向(恶意请求可能会抑制 User-Agent string) 和原来一样,所以我删除了这个条件。如果有的话,你会阻止这样的请求。
RewriteRule
模式中的正则表达式^
比.*
更优化,因为它只需要成功 - 它实际上不需要 匹配 任何东西,因为它以后不会被使用。“front-controller”之前的附加
RewriteRule ^index\.php/ - [L]
指令只是一种优化,可防止重写的 URL 不必要地通过随后的文件系统检查。
参考/另请参阅:
请参阅 my answer 网站管理员堆栈中的相关问题:
HSTS implementation in .htaccess when using www subdomain参见 my answer 代码审查的相关问题:
HSTS Recommendations in.htaccess
HSTS预加载列表提交(基本要求相同)https://hstspreload.org/
RFC6797 - HTTP 严格传输安全 (HSTS):https://datatracker.ietf.org/doc/html/rfc6797
更新: 请尝试以下操作。由于您在 AWS 上,您可能需要检查 X-Forwarded-Proto
HTTP 请求 header 而不是 HTTPS
Apache 服务器变量以确定对客户端的请求是否安全或没有。
需要更改的是 HTTP 到 HTTPS 重定向(第一条规则)和末尾的 <If>
表达式。
Options +FollowSymLinks -Indexes
RewriteEngine On
# Redirect HTTP to HTTPS on the same host (requirement of HSTS)
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect non-www to www (HTTPS only)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Front-controller
RewriteRule ^index\.php/ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/ [L]
<If "%{HTTP:X-Forwarded-Proto} == 'https'>
# The "always" condition is required to set the header on the HTTPS redirect
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</If>