First, my structure. Running Ubuntu 16.04.3 with Apache 2.4, I have a site at /mnt/WWW but never serves pages from there except for a login form. Everything is redirected to www. if not another subdomain and then redirected from http to https. I also have an authentication form running from the /mnt/WWW directory. This allows me to have a single php form that serves the mod_auth_form authentication for any url, path or reverse proxy.
I have spent over 12 hours getting this all working to this point, and have learnt a great deal about all of this, but am stuck on one last thing. But before that here some info regarding my existing (and working) setup.
Server directory structure.
- /mnt/WWW - Root Apache Directory
- /mnt/WWW/www.example.com - Root Directory of Site
- /mnt/WWW/dev.example.com - Root of Development Site
My current Virtual Hosts file:
# Default
ServerName example.com
DocumentRoot /mnt/WWW
ServerAdmin support@example.com
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>
Now, as you can see I have a login.php and logo.png file for the form. I plan on changing this to a form for LDAP and have no issues with that, and I am planning on styling it further as well. This means I will end up with more files to include in the configuration for the login.
In saying that, I want to move the login files to /mnt/WWW/authentication folder. I was hoping that I could then instead of making rules etc for 2+ individual files, I could simply set those to the directory itself. All the things like the Alias, noauth setting etc.
But I cannot seem to get it all to work. Any help will be appreciated.
PS: I am a beginner with all of this, and if someone see's any potential security issues please advise.
UPDATE: I reworked the config working thru each step and making sure I used full paths etc. I have everything so far working, that is:
- All Port 80 is redirect to 443
- All requests redirect to www.example.com unless its a subdomain
- Redirect some subfolders to a folder outside for services such as phpmyadmin.
- Reverse Proxy subdomains to relevant server, and access different services on said server using subfolder eg. nas.examle.com is NAS GUI while nas.example.com/webmin is NAS Webmin UI.
Here is an update of my config so far.
<VirtualHost *:80>
# Redirect anything on port 80 to port 443
#ServerName example.com
ServerAdmin support@example.com
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 support@example.com
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 support@example.com
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 support@example.com
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>
Now what I am trying to do is use a subfolder from the document root, to hold all files relevant for authentication. At this stage is simply a form, an image, css file and the .htaccess with credentials. This will change a little later to a form that will validate against an LDAP server instead of the .htaccess.
My goal is to lock down ALL access to the server, weather the local site, phpmyadmin or a reverseproxy, so I get the authform (in /mnt/WWW/example.login/) before given access to what was requested.
Now I have had this working before, so I believe my problem has something to do with the order or structure of the code, but so far no matter what I try I am getting a Internal Server Error.
I changed the final www.example.com virtualhost to the following:
<VirtualHost *:443>
ServerName www.example.com
ServerAdmin support@example.com
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>
What is it I am doing wrong. Is it ordering, or have I overlooked something? Been on this for hours and is driving me nuts. I just need some fresh (and experienced) eys on this. Thanks.
BTW, just for clarity, all paths and domains are correct as I have them IRL. I only changed the real domain name used, to example.com etc to hide the real one.
Another Update:
I read somewhere (can't find again) that I can use the Auth stuff on the directory tag instead of the location. I read it was more secure. Not sure if its true or not, but I did get a config that sorta works:
<VirtualHost *:443>
ServerName www.example.com
ServerAdmin support@example.com
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>
Now, this config, gives me a partial form, and I am able to login and get the main root www.example.com site. phpmyadmin is not secured, and example.login is also not secured. I plan on securing phpmyadmin and others later, just doing 1 step at a time.
When I say partial, I mean the form shows, but there is an image in the page that is not showing. I think it is a security issue, as the page shows normally when no auth is in the config.
So My issue right now is the following, how can I have the example.login folder and ALL files in it bypass auth, and is there not a better way to put in the auth code so to apply to everything and controll what is locked with the Require valid-user?