gpt4 book ai didi

django - 在 AWS ElasticBeanstalk 中阻止 Apache 中无效的 HTTP_HOST header

转载 作者:行者123 更新时间:2023-12-04 08:58:11 25 4
gpt4 key购买 nike

我有几个运行 Django/Apache 的网站部署在 AWS ElasticBeanstalk 中。
我唯一的问题是我每天收到的数百封关于这个主题的电子邮件:

[Django] ERROR (EXTERNAL IP): Invalid HTTP_HOST header: WHATEVER. You may need to add WHATEVER to ALLOWED_HOSTS.
那是因为我已经在我的 Django 配置中正确配置了 ALLOWED_HOSTS 变量,但是我需要 Apache 阻止所有无效的 HTTP_HOST header ,这样它们甚至无法到达 Django 并每天摆脱这数百封电子邮件。
我知道,在 Apache 中,有许多示例说明如何在 Apache 中执行此操作,但我还没有找到在 AWS ElasticBeanstalk 中进行部署时如何执行此操作的单个示例。
如果您不熟悉 AWS ElasticBeanstalk,请记住该系统会自动创建 /etc/httpd/conf.d/wsgi.conf文件中包含由亚马逊制作的一些配置,亚马逊可以(并且将)在我们无法控制的 future 修改它们。
因此,当我们想向 Apache 添加一些配置时,例如提供重定向,首选方式是在我们的项目中提供一个 YAML 文件,该文件定义了一个新的独立 Apache 配置文件,除了 wsgi.conf 之外,该文件将被考虑在内。亚马逊自动创建的文件,如下所示:
files:
"/etc/httpd/conf.d/ssl_rewrite.conf":
mode: "000644"
owner: root
group: root
content: |
RewriteEngine On
<If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</If>
这样做,一旦我们部署了我们的代码,一个 /etc/httpd/conf.d/ssl_rewrite.conf Apache 也会创建和使用该文件(我们不会编辑原始 wsgi.conf 文件,我们只是在新文件中提供更多配置)。
这里有一个关于这种模式的惊人解释: https://stackoverflow.com/a/38751648/1062587 .
这些 YAML 配置文件可以创建 Apache 配置文件或将某些内容附加到现有文件,但不能进行替换或版本。
但是,关于我的问题,原来的 wsgi.conf文件已经提供了这样的部分:
<VirtualHost *:80>
[...]
<Directory /opt/python/current/app/>
Require all granted
</Directory>
[...]
</VirtualHost>
由于我想阻止所有无效的主机请求,我假设我需要将其更改为这样的内容(根据此答案: https://stackoverflow.com/a/43322857/1062587 ):
<VirtualHost *:80>
[...]
<Directory /opt/python/current/app/>
Require expr "%{HTTP_HOST} in {'whatever.com', 'www.whatever.com'}"
Options
</Directory>
[...]
</VirtualHost>
我的问题是:YAML 文件无法制作版本。我只能为它们提供新的配置。
所以,我不知道是否可以在独立的 Apache 配置文件中提供一些配置来覆盖现有的 <VirtualHost> -> <Directory>部分,所以我可以像 ElasticBeanstalk 理解的那样在 YAML 文件中定义所需的代码。
否则,我将不得不提供一个脚本来即时进行替换。我知道怎么做,但我觉得这很丑陋。我只是问是否有更优雅的解决方案。

最佳答案

由于我没有找到使用 YAML 文件的任何更好的方法,我使用 Python 脚本来修改原始 Apache wsgi.conf以我能想到的最不可知的方式提交文件(无论亚马逊将来是否修改它)。
我在这里分享它,以防任何人发现它有用。使用这种方法,您不必在代码中的任何位置对主机白名单进行硬编码。

  • 首先在.ebextensions/deploy.config中添加一个新命令

  • container_commands:
    01__apache_block_invalid_hosts:
    command: python .ebextensions/apache_block_invalid_hosts.py
    请注意,您可以考虑添加 leader_only: true如果您不打算更改 DJANGO_ALLOWED_HOSTS任何时候的环境变量(稍后解释)并且如果您了解其含义。
  • .ebextensions/apache_block_invalid_hosts.py 中创建 python 脚本

  • from enum import Enum, auto
    import os


    NEW_AUTH_DIRECTIVE = """
    Require expr "%{{HTTP_HOST}} in {{{hosts}}}"
    Options
    """

    class Step(Enum):
    BEFORE_AUTH = auto()
    INSIDE_AUTH = auto()
    AFTER_AUTH = auto()

    step = Step.BEFORE_AUTH
    with open('/etc/httpd/conf.d/wsgi.conf', 'r') as file_in, open('../wsgi.conf', 'w') as file_out:
    for line in file_in.readlines():
    if step == Step.BEFORE_AUTH:
    file_out.write(line)
    if "<Directory /opt/python/current/app/>" in line:
    hosts = ", ".join([f"'{i}'" for i in os.environ['DJANGO_ALLOWED_HOSTS'].split('__')])
    file_out.write(NEW_AUTH_DIRECTIVE.format(hosts=hosts))
    step = Step.INSIDE_AUTH
    elif step == Step.INSIDE_AUTH:
    if "</Directory>" in line:
    file_out.write(line)
    step = Step.AFTER_AUTH
    elif step == Step.AFTER_AUTH:
    file_out.write(line)
    注意编辑文件的输出路径是 ../wsgi.conf而不是 /etc/httpd/conf.d/wsgi.conf .相信我,它有效。
  • 使用 AWS EB 配置网站中的所有白名单主机定义环境变量:
  • DJANGO_ALLOWED_HOSTS         whatever.com__www.whatever.com__whatever.us-east-1.elasticbeanstalk.com
    请注意,我使用的是 __分隔符,而不是逗号。这是因为我有时会使用 eb clone 直接从我的命令行创建/克隆环境。同时提供环境变量值的更改。如果这样做,则不能在值中包含逗号,并且无法转义它们。
  • 使用 Django 设置文件中的相同环境变量(我使用 django-environ 库从系统读取环境变量):

  • import environ
    env = environ.Env()
    env.read_env()
    ALLOWED_HOSTS = env('DJANGO_ALLOWED_HOSTS', default='*').split('__')

    关于django - 在 AWS ElasticBeanstalk 中阻止 Apache 中无效的 HTTP_HOST header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63704288/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com