How to set up SSL for localhost and virtual hosts with MAMP? - apache

I'm creating this "question" to document how I was able to set up SSL locally, in case I need to do this again in the future. Thought I'd document it here hoping this can be of help to others too, 'cause it's a tricky process.
I'm working on a Mac with High Sierra, MAMP v 4.2.1 and Chrome v 71
Alright, let's roll.

1) Create a SSL certificate for localhost
To be able to use HTTPS with localhost we actually need two certificates: a root certificate, and a domain certificate specifically created for the localhost domain.
These nifty scripts I've found take care of creating both. They're very easy to use—just follow the instructions closely and you'll be good to go. The only thing that is not so clear in the documentation is that, where it says Then mark the certificate as trusted, this means you have to click on the certificate in Keychain Access and change the Trust option to Always.
(Here you can find a more elaborate explanation of what those scripts actually do)
If everything worked for you, you should now have two files server.crt and server.key. I've created a ssl folder in /Applications/MAMP and moved the files in it; but you can put them wherever you think is best.
Let's forget about the files now and proceed to some Apache configuration.
2) Configure MAMP's Apache to accept SSL
By default, Apache is not configured to accept SSL connections, so we have to change that. Open /Applications/MAMP/conf/apache/httpd.conf and make sure the following lines are NOT commented out. If they are, remove the # at the beginning of the line:
LoadModule ssl_module modules/mod_ssl.so
Include /Applications/MAMP/conf/apache/extra/httpd-ssl.conf
Also, look for this line:
Servername localhost:443
and make sure the port is set to 443. 443 is the default port for HTTPS secured connections (regular, unsecured HTTP connections listen to port 80 by default).
Next, open /Applications/MAMP/conf/apache/extra/httpd-ssl.conf and make sure you have this line:
Listen 443
Again, this is important because we have to set up everything on the same port. To this end, you should also click on the MAMP icon in your MAC's dock, hit Preferences, go to the Ports tab and choose Set Web & MySql ports to 80 & 3306.
Stop and restart MAMP to apply the changes we've made so far.
3) Configure the default Virtual Host for SSL
While still in /Applications/MAMP/conf/apache/httpd.conf, look for these lines:
<VirtualHost _default_:443>
# General setup for the virtual host
DocumentRoot "/Applications/MAMP/Library/htdocs"
ServerName www.example.com:443
These lines set Apache's default behavior for all HTTPS connections. The ServerName is just a dummy name that you should replace with localhost; you should also make sure that the default DocumentRoot does match with your projects root folder.
So change the above lines as follows:
<VirtualHost _default_:443>
# General setup for the virtual host
DocumentRoot "/path/to/your/htdocs"
ServerName localhost
As you scroll a bit further down, while we're still in the default VirtualHost directive, you will find these two lines:
SSLCertificateFile "/Applications/MAMP/conf/apache/server.crt"
SSLCertificateKeyFile "/Applications/MAMP/conf/apache/server.key"
Change these to wherever you put the files we genereated in step 1. Like I said before, I've put mine in "/Applications/MAMP/ssl", so I've changed the
above lines to:
SSLCertificateFile "/Applications/MAMP/ssl/server.crt"
SSLCertificateKeyFile "/Applications/MAMP/ssl/server.key"
Stop and restart MAMP to apply the changes. Now if you go to https://localhost you should be able to see the list of projects in your root folder. That's it for localhost!
4) Create a SSL certificate for custom local domains
What if you wanted to create a custom domain myproject.dev and use SSL for that too, so you could access it at https://myproject.dev?
Pretty much like what we did for localhost, we need to create a SSL certificate specifically for the myproject.dev domain, then configure a virtual host for myproject.dev. Let's start with creating the certificate.
Again, I've found this little tool called create-ssl-certificate that will generate for you an SSL certificate for a specific local domain. This too is very easy to use, the only not so clear part is that it is a NPM package that you can install globally with npm -g install create-ssl-certificate.
If everything went well with create-ssl-certificate, you should now have two files, just like it was with localhost in step 1. By default, create-ssl-certificate calls the generated files ssl.crt and ssl.key. I've renamed them as server.crt and server.key to be consistent with the localhost files. Then I've created a ssl folder in the myproject root folder, and moved the files in there.
Let's forget about the files for a moment and proceed to some Apache configuration.
4) Configure MAMP's Apache to accept Virtual Hosts
If you've created virtual hosts before, you have probably already done this, so you can skip this step.
The only thing we need to do to 'activate' the possibility of creating virtual hosts is to go to /Applications/MAMP/conf/apache/httpd.conf and uncomment this line:
Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf
5) Configure your local domain's Virtual Host for SSL
Now we can set up a virtual host so that we can access myproject at https://myproject.dev. First of all, edit your hosts file and add this line:
127.0.0.1 myproject.dev
Then, go to /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf and add the following:
<VirtualHost myproject.dev:443>
ServerName myproject.dev
DocumentRoot "/Users/myusername/Sites/myproject"
SSLEngine on
SSLCertificateFile "/Users/myusername/Sites/myproject/ssl/server.crt"
SSLCertificateKeyFile "/Users/myusername/Sites/myproject/ssl/server.key"
</VirtualHost>
With this configuration, you will be able to access https://myproject.dev because the server is instructed to search for the SSL certificates we've created in step 4.

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!

Create an SSL certificate for a Shiny server running on CentOS

