受信任主机设置
本文档尚不完整。获取更多信息。
防御 HTTP HOST Header 攻击(防止您的网站被伪装成其他网站)
Drupal 7 在核心中添加了一个新功能,该功能并非直接供用户交互使用,但有时被称为 poormanscron。此功能会运行 Drupal 网站的定期任务,如清理日志文件、发送电子邮件和清除缓存。该功能与动态定义的“基础 URL”(添加于 Drupal 4.7)结合时,可能会导致一些奇怪的情况。本文介绍了其中一些由两种功能或模块共同引发的问题,以及如何防止它们发生。以下说明假设某些默认配置——在最后我会讲解如何更改默认设置来避免这些问题。
场景 1:用户收发属于其他域名的电子邮件
这种行为相对容易重现:
1. 通过现有网站的 IP 地址添加一个新域名——假设现有网站为 http://www.example.com,新域名指向同一 IP 地址,例如 http://other-site.example.org。
2. 访问 URL:http://other-site.example.org/user/password
3. 输入您网站中存在的用户名。
结果是,在步骤 2 中,$base_url 的检测结果将认为您的网站是 http://other-site.example.org,并且所有包含网站链接的电子邮件令牌(例如 [user: one-time-login-url])都将被替换为使用 http://other-site.example.org 作为基础 URL。收到此电子邮件的用户将会看到其用户名和邮箱在 example.com 上,却被用于 http://other-site.example.org,这通常会让人感到困惑。然而,这种情况可能导致两个严重问题:
- 最糟糕的情况是,用户点击密码重置链接,而恶意网站随后可以使用此链接登录主站点的用户账户。
- 用户可能在 http://other-site.example.org 输入用户名和密码——这是一种“社会工程”攻击,随后这些凭据可能被用来访问主站。
场景 2:缓存条目中包含错误的域名
当用户使用错误的域名发出请求时,也可能出现类似问题。这种请求可能会在缓存中生成一个包含错误域名的动态条目。后续访问若从缓存中提取数据,将会获取错误的域名。Drupal 核心的页面缓存机制使用域名作为缓存 ID 的一部分,以防止此类问题,但其他缓存机制可能并不具备相同的防御能力。
场景 3:包含错误域名的电子邮件通知
另一个常见问题出现在使用模块在 cron 运行期间发送电子邮件的网站上。此情景需要 poormanscron 与动态 base_url 共同存在。如果用户在访问错误的域名时意外触发 poormanscron,而当时队列中存在待发送的通知,那么这些通知将使用错误的域名发送。用户可能会非常困惑,为什么来自 example.com 的邮件中包含指向 http://other-site.example.org 的链接。
防止 Drupal 动态 base_url 检测混乱的解决方案
至少有四种方法可以防止此问题发生,您可以根据自己的环境选择合适的方案。
1. 在 sites/default/settings.php 文件中设置固定的 $base_url。虽然动态检测可能很方便,但它也可能引发问题。解决方案之一是设置固定的值。
2. 为特定站点(如 sites/example.com/settings.php)启用动态 $base_url。这意味着 Drupal 将响应 example.com 下的所有子域名,这可能是优点也可能是缺点。
3. 配置您的 Web 服务器,使其在请求与 Drupal 默认站点不匹配时返回默认页面,例如错误页面。
4. 配置 Web 服务器,将所有不属于正确域名的请求重定向至正确的域名。
在 Drupal 8 中配置受信任主机安全设置
自 2015 年 1 月起,Drupal 8 支持“受信任主机模式(Trusted Host Patterns)”。您可以(也应该)指定一组正则表达式,用来匹配所有允许的请求域名。settings.php 文件中的示例配置如下:
$settings['trusted_host_patterns'] = [ '^www\.example\.com$', ];
有关详细信息,请参阅上述变更日志。如果您在本地开发中使用此配置,可能会暂时阻止自己访问网站。在这种情况下,应添加 '^localhost$' 作为受信任主机。
MAMP 3 的受信任主机配置
在本地开发时,MAMP (3.5.2) 对 “^localhost$” 会报错 “指定的主机名对该服务器无效”,并且无法加载网站。解决方法是改用不带端口号的站点名称。例如在测试站点 "drupal8" 中:
$settings['trusted_host_patterns'] = [ '^drupal8$', ];
此配置即可启用受信任主机。
注意:在 MAMP 4.2 中,'^localhost$' 工作正常。
Acquia Dev Desktop 2 的受信任主机配置(已在 Drupal 8.6.2 与 PHP 7.2.8 上测试)
如果您使用 Acquia Dev Desktop 2,请尝试以下受信任主机模式。将 “sitename” 替换为您的站点名称:
$settings['trusted_host_patterns'] = array( '^sitename\.dd$', );
XAMPP 的受信任主机配置(已在 Drupal 8.4.0 与 PHP 7.1.8 上测试)
要启用受信任主机机制,我们需要在 $settings['trusted_host_patterns'] 中添加允许的主机。
打开 “settings.php” 文件并更新如下代码:
$settings['trusted_host_patterns'] = [ '^localhost$', '^192\.168\.00\.52$', '^127\.0\.0\.1$', ];
其中:
- '^localhost$':仅允许从 localhost 访问网站。
- '^192\.168\.00\.52$':仅允许通过系统的 IP 地址访问(不同系统 IP 地址不同)。
- '^127\.0\.0\.1$':仅允许从 127.0.0.1 访问,而不是 localhost。
注意:在多站点环境中,请指定所有允许的主机模式。
Lando 的受信任主机配置(已在 Drupal 8.7.10 与 PHP 7.2 上测试)
同样地,要启用受信任主机机制,我们需要在 $settings['trusted_host_patterns'] 中添加允许的主机。
打开 settings.php 文件并更新如下代码:
$settings['trusted_host_patterns'] = [ '^'.getenv('LANDO_APP_NAME').'\.lndo\.site$', # Lando 代理访问 '^localhost$', # 本地访问 '^'.getenv('LANDO_APP_NAME').'\.localtunnel\.me$', # Lando 共享访问 '^192\.168\.1\.100$' # 局域网 IP 访问 ];
注意:Lando 容器中包含更多环境变量,可用于设置数据库凭据。可通过 $lando_info = json_decode(getenv('LANDO_INFO'), TRUE); 查看,或使用 phpinfo() 检查。