SNI Dynamic Certificate - apache

I'm pulling my hair out here.
Websites like wix.com, squarespace.com ...etc; can generate websites on the fly and still use SSL on every one of the millions of custom domains.
I try to do the same thing, but I can't figure out how they do it!?
The logical solution would be on Apache:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAlias *
UseCanonicalName Off
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/%0/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/%0/server.key
</VirtualHost></IfModule>
But when I restart apache I get an error: SSLCertificateFile: file '/etc/apache2/ssl/%0/server.crt' does not exist or is empty
Even when I create a dummy folder /ssl/%0/ with some dummy certificates... it still used the (wrong) dummy certificates.
I know some will get on their high horses and yell that you cannot resolve the server name BEFORE the TLS handshake.
But according to this post and other ones: %0 can be resolved with mod_vhost_alias because the server name is sent with SNI...
I know this works: a second approach would be to create a virtualhost for every custom domain:
<VirtualHost *:443>
ServerName site111.ca
ServerAlias www.site111.ca
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile "/var/app/s3/ssl/site111.ca/certificate.crt"
SSLCertificateKeyFile "/var/app/s3/ssl/site111.ca/certificate.key"
SSLCertificateChainFile "/var/app/s3/ssl/site111.ca/certificate.chain"
</VirtualHost><VirtualHost *:443>
ServerName site222.ca
ServerAlias www.site222.ca
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile "/var/app/s3/ssl/site222.ca/certificate.crt"
SSLCertificateKeyFile "/var/app/s3/ssl/site222.ca/certificate.key"
SSLCertificateChainFile "/var/app/s3/ssl/site222.ca/certificate.chain"
I could create a dirty system where I add one virtual host per new domain and reload apache every day Eeewwww... and again: Apache cap the number of virtual hosts to 256 :/
How do they do it!? Is there other technology that can help me? Nginx, Nodejs?
Thank you for your time.

I try to do the same thing, but I can't figure out how they do it!?
To generate SSL websites on the fly, they use Letsencrypt certificate authority as you can check yourself (example : CN = www.thefoodmarketchiswick.com). But for the websites hosted under .wix.com names, they're just using a wildcard certicate ( CN = *.wix.com ) . Till then, easy.
The second question, as you mentioned Apache could not handle this massive hosting (and no one believes you could host millions of applications on one single server). Have a look on this Netcraft Survey which gives some clues. I can't answer for them, but running an openssl s_client ends in error, meaning they aren't doing very compliant things.

TL;DR: they use wildcard certificates. So the problem is solved # the certificate level and at the server config level, not only at the server config level like you are trying to do.
Couple of points:
The logical solution - hardly do I see anything "logical" in Computer Science or Software Engineering. It's engineering, not math, you have to DO stuff, not THINK stuff up. So knowledge becomes more important than intelligence in a lot of cases (not all).
You have a correct point about SNI - it is a push-back of host identification meachanism to the TCP/SSL layer (prior to HTTP where HTTP headers become available).
virtualhost for every custom domain - Depending on the scale we are talking about, it could work. However, if you onboard a client with 200, 1000, 5000 - subdomains. What then?
How do they do it - Let me just provide examples: HTTP proxy like cloudflare generates a free certificate for you, that you have to add on your server (PROXY->ORIGIN ecryption) and END_USER -> CLOUDFLARE connection is encrypted using a wildcard certificate. These are the DNS names of the wildcard certificate they issued for me:
Abbreviated:
DNS Name=sni178747.cloudflaressl.com
DNS Name=*.9992924.com
DNS Name=*.apum.de
DNS Name=*.arbomedia.net
DNS Name=*.australiacasinobonus.net
DNS Name=*.auto-lpg.de
DNS Name=*.autoprof.de
DNS Name=*.circuitodesafio.com.br
DNS Name=*.data--center.info
DNS Name=*.devclub.com
DNS Name=*.eissportanlagen.de
DNS Name=*.entrepreneur-hebdo.fr
DNS Name=*.environmentalbrasil.com.br
DNS Name=*.gofitnessplan.fr
DNS Name=*.golfinterieur.info
DNS Name=*.greenbuch.cf
DNS Name=*.mindaugas.cf
DNS Name=*.mp3fdm.trade
DNS Name=*.mp3freedom.info
DNS Name=*.mp3star.cricket
DNS Name=environmentalbrasil.com.br
DNS Name=gofitnessplan.fr
DNS Name=golfinterieur.info
DNS Name=greenbuch.cf
DNS Name=mindaugas.cf
DNS Name=mp3fdm.trade
DNS Name=mp3freedom.info
DNS Name=mp3star.cricket
DNS Name=preussische-geschichte.de
How does the configuration of such server look? It is really a server farm, under a loadbalancer, w/ resources shareded (static resources on separately tuned machines w/ cache). There are multiple virtual hosts / domains / host aliases on each of the server, but only 1 SSL file for many of them (or all, depending on the scale). The domains can have dedicated configurations, they can be grouped together if their configurations are identical.
Regarding webserver recommendations - unless there is a good reason to use APACHE, I would not use it. There is a reason why nginx is gaining traction and popularity.

