Simple ssl termination with multiple certificates. Nginx/haproxy or other? - ssl

Currently I have multiple vhosts in many configuration files with dedicated certificates.
My goal is to reach simple server configuration which support multiple certificates in one simple config (I want merge multiple vhosts files into one). I've tried with nginx something like:
server {
listen 443 default_server ssl;
ssl_certificate /etc/nginx/ssl.d/*/cert.pem;
ssl_certificate_key /etc/nginx/ssl.d/*/privkey.pem;
#
# detailed ssl config
#
location / {
proxy_pass http://other_location:80;
#
# detailed proxy config
#
}
}
but it returns:
nginx: [emerg] BIO_new_file("/etc/nginx/ssl.d/*/cert.pem") failed
(SSL: error:02001002:system library:fopen:No such file or
directory:fopen('/etc/nginx/ssl.d/*/cert.pem','r') error:2006D080:BIO
routines:BIO_new_file:no such file)
I don't want configure any hostnames (maybe I wrong?).
And also I don't want rather configure paths to certificates multiple times in haproxy nor other maps.
Any idea?

With haproxy I can pass directory with certificates and it works!
frontend www-https
bind *:443 ssl crt /etc/ssl/private/

A possible solution/workaround would be to generate a single multi site cert in one location using letsencrypt. You can generate simple scripts to then have the cert and key cat to one file for haproxy to use.
That would save remembering locations for the config files.

Related

Nginx NET::ERR_CERT_COMMON_NAME_INVALID

I'm trying to enable ssl certificates for my web app deployed on DigitalOcean but when I'm accessing the droplet ip I'm getting this error:
NET::ERR_CERT_COMMON_NAME_INVALID
This server could not prove that it is droplet-ip-address; its security certificate is from *.domain.com. This may be caused by a misconfiguration or an attacker intercepting your connection.
This is my nginx configuration:
server {
# SSL configuration
#
listen 443 ssl;
server_name sub.domain.com;
ssl_certificate /etc/nginx/ssl/star-op/__company_com.ca-chain.cert.pem
ssl_certificate_key /etc/nginx/ssl/star-op/__company_com.key;
}
At this moment I don't have any DNS record from sub.domain.com that points to my ip address... can this be the cause of that error?
Without a DNS entry, you are doing something like https://x.x.x.x which nginx associating with https://sub.domain.com most likely as it is the only server block in nginx at this time.
But https://x.x.x.x does not match the cert for https://sub.domain.com so your are getting a mismatch. If you are just testing you could add a host file entry for testing which should get you past this issue. Afterward, you would need to add a DNS entry to your public DNS server for the rest of the world to not have this issue.

Domain without ssl certificate redirecting to different ssl domain

I have two domains set up on a Digital Ocean droplet (with nginx). I've installed a SSL certificate in one of them (domain1) and everything is fine with that one. The second domain (domain2), does not require a SSL certificate but if I try to access https://domain2 is showing me the content of domain1 and giving me a certificate error (This page is not secure).
I understand the certificate error, but I don't want the contents of domain1 being displayed in https://domain2
Is it a configuration problem?
nginx always has a default server, the one that is used if the server_name does not match. If you only have one server block with listen 443, then that is the implicit default server for all https connections irrespective of server name.
You will need to set up an explicit catch-all server for https connections, or add listen 443 ssl to an existing server block to act as the catch-all server.
You can reuse the same certificate file and you will continue to get certificate errors if anyone attempts to use it, but at least your other domains will not be exposed.
For example:
ssl_certificate /path/to/crt;
ssl_certificate_key /path/to/key;
server {
listen 443 ssl;
server_name domain1;
...
}
server {
listen 443 ssl default_server;
return 403;
}
See this document and this document for more.

How to put ssl directives in server block instead of http block in nginx configuration?

I am about to use different ssl certificates for different virtual hosts, so I started by moving the existing ssl directives from the http block into one of the server blocks, before I start to add other ssl certificate directives into other server blocks. But as soon as I did this, the web server involved cannot be accessed anymore. Chrome reported connection closed and Nginx's error log read like this:
2016/01/08 20:13:32 [error] 16968#0: *364 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: x.x.x.x, server: 0.0.0.0:443
The ssl directives I moved include:
ssl_certificate
ssl_certificate_key
ssl_protocols
ssl_dhparam
ssl_prefer_server_ciphers
ssl_ciphers
What could possibly go wrong when moving these directives from http block to server block?
Make sure you haven't a global server configured to listen to 443.
Because you moved the ssl_certificate and ssl_certificate_key within a specific virtual host, that means the default configuration is missing the certificate and key. This is not allowed by Nginx. Each virtual host that is configured to listen on 443, regardless it's the default or not, must be configured to serve a certificate.
The default_server should only be processed when other virtual host listening on 443 is not selected, so why lacking ssl certificates on the default_server could impact access to other virtual hosts?
That's the point. Nginx reject the configuration because, if this scenario should happen, it would not be able to process the request because of the lacking of the ssl_certificate. Therefore, the configuration is invalid.

