Nginx dropping SSL handshakes with multiple virtual hosts - redirect

I have an Nginx server set up on an Ubuntu VPS with multiple hosts (1 IP). Previously, 1 host had certificates set up and NO redirecting (http allowed) and 1 host had certificates and forced HTTPS via 301. Now that I am attempting to force all of my hosts on SSL and force HTTPS, I am seeing that Nginx is dropping handshakes when I have more than 1 vhost with 301 directives. In particular, the error I am seeing is:
[error] 12370#0: *30 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: (removed), server: 0.0.0.0:443
The issue definitely seems to be with my 301's, because if I exclude them I do not have an issue. What's the best way I can force HTTPS and non-www in my server blocks?
All of my vhosts are in /etc/nginx/conf.d, along with ssl.conf (listed below). I can provide nginx.conf if requested, but I didn't see anything that would seem useful in there.
example1.conf
server {
server_name www.example1.com example1.com;
return 301 https://example1.com$request_uri;
}
server {
listen 443;
server_name www.example1.com
return 301 https://example1.com$request_uri;
}
server {
listen 443 ssl;
server_name example1.com;
ssl_certificate /etc/letsencrypt/live/example1.com/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/example1.com/privkey.pem;
root /var/www/example1.com;
location / {
try_files $uri $uri/ $uri.html =404;
}
access_log /var/log/nginx/example1.com.access.log;
error_log /var/log/nginx/example1.com.error.log;
}
example2.conf
same as example1.conf (except with example2.com instead of example1.com)
ssl.conf
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Perfect Forward Security
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS +RC4 RC4";
# HSTS
add_header Strict-Transport-Security max-age=31536000;
Pointing out other obvious errors is also appreciated.

Solved (at least for now) by removing
server {
listen 443;
server_name www.example1.com
return 301 https://example1.com$request_uri;
}
It seems that since there's no cert specified, this block would get hit for all HTTPS requests and then the connection would get dropped.

Related

Nginx serving from a different location with SSL

I have a webserver running Nginx. I have successfully managed to get SSL working with a Let's Encrypt Certificate, but whenever I connect to HTTPS, the webserver serves me the default index page for Nginx (this). I have been unable to find where this is coming from.
This is the server block I have in the config for the SSL:
##
# SSL Settings
##
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
server {
listen 139.59.163.228:443 ssl;
server_name sulphate.me www.sulphate.me;
keepalive_timeout 75 75;
ssl_certificate /etc/ssl/certs/sites/sulphate.me.crt;
ssl_certificate_key /etc/ssl/private/sites/sulphate.me.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
}
I want to be able to redirect it to where HTTP is served from (/var/www/html/), and also find out where this is coming from, since I haven't touched any location blocks.
Thanks in advance!

nginx: how much of the https server block is required for a redirect

My site will run exclusively at https://www.example.net
I have a server block for port 80 which returns a 301 to https://www.example.net, which works as expected.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name www.example.net example.net;
return 301 https://www.example.net$request_uri;
}
In terms of doing the same on port 443, I read somewhere that certificate negotiation happens before all else, and so this 443 redirect block needs to have all of the certificate details. My question is, how much of that stuff needs to be repeated in this block? Currently I have the following:
server {
listen 443 ssl;
listen [::]:443 ssl;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/ssl/certs/x.example.net.pem;
ssl_certificate_key /etc/ssl/private/example.net.key;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/certs/x.example.net.pem;
resolver 8.8.8.8 8.8.4.4;
server_name example.net;
return 301 https://www.example.net$request_uri;
}
Should I be setting Strict-Transport-Security headers? OSCP stapling? ssl_ciphers? Just for a redirect?
Many thanks!
Edited to add: that my certificate is valid on both www and non-www, and so this is not an effort to avoid an ugly certificate mismatch warning.
The following should be in an http block in nginx.conf so it applies to all SSL server configs and avoids this bug:
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
The rest should remain.

Ispconfig nginx redirecting to https