Related

How to use different vhost config files for Apache with SNI & multiple SSL certificates?

Ran into an issue with one of our setups, not to sure if that's even possible.
We're running a simple Ubuntu 18.04LTS server with PHP-FPM and Apache installed, that will host over a dozen different sites, with at least half of them having different SSL certificates. The server only has a single IP address/NIC.
To make everything easier to manage, I had initially created different vhost config files in /etc/apache2/sites-available, so every site would have their own; this was causing issues as one of the sites would be deemed "default" for SSL and its certificate would be handed out to all the other sites.
Going through StackOverflow and the internet, I've found a lot of posts that were saying to have a single vhost config file with all of our different site configurations...but now I have a thousand line config file, which is a mess to manage.
Is there a way to use SNI, with a single IP/NIC, with different vhost config files, or is our setup "uncommon" and we'll need to use a single vhost config file ?
Thanks!
EDIT: Link to a copy of the vhost config we use, sanitized of course: https://pastebin.com/1tQYBSxR
This is how Apache works for SSL VirtualHosts by default:
<VirtualHost *:443>
ServerName site1.com
# Certs definitions for site1.com
</VirtualHost>
<VirtualHost *:443>
ServerName site2.com
# Certs definitions for site2.com
</VirtualHost>
<VirtualHost *:443>
ServerName site3.com
# Certs definitions for site3.com
</VirtualHost>
Now you would expect that when a client connects with one of the sites, Apache understands which site it wants and uses that certificate, right?
But that is not the case. Apache does not know which site is asked for until after SSL negotiation is done. It must therefore always use the first VirtualHost certificate.
NameVirtualHost (Apache 2.2 directive, always on in v2.4) does not work for SSL.
You can put the definitions of each domain in a separate file. As long as they are all Included in the global config file. But again, only the first defined VirtualHost will serve *.443 requests.
In fact I have managed Apache servers with ~50 VirtualHost definitions, and having them all in one file would have been a nightmare. Split them by domain. You can even name the file THE_DOMAIN.conf.
Now how to get rid of that problem:
have 1 IP per domain. Which means 1 IP per VirtualHost. That way Apache knows which site the user requested, right form the start. But that requires as many addresses as you have domains.
have 1 port per domain. Instead of using port 443, some sites could use a non-default port. But that is weird for clients who have to specify the port in the request. Ex. https://example.com:445/. In enterprise setups, you can get your firewall-nat-proxy to change the port back for the client, but this is out of scope of this answer. This might be blocked as they are not default ports.
use SNI. This is supported by modern browsers, where the identification of the desired domain is sent at the time of SSL negotiation.
Using SNI is detailed here (and other references on the web) https://cwiki.apache.org/confluence/display/httpd/NameBasedSSLVHostsWithSNI
Overview:
the first VirtualHost is still the default used for clients that do not support SNI (older browser for example).
A new directive was added: SSLStrictSNIVHostCheck
You must use a minimum version of OpenSSL on the host, and Apache must have been compiled with it. It must enable TLS extensions.
Have fun!

Multiple Domain Hybris Server configuration