NGINX wrong configuration SSL certificate - The domain name does not match the certificate common name or SAN

I have an easy one, I think. I purchased a rapid SSL, I installed it on my website. It seems to be ok (I have a key file, the intermediate and final crs files), but there is a little mess: the SSL is correctly installed on https://xxxxx.com BUT NOT on https://www.xxxxx.com .
This is the error that I got from SSL checker:
Wrong certificate installed.
The domain name does not match the certificate common name or SAN.
I have a Nginx machine. This is a portion of config file:
server {
listen 80; ## listen for ipv4
listen 443 ssl;
set $myHost "xxxx.com";
set $site "xxxx";
server_name xxxx.com www.xxxx.com local.xxxx.com staging.xxxx.com s.xxxx.com;
#ssl_certificate /var/www/sites/ssl/oldfile.cert;
#ssl_certificate_key /var/www/sites/ssl/oldfile.key;
ssl_certificate /var/www/sites/ssl/122015/newfile.crt;
ssl_certificate_key /var/www/sites/ssl/122015/newfile.key;
root /var/www/sites/xxxx/current/web/;
access_log /var/www/sites/xxxx/current/app/logs/xxxx.com.access.log;
error_log /var/www/sites/xxxx/current/app/logs/xxxx.com.error.log;
....
When I got the key file, I set xxxx.com as domain name of course, because www was not allowed.
I need the SSL on www. Thanks for your help!!
M :)
You need a separate SSL certificate for each domain. You will then need to split your configuration for each domain into virtual hosts (nginx) and reference each individual SSL certificates for each domain you wish to use.

Nginx serving SSL certificate of another site

I'm serving two sites with Nginx. First site (say A) has a SSL certificate and second site (say B) doesn't. Site A works fine when opening on https and B on http. But when I access site B on https, nginx serves the SSL cert and contents of site A with domain of B, which shouldn't happen.
Nginx config for site A is as follows. For site B, it's just a reverse proxy to a Flask app.
server {
listen 80;
server_name siteA.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name siteA.com;
ssl_certificate /path/to/cert.cert
ssl_certificate_key /path/to/cert_key.key;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:RC4-SHA:AES256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
keepalive_timeout 70;
# and then the `location /` serving static files
}
I can't figure out what is wrong here.
Apparently I need a dedicated IP for site A.
Quoting from What exactly does "every SSL certificate requires a dedicated IP" mean?
When securing some connection with TLS, you usually use the certificate to authenticate the server (and sometimes the client). There's one server per IP/Port, so usually there's no problem for the server to choose what certificate to use. HTTPS is the exception -- several different domain names can refer to one IP and the client (usually a browser) connects to the same server for different domain names. The domain name is passed to the server in the request, which goes after TLS handshake. Here's where the problem arises - the web server doesn't know which certificate to present. To address this a new extension has been added to TLS, named SNI (Server Name Indication). However, not all clients support it. So in general it's a good idea to have a dedicated server per IP/Port per domain. In other words, each domain, to which the client can connect using HTTPS, should have its own IP address (or different port, but that's not usual).
Nginx was listening on port 443 and when request for site B went on https, the TLS handshake took place and the certificate of site A was presented before serving the content.
The ssl_certificate parameter should be closed with ; to get expected output.
Also make sure that you have followed the correct syntax in all the config file parameters by using following command and then restart or reload the service:
sudo nginx -t
NGINX supports SNI, so it's possible to serve different domains with different certificates from the same IP address. This can be done with multiple server blocks. NGINX has documented this in
http://nginx.org/en/docs/http/configuring_https_servers.html
For me HTTP2 and IPv6 are important, so I to listen to [::] and set ipv6only=off. Apparently this option should only be set for the first server block, otherwise NGINX will not start.
duplicate listen options for [::]:443
These server blocks
server {
listen [::]:443 ssl http2 ipv6only=off;
server_name siteA.com www.siteA.com;
ssl_certificate /path/to/certA.cert
ssl_certificate_key /path/to/certA_key.key;
}
server {
listen [::]:443 ssl http2;
server_name siteB.com www.siteB.com;
ssl_certificate /path/to/certB.cert
ssl_certificate_key /path/to/certB_key.key;
}
If you host multiple sites in you server and in one Nginx config if you have listen 443 ssl http2 default_server;
The default_server will give the same cert to all domains. removing it will fix the problem.
While following this tutorial I total missed this part:
Note: You may only have one listen directive that includes the default_server modifier for each IP version and port combination. If you have other server blocks enabled for these ports that have default_server set, you must remove the modifier from one of the blocks.