Unable to access site using https - ssl

I'm currently serving the server using nginx with the following configuration.
server {
server_name www.skipven.xyz skipven.xyz;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/ari-bot/aribot;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/ari-bot/ari-bot.sock;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/skipven.xyz/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/skipven.xyz/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.skipven.xyz) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = skipven.xyz) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.skipven.xyz skipven.xyz;
return 404; # managed by Certbot
}
When I try to access http://skipven.xyz, It's successfully redirected to https://skipven.xyz . But https://skipven.xyz doesn't return anything. I also can't find any access log of the https request but http request is logged like charm.
Other things to note:
Running sudo nginx -t return the following response:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Running sudo ufw status return the following response:
Status: active
To Action From
-- ------ ----
Nginx Full ALLOW Anywhere
22/tcp ALLOW Anywhere
Nginx Full (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)

First make sure that your web application is running, try to curl to unix socket. If it still does not work, which cloud service do you use right now? If you use aws or gce, you still need to configure their firewall.

Related

Why do I have to change from Flexible to Full to solve my "too many redirects" problem with cloudflare?

I just setup a new website.
After setting up everything (SSL with LetsEncrypt), there is a too many redirects problem.
It took me hours to figure out that I can just solve it by switching from Flexible to Full in my cloudflare seetings. But why? Can somebody explain details to me?
Nginx conf:
server {
server_name mysite.com;
root /root/mysite;
index index.html;
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mysite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name mysite.com;
listen 80;
return 404; # managed by Certbot
}
When the set up is configured in Flexible mode, it means that the connection follows this configuration:
Between the end user and Cloudflare, HTTPS is used
Between Cloudflare and your origin erver, HTTP is used
This can be useful if the origin does not support HTTPS, but you still want end users to connect securely to Cloudflare. The recommendation is to always have end to end TLS enabled with fully valid certificates.
If your origin is configured to redirect HTTP requests to HTTPS, then we enter into a loop, since the redirected HTTPS request goes back to Cloudflare, then Cloudflare makes an HTTP request to the origin ... and back to where it started!
In your case you seem to have a fully valid Let's Encrypt certificate on your origin server, so you should use Full (Strict) . More information is also available here

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.

How to listen to different port on Nginx and proxy the request?

