Apache 2.4 Restrict SSL to specific subdomain Vhosts - apache

I have a single digitalocean droplet, with only a single IPV4 address possible. I would like to use SNI to apply TLS (SSL) encryption onto only a specific subdomain, and not any other parts of the domain.
Example being:
domain.com (No TLS)
sub.domain.com (TLS, certificate 1)
sub1.domain.com (TLS, certificate 2)
sub2.domain.com (no TLS)
I'm using LetsEncrypt for the certificates, so wildcard domains are not possible.
domain.com.conf
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
sub.domain.com
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName sub.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
</VirtualHost>
</IfModule>
sub1.domain.com
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName sub1.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
</VirtualHost>
</IfModule>
sub2.domain.com
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName sub2.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Two things you should be aware of:
You never know which protocols users are going to use. They will default to http if protocol not defined and some browser extensions will try https first and use that if it exists.
Apache will fallback to the first site defined for that port if there's not a better match. In which case you might end up serving the wrong site if, for example, you don't define a sub2.domain.com site on port 443.
So you should define all 4 domains on both port 80 and port 443 and basically have 8 vhosts defined.
This also means will need to buy (or get for free from LetsEncrypt) certificates to cover all domains and not just the two you want to serve over https.
Then you should use redirects appropriately:
domain.com (No TLS): Serve site on port 80. Config for port 443 should just redirect all traffic back to equivalent page on http://domain.com
sub.domain.com (TLS, certificate 1): Serve site on port 443. Config for port 80 should just redirect all traffic back to equivalent page on https://sub.domain.com
sub1.domain.com (TLS, certificate 2): Similar to sub.domain.com setup mentioned in point 2 above.
sub2.domain.com (no TLS): Similar to domain.com set up mentioned in point one above.
Example config:
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
sub.domain.com
<IfModule mod_ssl.c>
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName sub.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/%$1 [R,L]
</VirtualHost>
</IfModule>
sub1.domain.com
<IfModule mod_ssl.c>
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName sub1.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/%$1 [R,L]
</VirtualHost>
</IfModule>
sub2.domain.com
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName sub2.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-domain.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-domain.key
RewriteEngine On
RewriteRule (.*) http://%{SERVER_NAME}/%$1 [R,L]
</VirtualHost>
sub.domain.com
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName sub.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-subdomain.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-subdomain.key
</VirtualHost>
</IfModule>
sub1.domain.com
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName sub1.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-subdomain1.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-subdomain1.key
</VirtualHost>
</IfModule>
sub2.domain.com
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName sub2.domain.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-subdomain2.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-subdomain2.key
RewriteEngine On
RewriteRule (.*) http://%{SERVER_NAME}/%$1 [R,L]
</VirtualHost>
However if going to all this hassle then might want to rethink not serving everything over https.

Related

How to avoid repeating virtualhost properties in apache?

I want my sites served via SSL to have a bunch of the same properies in my apache2 config. Unfortunately, I can't find anywhere that demos how to do that. Here's my config at the moment for two separate servers accessed by www.mydomain.com and blog.mydomain.com:
<IfModule mod_ssl.c>
<VirtualHost *:443>
DocumentRoot /var/www/html
ServerName www.mydomain.com
# Repeated stuff
ServerAdmin webmaster#localhost
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.com/privkey.pem
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /var/www/wordpress
ServerName blog.mydomain.com
# Repeated stuff
ServerAdmin webmaster#localhost
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.com/privkey.pem
</VirtualHost>
</IfModule>
As you can see, both virtualhosts have a lot of the same properties under #Repeated stuff. How can I specify these properties once and then have ONLY these virtualhosts inherit those properties? E.g. can virtualhosts be nested?
mod_macro gave me just what I wanted. On ubuntu it can simply be enabled with sudo a2enmod macro. My apache2 SSL config now looks something like this:
<IfModule mod_ssl.c>
<Macro SSLStuff>
ServerAdmin webmaster#localhost
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
</Macro>
<VirtualHost *:443>
Use SSLStuff
DocumentRoot /var/www/html
ServerName mydomain.com
ServerAlias www.mydomain.com
</VirtualHost>
<VirtualHost *:443>
Use SSLStuff
DocumentRoot /var/www/wordpress
ServerName blog.mydomain.com
</VirtualHost>
<VirtualHost *:443>
Use SSLStuff
ServerName mynodeapp.mydomain.com
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>
</IfModule>

