Apache mod_auth_form 到子目录

Apache mod_auth_form 到子目录

首先,我的结构。运行带有 Apache 2.4 的 Ubuntu 16.04.3,我的站点位于 /mnt/WWW,但除了登录表单外,从不提供来自那里的页面。所有内容都重定向到 www。如果不是另一个子域,然后从 http 重定向到 https。我还有一个从 /mnt/WWW 目录运行的身份验证表单。这使我能够拥有一个为任何 url、路径或反向代理提供 mod_auth_form 身份验证的 php 表单。

到目前为止,我已经花了 12 多个小时让这一切运转起来,并且学到了很多东西,但还有最后一点让我很为难。但在此之前,这里有一些关于我现有(和正在运行)设置的信息。

服务器目录结构。

  • /mnt/WWW——Apache 根目录
  • /mnt/WWW/www.example.com - 站点根目录
  • /mnt/WWW/dev.example.com - 开发站点的根目录

我当前的虚拟主机文件:

# Default
ServerName example.com
DocumentRoot /mnt/WWW
ServerAdmin [email protected]
RemoteIPHeader X-Forwarded-For

Alias "/login.php" "/mnt/WWW/login.php"
Alias "/logo.png" "/mnt/WWW/logo.png"

<Directory />
    # Allow access to excluded directories
    SetEnvIf Request_URI "login.php" allow
    SetEnvIf Request_URI "logo.png"  allow
    Order allow,deny
    Allow from env=allow
    Satisfy any
    Require valid-user
</Directory>

<Location />
    AuthFormProvider file
    AuthType form
    AuthName "Reserved Area"
    Session On
    SessionCookieName session path=/
    SessionCryptoPassphrase secret
    SessionMaxAge 300
    require valid-user

    # This is the login page
    ErrorDocument 401 /login.php

    # This is the file containing users login data
    AuthUserFile /mnt/WWW/.htpasswd
</Location>

# Default HTTP
<VirtualHost *:80>
    DocumentRoot "/mnt/WWW"
    ServerName example.com

    <Directory />
        Require valid-user
    </Directory>

    # Force SSL
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}:443$1 [R,L]

    # Force WWW Subdomain
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^[0-9a-zA-Z-]+\.[a-zA-Z]{2,}$
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}:443$1 [R=301,L]
</VirtualHost>

# Default HTTPS
<VirtualHost *:443>
    DocumentRoot "/mnt/WWW"
    ServerName example.com

    <Directory />
        Require valid-user
    </Directory>

    # Force WWW Subdomain
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^[0-9a-zA-Z-]+\.[a-zA-Z]{2,}$
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}:443$1 [R=301,L]

    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt
</VirtualHost>

# Default WWW
<VirtualHost *:443>
    DocumentRoot "/mnt/WWW/www.example.com"
    ServerName www.example.com

    <Directory />
        Require valid-user
    </Directory>

    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt
</VirtualHost>

#Reverse Proxies
<VirtualHost *:443>
    # NAS
    DocumentRoot /mnt/WWW

    ServerName nas.example.com
    ServerAlias nas.example.com

    <Directory /mnt/WWW/>
        Require valid-user
    </Directory>

    ProxyPass /logo.png !
    ProxyPass /login.php !
    ProxyPass / http://10.0.28.1:5000/
    ProxyPassReverse / http://10.0.28.1:5000/

    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt
</VirtualHost>

现在,如您所见,我有一个用于表单的 login.php 和 logo.png 文件。我计划将其更改为 LDAP 表单,并且没有任何问题,我还计划进一步设计它的样式。这意味着我最终将有更多文件包含在登录配置中。

话虽如此,我想将登录文件移动到 /mnt/WWW/authentication 文件夹。我希望这样我就不用为 2 个以上的单独文件制定规则等,而是可以直接将它们设置为目录本身。所有诸如别名、noauth 设置等内容。

但我似乎无法让一切正常运作。任何帮助都将不胜感激。

附言:我是这方面的新手,如果有人发现任何潜在的安全问题,请告知。

更新:我重新修改了配置,完成了每个步骤,并确保使用了完整路径等。到目前为止,一切正常,即:

  • 所有 80 端口重定向至 443
  • 所有请求都重定向到 www.example.com,除非它是子域名
  • 将一些子文件夹重定向到外部文件夹以提供诸如 phpmyadmin 之类的服务。
  • 将子域名反向代理到相关服务器,并使用子文件夹访问该服务器上的不同服务,例如 nas.examle.com 是 NAS GUI,而 nas.example.com/webmin 是 NAS Webmin UI。

这是迄今为止我的配置的更新。

<VirtualHost *:80>
    # Redirect anything on port 80 to port 443
    #ServerName example.com
    ServerAdmin [email protected]
    DocumentRoot /mnt/WWW

    # Force SSL
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}:443$1 [R,L]

    # Error Logs
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAdmin [email protected]
    DocumentRoot /mnt/WWW

    # Force WWW Subdomain
    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^[0-9a-zA-Z-]+\.[a-zA-Z]{2,}$
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}:443$1 [R=301,L]

    # SSL Certificates
    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt

    # Error Logs
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com
    ServerAdmin [email protected]
    DocumentRoot /mnt/WWW/www.example.com

    <Directory /mnt/WWW/www.example.com>
        Options Indexes FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

    <Directory /mnt/WWW/phpmyadmin>
        Options Indexes FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

    # Map PHPMyAdmin to another folder
    Alias "/phpmyadmin" "/mnt/WWW/phpmyadmin"

    # WEBMIN
    ProxyPass "/webmin" "http://localhost:10000/"
    ProxyPassReverse "/webmin" "http://localhost:10000/"

    # SSL Certificates
    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt

    # Error Logs
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

