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.
Related
I've read a lot of questions and answers which seem exactly the same as mine, but I can't seem to get my setup to work. I have a VM running Apache with only HTTP support at 192.168.2.101:32773. I can access it on my local network as such just fine. I now am ready to expose it through my Apache web server that has Lets Encrypt setup to generate SSL certificates. So I added this to my server conf file:
<VirtualHost *:32773>
ServerName server.com
SSLEngine on
SSLProxyEngine On
SSLCertificateFile /etc/letsencrypt/live/server.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/server.com/privkey.pem
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://192.168.2.101:32773/
ProxyPassReverse / http://192.168.2.101:32773/
</VirtualHost>
However, I get an ERR_SSL_PROTOCOL_ERROR when I try to load it up as https://server.com:32773. If I however change my address to http://server.com:32773, it loads just fine. Anything look wrong in this snippet? Thanks!
HTTP and HTTPS need to be on different ports. Typically HTTPS is served on port 443.
This is embarrassing... At some point I changed my port forward rules to point 32773 directly to 192.168.2.101 so I could validate that the rules were working at all. The above config worked as soon as I realized I wasn't even sending traffic to my Apache SSL enabled server.
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!
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.
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.
Today I'm trying to configure Apache to run two domains each with their own SSL certificate. From what I have read this is supported by SNI as long as my Apache is configured with a recent version of OpenSSL. I verified that it is:
[notice] Apache/2.2.22 (Ubuntu) PHP/5.3.10-1ubuntu3.7 with Suhosin-Patch mod_ssl/2.2.22 OpenSSL/1.0.1 configured -- resuming normal operations
I thought I had successfully set up the second domain and certificate, but when I try to visit the second domain in chrome I get the following error:
You attempted to reach example2.com, but instead you actually reached a server identifying itself as example1.com.
this post seems closest to my issue:
hosting multiple SSL certs on apache
but from what I can tell my server is already configured correctly (clearly it is not!)
I have the following directives in my conf file for example2.com
ServerName example2.com
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example2.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/example2.com.key
it looks right to me. so why is apache serving example1's cert when I visit example2?
turns out domain 1 was configured as
<VirtualHost *:443>
I use webmin, which only reveals that detail when you view the directive directly.
changing * was part of the solution but introduced some other problems. I think I will punt and do IP-based SSL.
I add this to ports.conf (Apache/2.2.22)
NameVirtualHost *:443
You can read details in this post
It's not possible to have multi SSL domain on the same ip addres.
context
When a client contact a https web site all communication are crypt with the site's public key (ssl certificat). Only the private key associate to the public key can decrypt the http request. basically that's how https work.
That why in your virtual host, you define for each ssl web site the certificate and the key
SSLCertificateFile /etc/apache2/ssl/example2.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/example2.com.key
VirtualHost Name base and SSL
When you use VirtualHost name base , when apache receive a client request the server read the request and look which domain name is requested. When the Domain Name is identified apache read virtuahost instruction and return the good web site.
When apache receive an SSL request , the system can't decrypt the message because apache need to use the SSLCertificateKeyFile defined in the Virtualhost but to know which virtualhost to use he need to be able to decrypt the message ....
Because apache don't know how to process your request the system return the first virtualhost processed.
That's why you need to use VirtualHost ip base that what is it use in the example :
hosting multiple SSL certs on apache
You have 2 ip 1.1.1.1 and 2.2.2.2
NameVirtualHost 1.1.1.1:443
NameVirtualHost 2.2.2.2:443
<VirtualHost 1.1.1.1:443>
ServerName www.domain1.com
...
...
</VirtualHost>
<VirtualHost 2.2.2.2:443>
ServerName www.domain2.com
...
...
</VirtualHost>
VirtualHost Name base and SSL wildcard certificat
If the private key AND the public key (ssl certificat) are the same for all domain, apache will be able to decrypt the communication. This situation append only when you use a wildcard certificate for a domain. example , if you have a wildcard for *.domain.com you can define VirtualHost name base like this
NameVirtualHost 1.1.1.1:443
<VirtualHost 1.1.1.1:443>
ServerName foo.domain.com
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/wildcard.domain.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/wildcard.domain.com.key
...
...
</VirtualHost>
<VirtualHost 1.1.1.1:443>
ServerName bar.domain.com
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/wildcard.domain.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/wildcard.domain.com.key
...
...
</VirtualHost>
This configuration will work because, whatever the domain, apache use the same private key to decrypt the communication so the system will be able to select the good VirtualHost setting.
Have a nice day.