I have a Hybris server installation hosting two sites hosted on two directories /site1 and /site2 pointing to two different domains such as www.site1.com and www.site2.com and both domains point to same ELB endpoint. In our current setup, we use the proxy web server (rewrite method) to add the /sitepath to the domain names. Eg: ELBcname/site1 and ELBcname/site2. We do this because both sites are deployed in the same instance.
As far as I know Hybris installation use apache-tomcat as their application web server. Can I do Apache Namevirtualhost configuration to point the two domains to these with different document root to avoid using the proxy server?
Eg:
<VirtualHost *:80>
DocumentRoot "/hybrisdocroot/site1/"
ServerName site1
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "/hybrisdocroot/site2/"
ServerName site2
</VirtualHost>
Or is there any provision to add the path to Cname of ELB or ALB?
I would drop the proxy entirely, terminate SSL at the ELB with ACM Certificates on each domain (ie ssl common name *.site1.com and *.site2.com) and eliminate the path completely. Let the site answer at the fully qualified domain name (FQDN) only, and ideally only on HTTPS - HTTP is really disfavored now IMHO.
The path construction you indicate may have been used to simplify SSL termination and eliminate the number of certs needed for the service. Since ACM certs are free, the goal should be to provision each site with its own proper SSL cert.
Or is there any provision to add the path to Cname of ELB or ALB?
No. And in any case not needed if you eliminate the path from the URI to reach each site. And of course you can use ELB CNAMEs/ALIAS for a FQDN.

SSL on subdomain and primary domain - ehost

I have issue with my provider - ehost.
I have wildcard certificate. I wanted to first test it before I go live. So I request to install it on subdomain first (uat.domain.com). I have tested application and want to go live. Provider said that it is impossible to install certificate on primary domain (domain.com) because they have installed it first on subdomain.
Of course they have offered me to buy certificate from them.
I really don't understand the issue can someone tell me if they have right or not? I thought that is possible even to take the certficate from ehost and send it to another provider and install it. The certificate is now installed on Apache Server and folders to subdomain and primary domain are in the same server.
Without looking at the actual configuration it is hard to tell, but to answer your question, if they say it is impossible, that is because they are just using 1 VirtualHost in their server.
Generally shared hosting have these kind of issues because they dedicate 1 single instance of Apache to many different clients and have 1 virtualhost per client, but this is just guessing you need to check this is what currently happening.
But I can also describe how Apache works so you understand what may be happening:
If the Apache configuration has different virtualhosts, you can have as many different certificates, wildcards and whatnot, as virtualhosts you have.
This is, 1 certificate per VirtualHost.
But that is not all, if you have several different domain or subdomain names this is when you need to carefully plan how you must configure them.
For instance
If you have defined this virtualhost first:
<VirtualHost *:443>
ServerName example.com
ServerAlias *.example.com
</VirtualHost>
No other virtualhosts for whatever.example.com or example.com will apply or be used since this virtualhost will grab all the requests for those names.
But if you have:
<VirtualHost *:443>
ServerName domain.com
</VirtualHost>
And now you need to define a virtualhost with a new wildcard certificate for your subdomain, you can perfectly do using the new wildcard certificate for *.example.com:
<VirtualHost *:443>
ServerName xxxxx.example.com
</VirtualHost>
and can now define more virtualhosts if you want/need with the same wildcard cert for *.example.com:
<VirtualHost *:443>
ServerName yyyyy.example.com
</VirtualHost>
Note these are stripped down virtualhost examples (obviously your virtualhosts will have more directives inside them, specially the ones loading the key and certificates, etc).
And briefly, things you need to consider:
Apache HTTPD looks at Host header to know to which virtualhost it must deliver the request.
If you overlap names or define too greedy serveraliases, further defined virtualhosts may never receive requests if the previous virtualhosts matches the host name requested. This is, first match in virtualhost list wins.
Apache lets you have 1 certificate per virtualhost, it does not matter if you use the same certificate in several virtualhosts though.
You just have to be careful of not overlapping names and wildcards if you use ServerAlias. Having two virtualhosts covering the same name will just make httpd ignore the second virtualhost for the same name.
If you have several different files for different virtualhosts, their files are read in alphabetical order, so if you have a-virtualhost.conf with servername 1.example.com and b-virtualhost.conf also with servername 1.example.com, b-virtualhost.conf will be ignored.

Why should we create A DNS record for subdomains when we can do it via httpd.conf?

