NGINX redirect HTTPS to HTTPS - ssl

How can I redirect https from one domain to https of another?
Case description:
I own three domains that is directed to the same ip/website in the NS server:
example1.com
example2.com
example3.com
I paid only for one SSL licence that initially was issued for the first domain, so when I bought the second domain, I redirected all traffic to https://example1.com
Lately, I wanted to redirect all calls to a new domain: https://example3.com. I reissued the old SSL licence for the new domain and installed it successfully. The last part is redirecting all traffic to the new domain.
Now, all traffic from http is redirect well, but https (https://example1.com and https://example2.com) is not directed at all, and results in working "Not secure" page.
When I try to listen to 443 SSL and redirect if from 1&2 name servers to the third one and run service nginx restart, I get:
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
When I run systemctl status nginx.service, I get:
nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sun 2020-05-24 17:53:24 UTC; 4min 5s ago
Process: 14068 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 13952 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 14073 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
Main PID: 13957 (code=exited, status=0/SUCCESS)
My guess I'm doing something wrong and redirecting 443 SSL twice is not allowed.
Code
This is my conf that is working without redirecting https example1.com and example2.com:
On /etc/nginx/nginx.conf I have include /etc/nginx/sites-enabled/*;.
On /etc/nginx/sites-enabled/example3.com.conf I wrote this:
server {
listen 80;
server_name example3.com wwww.example3.com example1.com www.example1.com example2.com www.example2.com;
rewrite ^/(.*) https://example3.com/$1 permanent;
}
server {
listen 443 ssl;
server_name example3.com;
ssl_certificate /etc/ssl/certs/ssl-bundle.crt;
ssl_certificate_key /etc/ssl/websitessl/example3.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
}
This is maybe duplication of this:
HTTPS to HTTPS redirect Nginx
But I failed to make it work.

Thank's to #RichardSmith, I learned that in order to redirect HTTPS to HTTPS without "Page not secure" warning, you should put the ssl_ statements out of the server blocks so all the domains will be included.
ssl_certificate /etc/ssl/certs/ssl-bundle.crt;
ssl_certificate_key /etc/ssl/websitessl/example3.com.key;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
server {
listen 80 default_server;
listen 443 ssl default_server;
return 301 https://example3.com$request_uri;
}
server {
listen 443 ssl;
server_name example3.com;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
}

Related

Nginx Reverse proxy not working with Gunicorn over LetsEncrypt SSL connection

I've EC2 Ubuntu 18.04 Server with Python Flask framework running on Gunicorn application server with Nginx reverse proxy listening on port 80 & 443. I've added LetsEncrypt for the domain using certbot.
The website works fine without ssl. With LetsEncrypt ssl configuration on Nginx the server fails to load the page.
My previous supervisor and Nginx configuration without ssl support is as follows and Nginx works with gunicorn with no issues.
server {
listen 80;
server_name example.com www.example.com;
location /static {
alias /home/ubuntu/myapp-backend/myapp/static;
}
location / {
proxy_pass http://localhost:8000;
include /etc/nginx/proxy_params;
proxy_redirect off;
}
}
[program:myapp]
directory=/home/ubuntu/myapp-backend
command=/home/ubuntu/myapp-backend/venv/bin/gunicorn -w 5 run:app
user=ubuntu
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/var/log/myapp/myapp.err.log
stdout_logfile=/var/log/myapp/myapp.out.log
When I change the Nginx configuration to include LetsEncrypt support while listening on port 80 & 443, the website doesn't show up.. It shows indefinite 301 redirects requests.
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location /static {
alias /home/ubuntu/myapp-backend/myapp/static;
}
location / {
proxy_pass http://localhost:8000;
include /etc/nginx/proxy_params;
proxy_redirect off;
}
}
When I load the site example.com, it redirects to https:\\www.example.com. However the website homepage doesn't load or show any response from server/Nginx. When I login to the server and run curl -v localhost:8000, the the gunicorn works fine.
curl -v localhost:8000
* Rebuilt URL to: localhost:8000/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 500 INTERNAL SERVER ERROR
< Server: gunicorn/19.9.0
< Date: Sat, 28 Sep 2019 14:14:47 GMT
< Connection: close
< Content-Type: text/html; charset=utf-8
< Content-Length: 27911
<
<!doctype html>
...
There was earlier Stackoverflow question on gunicorn over ssl with ssl parameters which can be added to supervisor config.
I believe the error must be with on Nginx configuration on port 443 or Gunicorn supervisor config info. If you could have a look, I would appreciate it.
You have too many server blocks
The second block in your configration with SSL, catches connections to 443 and redirects them to the https:// URL. Thus causing the infinite loop:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
return 301 https://www.example.com$request_uri;
}
This 301 should only be returned when the user hits the server on port 80. That's what the first server block in this config file actually does.
Remove this whole block and it should probably work. You already have the third server block configured to (correctly) catch traffic to 443 and proxy it to gunicorn.
There was earlier Stackoverflow question on gunicorn over ssl with ssl parameters which can be added to supervisor config. I believe the error must be with on Nginx configuration.
You are terminating SSL at nginx, then proxying to gunicorn in plain HTTP (which is the correct way to operate with nginx involved). The question you linked there is about adding native SSL support to gunicorn, so that gunicorn terminates SSL. This would only be required if your internet based users connect directly to the gunicorn server.

Nginx - Only enable SSL if SSL Certificates Exist

I have an issue wherein I am building an nginx reverse proxy for directing to multiple microservices at different url paths.
The system is entirely docker based and as a result the same environment is used for development and production. This has caused an issue for me when installing SSL as the SSL certs will only be available in production so when I configure NGINX with SSL the development environment no longer works as the ssl certs are not present.
Here is the relevant part of my conf file -
server {
listen 80;
listen 443 default_server ssl;
server_name atvcap.server.com;
ssl_certificate /etc/nginx/certs/atvcap_cabundle.crt;
ssl_certificate_key /etc/nginx/certs/atvcap.key;
...
}
But this throws the following when running my application in development mode -
nginx: [emerg] BIO_new_file("/etc/nginx/certs/atvcap_cabundle.crt") failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/nginx/certs/atvcap_cabundle.crt','r') error:2006D080:BIO routines:BIO_new_file:no such file)
Is it possible to only turn on SSL if the "/etc/nginx/certs/atvcap_cabundle.crt" is available?
I had tried something like the following -
if (-f /etc/nginx/certs/atvcap_cabundle.crt) {
ssl_certificate /etc/nginx/certs/atvcap_cabundle.crt;
ssl_certificate_key /etc/nginx/certs/atvcap.key;
}
But that threw the following error -
nginx: [emerg] "ssl_certificate" directive is not allowed here in
/etc/nginx/conf.d/default.conf:7
Any one have any ideas on how to achieve something like this?
Thanks
You can create an additional file ssl.conf and put here ssl configs:
ssl_certificate /etc/nginx/certs/atvcap_cabundle.crt;
ssl_certificate_key /etc/nginx/certs/atvcap.key;
Then include from the main config:
server_name atvcap.server.com;
include /somepath/ssl.conf*;
Make sure to include * symbol - this will not break when the file does not exist at development mode.
The answer of #super_p is correct. But to answer to #AbdolHosein comment I add my answer here if it's not clear.
You need to include your ssl_certificate directive in the included file.
# sample nginx config
http {
server {
listen 80 deferred;
server_name _;
include /ssl/ssl.conf*;
client_body_timeout 5s;
client_header_timeout 5s;
root /code;
}
}
Then in your /ssl/ssl.conf you can do whatever you want, such as enabling HTTPS:
# this is the /ssl/ssl.conf file
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /ssl/cert.cer;
ssl_certificate_key /ssl/key.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
The trick is that we don't look if the certificate exists but we check if the /ssl/ssl.conf exists. This is thanks to the * in the include /ssl/ssl.conf*; directory as stated by #super_p

NGINX + HTTPS causes 504 Gateway Timeout error for external requests

I'm running nginx server on my Raspberry Pi and it seems to be working just fine using HTTP protocol.
Recently, I decided to add HTTPS support to my server and got certificate from Let's Encrypt.
And it still works like a charm, if you are sending requests from local network. But every external request via HTTPS ends with 504 Gateway Timeout error.
Here is my config:
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name domain.name;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 180m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DHE+AES128:!ADH:!AECDH:!MD5;
ssl_certificate /etc/letsencrypt/live/domain.name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.name/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/domain.name/chain.pem;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location ~ /.well-known {
allow all;
root /usr/share/nginx/html;
}
}
Found out that my ISP has a firewall service active by default. It was blocking all connections to 443 port. Disabling it resolved my issue.

The plain HTTP request was sent to HTTPS port(NGINX)

First of all my problem is different.
I have used listen 443 default ssl; also listen 443 ssl; and commenting out # but seems nothing is working. Port 80 works fine but on port 443 I get this error.
Currently this is the default file for nginx.
server {
listen 80;
listen 443 ssl;
#listen 443 default ssl;
server_name .******.org;
keepalive_timeout 70;
#ssl on;
ssl_certificate /etc/ssl/private/lol/www.*******.crt;
ssl_certificate_key /etc/ssl/private/lol/www.********.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
On ssl_protocols I also tried to only use SSLv3 TLSv1 but its same. My nginx version is 1.2.1.
I have gone through many online sites even here but I think my problem is not being solved with any of those methods mentioned by different geeks.
So finally I am here.
Any suggestions?
P.S: I am using cloudflare, but there I have turned Universal SSL Off as I want to use other ssl.
You should write two server blocks one for http and one for https like:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/public/;
index index.html;
#other settings
}
server {
listen 443;
server_name localhost;
root /var/www/public/test/;
index index.html;
ssl on;
ssl_certificate /etc/nginx/certs/wss.pem;
ssl_certificate_key /etc/nginx/certs/wss.pem;
#other settings
}
I have tried it with the default nginx settings and both ports work fine.
If you are experiencing this issue with Google Compute Engine / Google HTTP loadbalancer... Ensure you have your instance group setup with separate named ports for http: 80 and https: 443.
Or it will randomly select a port.
This came about in my case due to originally setting up the HTTP loadbalancer when it was still in beta. Then when I added another loadbalancer it refreshed the settings and started randomly failing.
It was failing 50% of the time, because I only had Nginx setup with a vhost for port 80, and it was trying to push HTTP requests to port 80 on the web boxes.
The error you get is most likely, because you send a unencrypted HTTP-request to the SSL-port.
Something like
wget http://example.com:443/
This is a client problem (the server just tells you that it refuses to answer non-encrypted messages on to-be-encrypted channels)
It is client problem.
I was having the same issue. Turns out the https prefix was being dropped in the URL.
In the browser inspect the network traffic to verify that the browser is sending an http request, not https. Issue found!
Manually type in the wanted URL with https to retrieve the page successfully.
Now you can go about applying a focused fix to your client.

SSL configuration on nginx 1.6

I'm tryng to configure nginx 1.6 on a VM to accept https connection.
I have created a self signed certificate following this tutorial. and then I have added a configuration file like this
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
The problem is that when I access the https url from the browser I have no results but this error
Error code: ERR_CONNECTION_RESET
I think that port 443 is open
netstat -tulpn | grep 443
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 8603/nginx.conf
Moreover, I can wget the index.html:
wget -–no-check-certificate https://<server_url>
Now, I suppose that the problem is the untrusted certificate because wget gives error if -–no-check-certificate is omitted but in this case I expect browser (Chrome or Firefox) to give some kind of warning and maybe let me see the untrusted certificate instead of reset connection.
What am I doing wrong? Thanks in advance
EDIT:
Firefox gives "200 Connection Established" but no content or warning is shown. It only says that connection has been canceled
The problem might be with the certificate. You can see tutorial to create *.pem certificate instead of *.crt and add as:
ssl_certificate /etc/nginx/ssl/nginx.pem;
Issue was on my side renamed my.host.com to localhost and it worked.
server_name localhost;