I've deployed a CentOS server with ISPConfig and Nginx.
Also I was able to configure Nginx, manually (by editing /etc/nginx/sites-available/mysite.com.vhost), to redirect http requests to https:
server {
listen 80;
server_name mysite.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
..
}
As I edited the file manually, every time I change a setting with ISPConfig, my vhost file gets overwritten and I lose my redirection's trick.
Do you know a way to config the redirection above using ISPConfig panel instead editing the nginx file manually ?
Thanks in avance.
I've configured the redirection as the accepted answer suggested.
Also I've included an external config so I put all our manual configurations.
In our version of ISPConfig, I did this:
if ($scheme != "https") {
rewrite ^ https://$http_host$request_uri? permanent;
}
include /etc/nginx/sites-available/my-own-config.conf;
That way, ISPConfig won't break our configs.
On the more recent versions of ISPConfig, you can simply select the website to use SSL (and that means HTTPS, and optionally, SPDY or HTTP/2), with an additional checkbox to redirect all HTTP requests permanently to HTTPS, and ISPConfig will automatically generate the vhosts files correctly.
For the sake of completude, this is what ISPConfig adds:
server {
listen *:80;
listen *:443 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /var/www/clients/clientX/webY/ssl/your.web.site.crt;
ssl_certificate_key /var/www/clients/clientX/webY/ssl/your.web.site.key;
server_name your.web.site www.your.web.site;
root /var/www/your.web.site/web/;
if ($http_host = "www.your.web.site") {
rewrite ^ $scheme://your.web.site$request_uri? permanent;
}
if ($scheme != "https") {
rewrite ^ https://$http_host$request_uri? permanent;
}
index index.html index.htm index.php index.cgi index.pl index.xhtml;

nginx HTTPS Redirect

I'm trying to get my site to use HTTPS only. I've looked all over stackoverflow and tried many of the suggested settings for the nginx settings file for the site, but I still can't get all address combinations to work. What do I need to change in the file to get it to work?
These two address combinations don't redirect -
http://www.example.com > No Redirect (Errors Out)
https://example.com > No Redirect (Errors Out)
Here's what the settings file looks like -
server {
listen [::]:80;
server_name www.example.com;
return 301 https://$host$request_uri;
}
server {
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen [::]:443 default_server ipv6only=off;
server_name example.com www.example.com;
# rest of config file...
}
I accomplish this on my server in the following way:
server {
listen 80;
server_name example.com;
rewrite ^/(.*) https://example.com/$1 permanent;
}
At a glance your configuration looks OK, but the return directive documentation does note some limitations for older versions of nginx that would be encountered with your configuration.
Finally, in the secure server configuration, you could include an HTTP Strict Transport Security directive to cause clients to only connect to your domain over TLS in the future.
add_header Strict-Transport-Security max-age=31536000;
Below config will redirect example.com to https://example.com
server {
listen 80;
server_name *.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name *.example.com;
[....]
}
However, if you want to redirect all domains to https:
change server_name to _ (server_name _;)
replace $server_name variable to $host in redirect rule (return 301 https://$host$request_uri;)
You can use like this
server {
listen 192.168.1.1:443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 192.168.1.2:443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
http://nginx.org/en/docs/http/configuring_https_servers.html

Nginx Redirect HTTP to HTTPS and non-www to ww

I'm setting up an Nginx server with an SSL.
The domain with the SSL is www.mydomain.example
I want to redirect all requests from:
http://mydomain.example, http://www.mydomain.example, & https://mydomain.example to
https://www.mydomain.example
I have the following server blocks setup currently:
server{
listen 443 ssl;
root /www/mydomain.example/;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen 80;
server_name www.mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen ssl 443;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
This currently does not work, but I don't understand why not. I can get a combination of either HTTP -> HTTPS working or no-www to -> www working, but mixing them as above does not work.
The SSL redirect won't work if your SSL certificate doesn't support the non-www domain.
The config is correct but can be reduced to just 1 redirect server
Also don't forget to reload Nginx sudo service nginx reload
server {
listen 80;
listen 443 ssl;
server_name example.com;
# add ssl settings
return 301 https://www.example.com$request_uri;
}
I am late, But you can do like this
server{
listen 443 ssl;
server_name www.mydomain.example;
root /www/mydomain.example/;
ssl on;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name www.mydomain.example mydomain.example;
return 301 https://$server_name$request_uri;
}
server{
listen 443;
server_name mydomain.example;
return 301 https://www.$server_name$request_uri;
}
Or you can replace return 301 https://www.$server_name$request_uri; with rewrite ^ http://www.$server_name$request_uri? permanent;, both will work.
You also need to set this in google webmaster for better SEO.
this works for me for HTTP to HTTPS redirection,
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com;
#For HTTP to HTTPS:
proxy_set_header X-Forwarded-Proto $scheme;
if ( $http_x_forwarded_proto != 'https' )
{
return 301 https://$host$request_uri;
}
location / {
try_files $uri $uri/ /index.php;
add_header 'Access-Control-Allow-Origin' '*';
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Use a rewrite to send all HTTP traffic to HTTPS:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
This configuration listens on port 80 as the default server for both IPv4 and IPv6 and
for any hostname. The return statement returns a 301 permanent redirect to the
HTTPS server at the same host and request URI.
#If you like to redirect all "http" to "https" then add the following:
server {
listen 80;
server_name yourdomain.example;
server_name www.yourdomain.example;
if ($scheme = "http")
{
rewrite ^(.*)$ https://yourdomain.example$1 permanent;
}
}
Please add two given things on your file.
Code to paste on top:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Code to paste on bottom:
server {
listen 443 ssl http2;
server_name www.example.com;
# . . . other code
return 301 https://example.com$request_uri;
}
Source
I was trying to fix the problem by redirecting the request URI to HTTPS if it was requested with the HTTP scheme. But this solution does not work in some conditions.
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
When we type a domain name in the search bar of a browser, it makes a request with the HTTP scheme by default. This behavior of the browser is not handled by nginx, but it can be done manually. We have to handle 497 status code by adding error_page 497 https://$server_name$request_uri;.
error_page 497 https://$server_name$request_uri;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
What does the 497 indicate, and when occur?
The 497 HTTP Request Sent to HTTPS Port is used when a client has made an HTTP request to a port that is listening for HTTPS requests specifically.
I couldn't figure out why HTTP http://example.com wouldn't redirect to HTTPS https://example.com. i had configured it the following way like others have and according to https://nginx.org/en/docs/http/configuring_https_servers.html, even after restarting the server with nginx -s reload && sudo systemctl restart nginx
/etc/nginx/sites-available/example.com
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}
server {
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 1m;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.example.com example.com;
root /var/www/build;
index index.html;
location / {
try_files $uri /index.html =404;
}
}
But even though i'm using the latest browsers, the redirection from HTTP to HTTPS only works with the latest in incognito window:
Firefox: 110.0 (64-bit) (both on Desktop and Mobile)
But not with the latest in incognito window even after clear cache and hard reload:
Brave: Version 1.48.164 Chromium: 110.0.5481.100 (Official Build) (x86_64)
Chrome: Version 110.0.5481.100 (Official Build) (x86_64)
With Brave and Chrome it just loads the default HTTP page "Welcome to nginx!" from /var/www/html/
index.nginx-debian.html