当主域上使用端口时,Apache2 主域重定向到子域

当主域上使用端口时,Apache2 主域重定向到子域

我的所有 http > https 重定向均运行正常。

我已经设置了一个单独的子域和端口,以便与 PHPMyAdmin 一起使用来访问 MySQL DB,因此不太可能被机器人等扫描。下面的示例仅用于演示目的。

我遇到的问题是,如果我在PHPMyAdmin主域名后输入子域名上使用的端口而没有加上 https 前缀,那么它就会变成http://example.com:8080,在开始出现超时网页之后,它最终会将我重定向到 https 站点,但在子域名上https://phpmyadmin.example.com:8081

如何阻止主域重定向到子域,而是像典型服务器一样超时?如果有人猜测主域的每个端口,最终会有人找到子域。

/etc/apache2/sites-enabled/example.com

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    Redirect permanent / https://example.com
    DocumentRoot /var/www/example.com
    # <Directory />
    #     DirectoryIndex index.html index.php
    #     Require all denied
    #     Options FollowSymLinks
    #     AllowOverride All
    # </Directory>
    #ErrorLog ${APACHE_LOG_DIR}/error.log
    #CustomLog ${APACHE_LOG_DIR}/access.log combined    
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com
    # <Directory />
    #     DirectoryIndex index.html index.php
    #     Require all denied
    #     Options FollowSymLinks
    #     AllowOverride All
    # </Directory>
    #ErrorLog ${APACHE_LOG_DIR}/error.log
    #CustomLog ${APACHE_LOG_DIR}/access.log combined
    SSLEngine On
    SSLCertificateFile "/etc/ssl/certs/example.com.crt"
    SSLCertificateKeyFile "/etc/ssl/private/example.com.key"
    SSLCertificateChainFile "/etc/ssl/certs/example.com.ca-bundle"
</VirtualHost>


/etc/apache2/sites-enabled/phpmyadmin.example.com

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081
</VirtualHost>

<VirtualHost *:8081>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    DocumentRoot /usr/share/phpmyadmin
#    RewriteEngine On
#    RewriteCond %{HTTPS} off
#    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
    <Directory />
        Require all denied
        Options FollowSymLinks
        AllowOverride All
    </Directory>
    LogLevel notice
    CustomLog /var/log/apache2/access.log combined
    ErrorLog /var/log/apache2/error.log
    Include /etc/phpmyadmin/apache.conf
    SSLEngine On
    SSLCertificateFile "/etc/letsencrypt/live/phpmyadmin.example.com/cert.pem"
    SSLCertificateKeyFile "/etc/letsencrypt/live/phpmyadmin.example.com/privkey.pem"
    SSLCertificateChainFile "/etc/letsencrypt/live/phpmyadmin.example.com/chain.pem"
</VirtualHost>

更新 1

我认为问题一般出在 http 到 https 重定向之间。通过在主域上键入子域的 HTTP 端口,Apache 的 VirtualHost 会将其视为将 http 重定向到 https 的发起者,但完全忽略了应该执行此操作的域。有没有办法根据域前缀隔离 http 到 https 重定向?

更新2

是否有任何重写规则/条件可用于每个 http 虚拟主机,以便仅响应其正在侦听的端口?我对重写规则等一无所知,因此我依靠良好的 Google 研究技能来找到写入网站。我偶然发现了这一点。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [R,L]

更新 3

我已修复该问题。

但是,如果我访问示例 URL,http://example.com:8080则会收到 403 禁止错误消息

Forbidden

You don't have permission to access this resource.

我怎样才能让 Apache 超时连接而不是直接拒绝它?

两个 VirtualHost 文件现在变成:

/etc/apache2/sites-enabled/example.com

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com
    RewriteEngine On
    RewriteCond %{HTTP_HOST} example.com [NC]
    RewriteCond %{SERVER_PORT} 80
    RewriteRule ^(.*)$ https://www.example.com$1 [R,L]
    <Directory />
        DirectoryIndex index.html index.php
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined    
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com
    <Directory />
    DirectoryIndex index.html index.php
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    SSLEngine On
    SSLCertificateFile "/etc/ssl/certs/example.com.crt"
    SSLCertificateKeyFile "/etc/ssl/private/example.com.key"
    SSLCertificateChainFile "/etc/ssl/certs/example.com.ca-bundle"
</VirtualHost>

/etc/apache2/sites-enabled/phpmyadmin.example.com

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    RewriteEngine On
    RewriteCond %{HTTP_HOST} phpmyadmin.example.com [NC]
    RewriteCond %{SERVER_PORT} 8080
    RewriteRule ^(.*)$ https://phpmyadmin.example.com:8081$1 [R,L]
</VirtualHost>

<VirtualHost *:8081>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    DocumentRoot /usr/share/phpmyadmin
    <Directory />
        DirectoryIndex index.html index.php
    </Directory>
    LogLevel notice
    CustomLog /var/log/apache2/access.log combined
    ErrorLog /var/log/apache2/error.log
    Include /etc/phpmyadmin/apache.conf
    SSLEngine On
    SSLCertificateFile "/etc/letsencrypt/live/phpmyadmin.example.com/cert.pem"
    SSLCertificateKeyFile "/etc/letsencrypt/live/phpmyadmin.example.com/privkey.pem"
    SSLCertificateChainFile "/etc/letsencrypt/live/phpmyadmin.example.com/chain.pem"
</VirtualHost>

答案1

就我个人而言,我倾向于使用防火墙或 ssh 端口转发和 localhost 的解决方案,以安全的方式向受信任的主机公开 phpmyadmin 服务,并且绝对使用适当的身份验证而不是“模糊安全性”。然而,为了尝试回答手头的问题...

因为每个端口只有一个 VirtualHost,第一个defined 成为对该端口的请求的默认值,无论在 ServerName 和 ServerAlias 中设置的域名是什么。

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081/
</VirtualHost>

这将匹配对 *:8080 的任何请求,包括:

并将它们重定向到端口 8081 上的服务。

为了区分请求,我会添加第二个端口 8080 上的 VirtualHost 捕获所有其他内容(包括http://example.com:8080),并将其重定向到某个不存在的地方,这会导致超时。

<VirtualHost *:8080>
    ServerName example.com
    # redirect to somewhere non-existing will cause timeout
    Redirect permanent / https://192.168.99.99/
</VirtualHost>

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081/
</VirtualHost>

(请注意,默认值需要先出现)

笔记:

如何停止主域名重定向到子域名以及而是超时就像典型的服务器一样?

不幸的是,当 Apache 收到请求并进行处理时,它无法判断该请求是否http://phpadmin.example.com:8080或者http://example.com:8080,apache 本身已经来不及删除初始连接并导致超时。

我通常会为此目的使用防火墙(直接在 iptables 中,或根据您的发行版使用 ufw/firewalld),以将对端口 8080 的访问限制为仅限已知的受信任主机。

更新:使用 mod_security

看起来可以使用 mod_security 模块来模拟超时: https://serverfault.com/a/401592/47650

因此,在处理完请求头后,类似这样的操作就会发送一个 FIN 数据包来断开连接......

<VirtualHost *:8080>
  ServerName example.com
  SecRuleEngine On
  SecAction id:1,phase:1,nolog,drop
</VirtualHost>

<VirtualHost *:8080>
    ServerName phpmyadmin.example.com
    ServerAlias phpmyadmin.example.com
    Redirect permanent / https://phpmyadmin.example.com:8081/
</VirtualHost>

https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-%28v2.x%29#drop

相关内容