I want to implement a blog in my site with usernames as subdomains like user1.domain.com.
I've read bunch of articles that was mentioned to create an A record like below in DNS:
*.domain.com A 127.0.0.1 ;OR you site ip address
Then use .htaccess to redirect requests from subdomains to a folder in your server.
But I find another approach that was said to just modify your httpd.conf as below:
<VirtualHost *:80>
DocumentRoot /abs/path/to/webroot
ServerName domainname.com
ServerAlias *.domainname.com
<Directory /abs/path/to/webroot>
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Then retrieve subdomains via $_SERVER['HTTP_HOST'].
The question is why should someone use htaccess and put pressure on apache and create A DNS record when we can do a simple thing like ServerAlias *.domainname.com in httpd.conf?
I appreciate in advance for your views.
You need to setup both a wildcard DNS record and configure a server alias in httpd.conf to enable the hosting of arbitrary sub domains. They configure completely different things.
Add the wildcard DNS records is what allows clients to determine the IP address of your sub domain. With the wildcard DNS record about user1.domain.com will resolve to 127.0.0.1. If you do not have a DNS record no user1.domain.com will not be a valid name and it will not resolve to an IP address. the DNS record is to allow clients to connect to your server.
The httpd.conf configuration is local to your Apache server. It does not affect clients. The line ServerAlias *.domainname.com will configure Apache to tell it to process the arbitrary sub domains. Client's will not be directly affected by this setting.
You have added the ServerAlias, but for your computer to find that user1.domain.com and user2.domain.com should resolve to 127.0.0.1, you need to update your HOSTS file or DNS Table.
The configuration you have written is for Apache Server for handling the redirects when the user requests the domain. So, essentially, either you need a Dynamic HOSTS file or a service which resolves *.domain.com to your 127.0.0.1 server.
Hope this helps. :)

Apache Name Virtual Host with SSL

I am attempting to setup our servers to allow traffic over SSL. I am aware that SSL does not work with Name Virtual Host, but we have all of our Apache servers on virtual machines with dedicated private IPs. We have a primary virtual machine that has mod_proxy setup to route traffic to the appropriate VMs.
However, in order to route HTTPS traffic we need to have the certificate installed on the proxy as well as the VMs. We have a wildcard certificate that can be used across all of our hosts. Everything appears to work properly, but I receive the following in the Apache logs for the proxy:
[warn] Init: SSL server IP/port conflict: host1.example.com:443 (/etc/apache2/sites-enabled/host1:1) vs. host2.example.com:443 (/etc/apache2/sites-enabled/host2:1)
There is one of these error message for each host we have setup on the proxy. Our Virtual Host setup for the proxy is posted below:
<VirtualHost ipaddress:443>
ServerName host1.example.com
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / https://privateip:443/
ProxyPassReverse / https://privateip:443/
SSLProxyEngine on
SSLEngine on
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
</VirtualHost>
Is there any way that I can get this to work?
It sounds like Apache is warning you that you have multiple <VirtualHost> sections with the same IP address and port... as far as getting it to work without warnings, I think you would need to use something like Server Name Indication (SNI), a way of identifying the hostname requested as part of the SSL handshake. Basically it lets you do name-based virtual hosting over SSL, but I'm not sure how well it's supported by browsers. Other than something like SNI, you're basically limited to one SSL-enabled domain name for each IP address you expose to the public internet.
Of course, if you are able to access the websites properly, you'll probably be fine ignoring the warnings. These particular ones aren't very serious - they're mainly an indication of what to look at if you are experiencing problems
As far as I know, Apache supports SNI since Version 2.2.12
Sadly the documentation does not yet reflect that change.
Go for http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI until that is finished
You may be able to replace the:
VirtualHost ipaddress:443
with
VirtualHost *:443
You probably need todo this on all of your virt hosts.
It will probably clear up that message. Let the ServerName directive worry about routing the message request.
Again, you may not be able to do this if you have multiple ip's aliases to the same machine.
The VirtualHost would look like this:
NameVirtualHost IP_Address:443
<VirtualHost IP_Address:443>
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/ca.crt # Where "ca" is the name of the Certificate
SSLCertificateKeyFile /etc/pki/tls/private/ca.key
ServerAdmin webmaster#example.com
DocumentRoot /var/www/html
ServerName www.example.com
ErrorLog logs/www.example.com-error_log
CustomLog logs/www.example.com-access_log common
</VirtualHost>
First you need NameVirtualHost ip:443 in you config file!
You probably have one with 80 at the end, but you will also need one with 443.
Second you need a *.domain certificate (wildcard) (it is possible to make one)
Third you can make only something.domain webs in one ip (because of the certificate)
You MUST add below part to enable NameVirtualHost functionality with given IP.
NameVirtualHost IP_Address:443
Apache doesn't support SSL on name-based virtual host, only on IP based Virtual Hosts.
Source: Apache 2.2 SSL FAQ question Why is it not possible to use Name-Based Virtual Hosting to identify different SSL virtual hosts?
Unlike SSL, the TLS specification allows for name-based hosts (SNI as mentioned by someone else), but Apache doesn't yet support this feature. It supposedly will in a future release when compiled against openssl 0.9.8.
Also, mod_gnutls claims to support SNI, but I've never actually tried it.