Malformed Request Line With SSL on Ubuntu

I'm in the process of setting up a droplet at DigitalOcean. I would like to serve multiple sites from the same droplet and use LetsEncrypt SSL certs. When accessing a test site, I see an error in the logs "AH00566: request failed: malformed request line" and in the Chrome I see "ERR_SSL_PROTOCOL_ERROR".
It seems that I likely have a configuration error somewhere but am not sure where.
The conf for my site is:
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName mydomain.com
ServerAlias www.mydomain.com
DocumentRoot /var/www/mydomain.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.mydomain.com [OR]
RewriteCond %{SERVER_NAME} =mydomain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:443>
<Directory /var/www/mydomain.com>
AllowOverride All
</Directory>
ServerAdmin webmaster#localhost
ServerName mydomain.com
ServerAlias www.mydomain.com
DocumentRoot /var/www/mydomain.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.com/privkey.pem
</VirtualHost>

Reverse Proxy works but not Virtual Host in the secondary RPi Web Server

I have two RPi(3+), both use for LAMP web server. And their relation is like this image
So, Rpi1 is the one directly talks to my home router and I set up reverse proxy to retrieve RPi2 Data.
My problem is I was able to access both RPi1 sites with their domains (static1.com and wordpress1.com) but both of RPi2 domains(static2.com and wordpress2.com) lead to the same site(wordpress2.com).
I assume my virtual host setting in RPi2 has some problem but could not find any clue yet... I need help solving this apache setting issue!
Here is my set up in RPi 1 Apache server,
static2.com setting:
pi#cloelee:/etc/apache2/sites-available $ cat static2.com.conf
<VirtualHost *:80>
ServerAdmin webmaster#example.com
ServerName static2.com
ServerAlias www.static2.com
SSLProxyEngine on
ProxyPass / http://192.168.1.18/
ProxyPassReverse / http://192.168.1.18/
ProxyPreserveHost Off
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#example.com
ServerName static2.com
ServerAlias www.static2.com
SSLProxyEngine on
ProxyPass / http://192.168.1.18/
ProxyPassReverse / http://192.168.1.18/
ProxyPreserveHost Off
SSLCertificateFile /etc/letsencrypt/live/static2.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/static2.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
wordpress2.com setting:
pi#cloelee:/etc/apache2/sites-available $ cat wordpress2.com.conf
<VirtualHost *:80>
ServerAdmin webmaster#example.com
ServerName wordpress2.com
ProxyPass / http://192.168.1.18/
ProxyPassReverse / http://192.168.1.18/
ProxyPreserveHost Off
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster#example.com
ServerName wordpress2
ProxyPass / http://192.168.1.18/
ProxyPassReverse / http://192.168.1.18/
ProxyPreserveHost Off
</VirtualHost>
And this is my setup in RPi2 Apache Server,
static2.com setting:
pi#kyongoh:/etc/apache2/sites-available $ cat static2.com.conf
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName static2.com
ServerAlias www.static2.com
DocumentRoot /var/www/static2.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteCond %{HTTP_HOST} ^(www\.)?static2\.com$
RewriteRule (.*) https://static2.com/$1 [L,R,NE]
</VirtualHost>
pi#kyongoh:/etc/apache2/sites-available $ cat static2.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName static2.com
ServerAlias www.static2.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/static2.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/static2.com/privkey.pem
</VirtualHost>
</IfModule>
wordpress2.com setting:
pi#kyongoh:/etc/apache2/sites-available $ cat wordpress2.com.conf
<VirtualHost *:80>
<Directory "/var/www/wordpress2.com">
AllowOverride All
</Directory>
ServerName wordpress2.com
ServerAdmin webmaster#local_wordpress
DocumentRoot /var/www/wordpress2.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster#example.com
ServerName wordpress2.com
ServerAdmin webmaster#local_wordpress
DocumentRoot /var/www/wordpress2.com
</VirtualHost>
As you may realize wordpress2.com has not SSL yet but static2.com has. Do you see why both RP2 domains request wordpress2 data? what did I miss?
Thanks for help!
It was simple fix, just missed to turn ProxyPreserveHost on
ProxyPreserveHost Off
to
ProxyPreserveHost On