I can't figure how to create an SSL certificate for a Shiny server that runs on a CentOS machine.
My end goal is to be able to access my app with HTTPS.
So instead of - HTTP://mydomain.com:3838/my-app/
To have something like - HTTPS://mydomain.com:3838/my-app/
Or even better - HTTPS://mydomain/my-app/
I tried my best with numerous tutorials but I'm not an expert in system administration and didn't have a lot of success.
Would really appreciate any help here!
# cat /etc/centos-release
CentOS Linux release 7.5.1804 (Core)
# shiny-server --version
Shiny Server v1.5.7.907
Thanks!
My answer in one word: letsencrypt.
Letsencrypt provides an executable that will grant you SSL certificates for all the domains your server handles. For this, it validates your machine by mounting a temporary web server and checks if can reach it with the domain names you provided.
There's more info in the official website. Once you have the certs, simply add them to nginx or Apache or whatever web server you are using.
UPDATE:
To forward http calls to your shiny web server you have to use Apache web server as a proxy, that means, that every call yo yourdomain:80, will be redirected to locahost:3838.
You have to edit your default conf. In ubuntu you can find it in this path: /etc/apache2/sites-enabled/000-default.conf
Then, in the conf file:
<VirtualHost *:80>
# These lines configures SSL
SSLEngine on
SSLCertificateFile /path/to/your/ssl.crt
SSLCertificateKeyFile /path/to/your/ssl.key
# These lines configure the proxy
ProxyPreserveHost On
ProxyPass / http://0.0.0.0:3838/
ProxyPassReverse / http://0.0.0.0:3838/
# This sets the domain name to listen for
ServerName yourdomain.com
</VirtualHost>
Then, restart apache and you're good to go.

Apache mass virtual host configuration issue

I'm brand new to VPS hosting, so bear with me.
I recently purchased a VPS through inmotion hosting. It has Apache, cPanel and WHM installed out of box. I'm not sure if this is important, but at the top right of the WHM root login it shows: CENTOS 7.3 x86_64
I'm working on developing a system where users can sign up with me and be provided with a sub domain like so: theirUsername.mydomain.com. This will point to a directory on my server where their files will be located. People should also be allowed to have a domain name with my nameservers. I need the system to automatically detect their domain name and point it to where their directory is. It's just like if I were to manually log into cPanel and create an addon domain, but I need this process to be automated. I also need the sub domain to remain and I need to be able to install SSL certs for these domains.
My system would be VERY similar to how Squarespace works.
I've read into mass virtual hosting but cannot for the life of me figure out how to get it working or if it would even be what I'm looking for.
I've tried configuring the virtual hosting but have had no luck. Just for testing purposes I was trying a single domain. Here is my code:
NameVirtualHost *:80
Listen 80
<IfModule mod_ssl.c>
# SSL name based virtual hosts are not yet supported, therefore no
# NameVirtualHost statement here
Listen 443
</IfModule>
<VirtualHost *:80>
DocumentRoot "/home/username/www/domain.com"
ServerName www.domain.com
ServerAlias domain.com
ErrorLog "/home/username/www/domain.com/error.log"
CustomLog "/home/username/www/domain.com/requests.log" common
</VirtualHost>
The log files are making it to that directory but visiting the domain gives me a "This site can’t be reached" error in Chrome.
Any tips would be greatly appreciated.
Thanks!

Cannot setup SSL keys on my apache server in AWS EC2

I have an EC2 instance on AWS, with Apache server.
I purchased an SSL certificate from Comodo and installed the following files in /etc/pki/tls/private/:
server.ca-bundle server.crt server.key
I also added the following lines to /etc/httpd/conf/httpd.conf:
<VirtualHost www.mydomain.com:443>
ServerName www.mydomain.com
DocumentRoot "/var/www/html"
SSLENGINE on
SSLCertificateFile /etc/pki/tls/private/server.crt
SSLCertificateKeyFile /etc/pki/tls/private/server.key
SSLCertificateChainFile /etc/pki/tls/private/server.ca-bundle
</VirtualHost>
and restarted the http server.
But when trying to access my site through https://www.mydomain.com there is a certificate error warning (but if I continue through the warning, the site shows well).
I checked with ssltool.com and got:
The site tested www.mydomain.com is NOT the same as the Subject CN ip-10-203-65-225!
Needless to say, the key file was created with my domain name (CN=www.mydomain.com) and not with the name containing the ip.
When I enter "hostname" in the unix shell, I indeed get 'ip-10-203-65-225', which is something that Amazon gave it automatically. But even if I change it (in /etc/sysconfig/network) it is still seen as ip-10-203-65-225.
On the other hand, the same problem is viewed without installing the keys: Even if I remove those lines from httpd.conf, and remove the key files, the browsers warn about a certificate error, as if there is a self-signed certificate and with the same error on ssltool.com. So it seems that it's not that my key files are invalid but rather that the server doesn't use them at all...
I'm totally confused. Please can anybody help?
For some reasons, none of the pages I visited to seek for the answer mentioned that the above lines should be in
/etc/httpd/conf.d/ssl.conf
and not in
/etc/httpd/conf/httpd.conf
(and not inside a <virtualHost> section)
Your certificate was issued to a Common Name (CN) matching the hostname of your EC2 instance. You need to create a new CSR using the correct hostname and go through the entire process again. When you generate the new CSR, be sure to change the CN rather than accept the default.

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.