Apache 虚拟主机配置让错误的服务器名称请求通过代理

Apache 虚拟主机配置让错误的服务器名称请求通过代理

我已将服务器配置移至新服务器,同时使用 apache mod_proxy 配置它以访问 gunicorn/django web 服务器(位于端口 8000 上的 docker 容器内)。以前的服务器使用 apache mod_wsgi 直接访问 django。

因此我更改了一些虚拟主机配置,但我不明白为什么现在一些请求要通过 apache 到 django,而请求服务器名不是我的 DNS 和虚拟主机配置之一……

目前,django 会以Invalid HTTP_HOST header错误的方式阻止它们,但我想直接在 apache 配置中过滤它们,并了解此类扫描请求如何传递 DNS 和 apache 配置。

以下是我收到的一个典型的 django 错误:

Report at /
Invalid HTTP_HOST header: 'sprucetips.cyou'. You may need to add 'sprucetips.cyou' to ALLOWED_HOSTS.

Request Method: GET
Request URL: https://sprucetips.cyou/
Django Version: 2.2.28
Python Executable: /usr/local/bin/python
Python Version: 3.5.10
...

Request information:
USER: [unable to retrieve the current user]
GET: No GET data
POST: No POST data
FILES: No FILES data
COOKIES: No cookie data

META:
HTTP_ACCEPT_ENCODING = 'gzip'
HTTP_CONNECTION = 'Keep-Alive'
HTTP_HOST = 'sprucetips.cyou'
HTTP_USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
HTTP_X_FORWARDED_FOR = '34.220.181.252'
HTTP_X_FORWARDED_HOST = 'sprucetips.cyou'
HTTP_X_FORWARDED_PROTO = 'https'
HTTP_X_FORWARDED_SERVER = 'mydomain.ca'
PATH_INFO = '/'
QUERY_STRING = ''
RAW_URI = '/'
REMOTE_ADDR = '172.23.0.1'
REMOTE_PORT = '47332'
REQUEST_METHOD = 'GET'
SCRIPT_NAME = ''
SERVER_NAME = '0.0.0.0'
SERVER_PORT = '8000'
SERVER_PROTOCOL = 'HTTP/1.1'
SERVER_SOFTWARE = 'gunicorn/20.1.0'
...

我的 DNS 配置在两个域名上,mydomain.ca 和 mydomain.com。我之前为每个子域名设置了一个 DNS 配置,但现在我只将mydomain.ca *.mydomain.ca mydomain.com *.mydomain.com它们都设置为同一个 IP。这会是个问题吗?

这是我的虚拟主机:

首先001-mydomain.ca.conf将任何 80 端口请求重定向到 443 端口

<VirtualHost *:80>
        ServerName mydomain.ca
        ServerAlias www.mydomain.com www.mydomain.ca mydomain.com sub1.mydomain.ca sub2.mydomain.ca sub3.mydomain.ca

        ErrorLog ${APACHE_LOG_DIR}/mydomain.ca.error.log
        LogLevel info
        CustomLog ${APACHE_LOG_DIR}/mydomain.ca.access.log combined

        RewriteEngine on
        RewriteCond %{SERVER_NAME} =www.mydomain.ca [OR]
        RewriteCond %{SERVER_NAME} =mydomain.com [OR]
        RewriteCond %{SERVER_NAME} =www.mydomain.com [OR]
        RewriteCond %{SERVER_NAME} =mydomain.ca
        RewriteRule ^ https://mydomain.ca%{REQUEST_URI} [END,QSA,R=permanent]

        RewriteCond %{SERVER_NAME} =sub1.mydomain.ca
        RewriteRule ^ https://sub1.mydomain.ca%{REQUEST_URI} [END,QSA,R=permanent]

        RewriteCond %{SERVER_NAME} =sub2.mydomain.ca
        RewriteRule ^ https://sub2.mydomain.ca%{REQUEST_URI} [END,QSA,R=permanent]

        RewriteCond %{SERVER_NAME} =sub3.mydomain.ca
        RewriteRule ^ https://sub3.mydomain.ca%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>

010-mydomain.ca-ssl.conf