I am a newbie to Nginx config and all, I have a process which is an express app, running on port 3000 using pm2 and I have allowed port 3000 using ufw as well, and have made a server instance on Nginx to proxy it,
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name .mysite.co;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/django/mysite;
}
proxy_cache mysite;
location / {
include proxy_params;
proxy_pass http://unix:/home/django/mysite/mysite.sock;
}
gzip_comp_level 3;
gzip_types text/plain text/css image/*;
ssl_certificate /etc/letsencrypt/live/mysite.co/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.co/privkey.pem; # managed by Certbot
}
server {
if ($host = www.mysite.co) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mysite.co) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name .mysite.co;
return 404; # managed by Certbot
}
server{
listen 3000;
listen 443 ssl http2;
server_name .mysite.co:3000;
location / {
proxy_pass https://localhost:3000;
}
}
I ran netstat -napl | grep 3000 and I could confirm that the process is running and pm2 status also says its running and no errors in log as well.
How could I make this work? Thanks for the help in advance.
You won't be able to use nginx to listen on port 3000 as well as your node process as only one service can really listen on the port at once. So you'll need to ensure nginx is listening for connections on a different port. I imagine what you're trying to do is to listen on port 80 / 443 and then send the request onto your express service which is listening on port 3000?
In this case your bottom server block is nearly correct. To get this working without TLS/SSL (just on port 80) you'll want to use something like this:
server {
listen 80;
server_name node.mysite.co
location / {
proxy_pass http://localhost:3000;
}
}
The following is a very basic example and you'll probably want to toggle some other settings. This will make "http://node.mysite.co" go proxy through to whatever service (in this case an Express server) is listening on port 3000 locally.
You do not need to make a firewall (ufw) exception for port 3000 in this case as it's a local proxy pass. You should close the port on the firewall so people can't access it directly, this way the must go through nginx.
If you want to get SSL/TLS working, you'll want another block that'll look something like the following. Again, this is very basic and doesn't have a lot of settings you probably want to research and set (such as cipher choices).
server {
listen 443 ssl;
server_name node.mysite.co
ssl_certificate certs/mysite/server.crt;
ssl_certificate_key certs/mysite/server.key;
location / {
proxy_pass http://localhost:3000;
}
}
You'll need to replace the cert and key path to point to your SSL/TLS ceritifcate and key respectively. This will enable you to access https://node.mysite.co and it'll be proxied onto the service on port 3000 as well.
Once you've done that you might then choose to go back and change the http (port 80) server to a redirect to https to force https only connections.
Also note that I've ensured the server_name is different to your existing django server_name with a subdomain (node.mysite.co). You might wish to change this value but you can't have two server blocks listening on the same port and server_name, otherwise nginx would have no idea what to do with the request. I'm sure you're doing this anyway but I wanted to make sure it was explicit and would work with your existing setup.
If you wish the site to be served only for mysite.co:3000
If for some reason you want the user to go to port 3000 on the domain mysite.co, then you will need to set the "listen" to 3000 and keep the server name as "mysite.co". This will allow someone to go to mysite.co:3000 in their browser and hit your node service. I imagine this isn't really what you want for a public facing website though, it also won't line up very nicely with your port 443 version.
Note: I don't claim to be an nginx expert, but I've used it for all my node projects for the past few years and I find this setup to be pretty clear. There might be some nicer syntax you can use.

Unable to connect to secure websocket in DigitalOcean

I'm having trouble setting up my WebSocket server in Digital Ocean.
I'm changing my actual domain name for domain.com for the question's sake.
I basically have a NodeJs WebSocket server that I'm trying to connect to a react app I'm hosting at Heroku. I'm getting the following error when attempting to connect:
WebSocket connection to 'wss://domain.com/' failed: Error during WebSocket handshake: Unexpected response code: 200
Here's my server entry code:
const PORT = process.env.PORT || 8080
const privateKey = fs.readFileSync('/etc/letsencrypt/live/domain.com/privkey.pem', 'utf-8')
const certificate = fs.readFileSync('/etc/letsencrypt/live/domain.com/cert.pem', 'utf-8')
const credentials = { key: privateKey, cert: certificate }
const server = express()
const httpsServer = https.createServer(credentials, server)
httpsServer.listen(PORT)
this.wss = new WebSocket.Server({ server: httpsServer })
I used cert-bot to secure my connection, as for Heroku is obligatory. So here's my nginx default config file, located at /etc/nginx/sites-available/default
server {
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
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.com www.domain.com;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
I also changed a bit my UFW config. Here's the output to sudo ufw status
Nginx Full ALLOW Anywhere
22/tcp ALLOW Anywhere
Nginx Full (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)
Just to be clear, I'm NOT using domain.com for real. I just changed it in the current question for privacy concerns, :D
Hope anyone can point me in the right direction. Not really sure where I'm going wrong.

Configure proxy_pass for intermittent service

I'm using Nginx within a Doccker container to host my application
I'm trying to configure Nginx to proxy traffic to the /.well-known/ directory to another container that handles the letsencrypt process to setup & renew SSL certificates, but I don't need that container to be running all the time, only when attempting to renew the certificates.
My idea was to use proxy_pass for the directory specific traffic, through to the leysencrypt container, but as it's not always running, the Nginx process exits complaining that the upstream is not available.
Is there a way to configure Nginx not to check the status of the upstream for proxy_pass setting?
Here's the current config, if it's useful…
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name domain.com;
root /var/www/html/web;
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/ {
proxy_pass http://letsencrypt/.well-known/;
}
}
I guess I could use an in app forwarding of files, but this feels clunky. I'd rather configure it within Nginx.
location ^~ /.well-known/ {
resolver 127.0.0.1;
set $upstream letsencrypt;
proxy_pass http://$upstream/.well-known/; # use variables to make nginx startable
}