首先,我的结构。运行带有 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 锁定的内容?