Apache virtual host from GET url

<VirtualHost *:80>
ServerAdmin admin#example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Above is the example of https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-hosts-on-ubuntu-14-04-lts which I've followed to setup some sites. But what I wanna do is basically:
www.example.com?site=mynewsite.com
With htaccess: www.example.com/mynewsite.com
<VirtualHost *:80>
ServerAdmin admin#example.com
ServerName example.com/mynewsite.com
ServerAlias www.example.com/mynewsite.com
DocumentRoot /var/www/example.com/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Sadly above doesn't work.
Reason why I wanna do this is because I want to generate a website using database which will be triggered based of URL.
How may I do?
You could try the obscure ServerPath directive, which maps a request to a virtualhost based on the first component of the URL path.

Apache htpasswd for multiple websites/dirs?

I'm not 100% familiar how htpasswd works, but i'm wondering if it is possible.
I have one server with one IP and multiple domains there. I need to password protect all of those domains but if possible only at one place. I don't want to go around and make htpasswd for each website.
Assuming that i have all websites places under /var/www/{vhost dirs}
Is it possible at all and how and how?
Multiple domain on single IP is possible from virtual host configuration in apache.
E.g I am running few domains on single machine :
www.internationalworkersday.com
www.internationallabourday.com
www.internationlaborday.com
www.internationalworkersday.org
www.apnok.com
#Here is virtual host configuration in httpd.conf
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for requests without a known
# server name.
#
<VirtualHost *:80>
ServerAdmin www.apnok.com
DocumentRoot /home/ap/
ServerName www.apnok.com
ServerAlias apnok.com *.apnok.com
ErrorLog logs/error_log
CustomLog logs/access_log common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin www.internationalworkersday.com
DocumentRoot /home/iwd/
ServerName www.internationalworkersday.com
ServerAlias internationalworkersday.com
ErrorLog logs/error_log
CustomLog logs/access_log_iwd common
</VirtualHost>
<VirtualHost *:80>
# ServerAdmin www.internationallabourday.com
DocumentRoot /home/ild/
ServerName www.internationallabourday.com
ServerAlias internationallabourday.com
# ErrorLog logs/error_log
#CustomLog logs/access_log_ild common
RewriteEngine On
RewriteCond %{HTTP_HOST} ^internationallabourday\.com [NC]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ http://www.internationalworkersday.com
#DirectoryIndex index.php index.php.var
</VirtualHost>
<VirtualHost *:80>
ServerAdmin www.internationallaborday.com
DocumentRoot /home/ila/
ServerName www.internationallaborday.com
ServerAlias internationallaborday.com
ErrorLog logs/error_log
CustomLog logs/access_log common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin www.internationalworkersday.org
DocumentRoot /home/iwd/
ServerName www.internationalworkersday.org
ServerAlias internationalworkersday.org
ErrorLog logs/error_log
CustomLog logs/access_log_org common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin www.internationallabourday.org
DocumentRoot /home/ild/
ServerName www.internationallabourday.org
ServerAlias internationallabourday.org
ErrorLog logs/error_log
CustomLog logs/access_log_org common
</VirtualHost>