# Reverse Proxies

<VirtualHost *:443>
    # NAS
    ServerName nas.example.com
    ServerAdmin [email protected]
    DocumentRoot /mnt/WWW

    # NAS 2
    ProxyPass "/nas2" "http://10.0.28.3:5000/"
    ProxyPassReverse "/nas2" "http://10.0.28.3:5000/"

    # NAS 1
    ProxyPass "/nas1" "http://10.0.28.2:5000/"
    ProxyPassReverse "/nas1" "http://10.0.28.2:5000/"

    # NAS CLUSTER
    ProxyPass / http://10.0.28.1:5000/
    ProxyPassReverse / http://10.0.28.1:5000/

    # SSL Certificates
    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt

    # Error Logs
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

现在,我想做的是使用文档根目录中的子文件夹来保存与身份验证相关的所有文件。在此阶段,只有一个表单、一个图像、css 文件和带有凭据的 .htaccess。稍后,这将更改为针对 LDAP 服务器而不是 .htaccess 进行验证的表单。

我的目标是锁定对服务器的所有访问,包括本地站点、phpmyadmin 或反向代理,这样我就可以在获得所请求的访问权限之前获得身份验证表单(在 /mnt/WWW/example.login/ 中)。

我之前已经解决这个问题了,所以我相信我的问题与代码的顺序或结构有关,但到目前为止,无论我尝试什么,都会出现内部服务器错误。

我将最终的 www.example.com 虚拟主机更改为以下内容:

<VirtualHost *:443>
    ServerName www.example.com
    ServerAdmin [email protected]
    DocumentRoot /mnt/WWW/www.example.com

    <Directory /mnt/WWW/www.example.com>
        Options Indexes FollowSymLinks
        AllowOverride all
        Require valid-user
    </Directory>

    <Location /mnt/WWW>
        AuthFormProvider file
        AuthType form
        AuthName "Reserved Area"

        Session On
        SessionCookieName session path=/;domain=.example.com;httponly;secure
        SessionCryptoPassphrase secret
        SessionMaxAge 300
        require valid-user

        ErrorDocument 401 /example.login/index.php
        AuthUserFile /mnt/WWW/example.login/.htpasswd
    </Location>

    <Directory /mnt/WWW/phpmyadmin>
        Options Indexes FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

    # Map PHPMyAdmin to another folder
    Alias "/phpmyadmin" "/mnt/WWW/phpmyadmin"

    # WEBMIN
    ProxyPass "/webmin" "http://localhost:10000/"
    ProxyPassReverse "/webmin" "http://localhost:10000/"

    # SSL Certificates
    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt

    # Error Logs
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

我做错了什么。是订购问题,还是我忽略了什么?我花了好几个小时才搞定,快把我逼疯了。我只需要一些新(和有经验)的眼光来看待这个问题。谢谢。

顺便说一句,为了清楚起见,所有路径和域都是正确的,因为我在现实生活中有它们。我只将使用的真实域名更改为 example.com 等以隐藏真实域名。

另一个更新:

我在某处读到(再也找不到了)我可以在目录标签而不是位置上使用 Auth 内容。我读到它更安全。不确定这是不是真的,但我确实得到了一个有点用的配置:

<VirtualHost *:443>
    ServerName www.example.com
    ServerAdmin [email protected]
    DocumentRoot /mnt/WWW/www.example.com

    # Map PHPMyAdmin to another folder
    Alias "/example.login" "/mnt/WWW/example.login"

    <Directory "/mnt/WWW/example.login">
        Order allow,deny
        Allow from all
        Satisfy any
    </Directory>

    # Map PHPMyAdmin to another folder
    Alias "/phpmyadmin" "/mnt/WWW/phpmyadmin"

    <Directory /mnt/WWW/phpmyadmin>
        Order allow,deny
        Allow from all
        Satisfy any
    </Directory>

    <Directory /mnt/WWW/www.example.com>
        Options Indexes FollowSymLinks
        AllowOverride all
        Require valid-user

        AuthFormProvider file
        AuthType form
        AuthName "Reserved Area"

        Session On
        SessionCookieName session path=/;domain=.example.com;httponly;secure
        SessionCryptoPassphrase secret
        SessionMaxAge 300
        Require valid-user

        ErrorDocument 401 /example.login/index.php
        AuthUserFile /mnt/WWW/example.login/.htpasswd
    </Directory>

    # WEBMIN
    ProxyPass "/webmin" "http://localhost:10000/"
    ProxyPassReverse "/webmin" "http://localhost:10000/"

    # SSL Certificates
    SSLEngine on
    SSLCertificateFile /root/ssl/example.com.crt
    SSLCertificateKeyFile /root/ssl/private.key
    SSLCACertificateFile /root/ssl/intermediateCA.crt

    # Error Logs
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

现在,此配置为我提供了部分表单,我能够登录并获取主根 www.example.com 站点。phpmyadmin 不安全,example.login 也不安全。我计划稍后再保护 phpmyadmin 和其他站点,每次只需执行 1 步。

当我说部分时,我的意思是表单显示,但页面中有一张图片未显示。我认为这是一个安全问题,因为当配置中没有身份验证时,页面会正常显示。

所以我现在的问题是,如何让 example.login 文件夹及其中的所有文件绕过身份验证,并且有没有更好的方法来输入身份验证代码以便应用于所有内容并控制使用 Require valid-user 锁定的内容?

相关内容