<VirtualHost *:443>
        ServerName mydomain.ca
        ServerAlias www.mydomain.ca sub1.mydomain.ca sub2.mydomain.ca
        DocumentRoot /var/www/mydomain.ca

        ErrorLog ${APACHE_LOG_DIR}/mydomain.ca.error.log
        LogLevel debug

        CustomLog ${APACHE_LOG_DIR}/mydomain.ca.access.log combined

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/mydomain.ca/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.ca/privkey.pem

        RewriteEngine On
        RewriteMap exceptions /var/www/mydomain.ca/maintenance_exceptions.map

        RewriteCond /var/www/mydomain.ca/maintenance.html -f
        RewriteCond /var/www/mydomain.ca/maintenance.enable -f
        RewriteCond %{SCRIPT_FILENAME} !maintenance.html
        RewriteCond ${exceptions:%{REMOTE_ADDR}} !OK
        RewriteRule ^.*$ /maintenance.html [R=503,L]
        ErrorDocument 503 /maintenance.html

        ProxyRequests Off
        ProxyPreserveHost On
        RequestHeader set X_FORWARDED_PROTO 'https' env=HTTPS
        ProxyPass /static/ !
        ProxyPass /media/ !
        ProxyPass /favicon.ico !
        ProxyPass /maintenance.html !
        ProxyPass / http://localhost:8000/
        ProxyPassReverse / http://localhost:8000/

        Alias /favicon.ico /var/www/mydomain.ca/favicon.ico
        Alias /media/ /var/www/mydomain.ca/media/
        Alias /static/ /var/www/mydomain.ca/static/

        <Directory /var/www/mydomain.ca>
                Order allow,deny
                Allow from all
        </Directory>

        <Directory /var/www/mydomain.ca/static>
                Header set Cache-Control "max-age=86400, must-revalidate"
        </Directory>
</VirtualHost>

<VirtualHost *:443>
        ServerName mydomain.com
        ServerAlias www.mydomain.com

        RewriteEngine On
        RewriteRule ^ https://mydomain.ca%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>

其中一个子域名被重定向到另一个 Web 服务器,011-sub3.mydomain.ca-ssl.conf

<VirtualHost *:443>
        ServerName sub3.mydomain.ca

        ErrorLog ${APACHE_LOG_DIR}/sub3.mydomain.ca.error.log
        LogLevel debug
        CustomLog ${APACHE_LOG_DIR}/sub3.mydomain.ca.access.log combined

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/mydomain.ca/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.ca/privkey.pem

        ProxyPreserveHost On
        ProxyRequests off
        AllowEncodedSlashes NoDecode
        ProxyPass /.well-know !
        ProxyPass /robots.txt !
        ProxyPass / http://localhost:3000/ nocanon
</VirtualHost>

我终于管理了其他子域名,并直接在020-default.mydomain.ca.conf

<VirtualHost *:80 *:443>
        ServerName default.mydomain.ca
        ServerAlias *.mydomain.ca *.mydomain.com
        Redirect 404 /
        CustomLog ${APACHE_LOG_DIR}/mydomain.ca.other.log combined
</VirtualHost>

<VirtualHost *:80 *:443>
        ServerName <IP>
        Redirect 403 /
        ErrorDocument 403 "Direct IP access not allowed"
        UseCanonicalName Off
        CustomLog ${APACHE_LOG_DIR}/mydomain.ca.other.log combined
</VirtualHost>

任何提示、建议或神奇答案都将不胜感激。谢谢。

答案1

除了 AlexD 的回答默认 VirtualHost 应该是第一个,但<VirtualHost *:80 *:443>不起作用,因为*:80是用于纯 HTTP 的,而 是*:443用于 HTTPS 的。您需要将这些配置分开,并添加 TLS 设置(包括 的任何证书)<VirtualHost *:443>


此外,RewriteRuleHTTP 到 HTTPS 重定向中的 s 有点过于复杂。

对于子域名,您可以使用mod_rewrite使用带有变量的单一规则:

<VirtualHost *:80>
    ServerName sub1.example.net
    ServerAlias sub2.example.net sub3.example.net

    RewriteEngine On
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

对于应重定向到规范主机名的主机名,mod_alias将会可取的

<VirtualHost *:80>
    ServerName example.net
    ServerAlias www.example.com www.example.net example.com 

    Redirect "/" "https://www.example.net/"
</VirtualHost>

答案2

摘录自Apache 文档

收到请求后,服务器首先根据本地 IP 地址和端口组合将其映射到最佳匹配项。非通配符具有更高的优先级。如果完全没有基于 IP 和端口的匹配项,则使用“主”服务器配置。

如果多个虚拟主机包含最佳匹配的 IP 地址和端口,则服务器会根据请求的主机名从这些虚拟主机中选择最佳匹配。如果未找到匹配的基于名称的虚拟主机,则将使用与 IP 地址匹配的第一个列出的虚拟主机。因此,给定 IP 地址和端口组合的第一个列出的虚拟主机是该 IP 和端口组合的默认虚拟主机

您需要重命名您的020-default.mydomain.ca.conf000-default.mydomain.ca.conf以便它是第一个。

相关内容