I am trying to use SSL on my application running socket.io with express and nginx but I can't make it work. I have done my research but none of what I found worked.
I keep having the error : ERR_CONNECTION_CLOSED with not http status code on client side.
GET https://subdomain.mywebsite.com:1339/socket.io/?EIO=3&transport=polling&t=LIgxHmz net::ERR_CONNECTION_CLOSED
Here is my nginx configuration :
server {
listen 443;
server_name subdomain.mywebsite.com;
root /usr/share/nginx/html;
index index.html index.htm;
ssl on;
# Use certificate and key provided by Let's Encrypt:
ssl_certificate /etc/letsencrypt/live/subdomain.mywebsite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/subdomain.mywebsite.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:1339/;
proxy_redirect off;
# Socket.IO Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Here is the server side :
var express = require('express'),
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
server.listen(1339);
...
Here is the client side :
subdomain.mywebsite.com
var socket = io.connect("https://subdomain.mywebsite.com:1339");
The page loads nicely, no error on server side but no connection to socket.io.
Everything worked flawlessly before I tried to switch to SSL.
What am I doing wrong ?
Try this configuration. Please make sure to have a correct SSL certificate and key. If you test on local you can easily use mkcert tool to generate SSL certificate to local testing.
server {
listen 80;
server_name <your server_name>;
return 301 https://<your server_name>$request_uri;
}
server {
listen 443 ssl;
ssl_certificate <your certificate path>; # better if you put them at /etc/nginx/ssl/
ssl_certificate_key <your certificate_key path >;
server_name <your server_name>;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Client-Verify SUCCESS;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:3000;
proxy_redirect off;
proxy_buffering off;
}
}
Related
I have a React web App which uses axios to communicate with the backend API. Backend receives all requests from suffix /api address. And after that, those are redirected by nginx to localhost:1337 where my backend listens to requests. Everything works okay but the socket connection. The console says it can not find domain/socket.io/... but it should be domain/api/socket.io/.... My connection in the client code:
const ENDPOINT = "https://sinavhukuk.com/api";
const socket = io(ENDPOINT);
Would mention that Strapi is used as a backend service (NodeJS).
Here is /etc/nginx/sites-available/default file configuration.
server {
# Listen HTTP
listen 80;
server_name sinavhukuk.com www.sinavhukuk.com;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}
server {
# Listen HTTPS
listen 443 ssl;
server_name sinavhukuk.com www.sinavhukuk.com;
# SSL config
ssl_certificate /etc/letsencrypt/live/sinavhukuk.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sinavhukuk.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
# Static Root
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
# Strapi API and Admin
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
}
It is responsible for redirecting /api/...s to localhost:1337. But on socket it is not completely redirected. The error I get is:
https://sinavhukuk.com/socket.io/..... is not found
As I said, if the nginx worked here as always, it should be
https://sinavhukuk.com/api/socket.io/.....
What am I doing wrong?
EDIT: Added redirection from /socket.io/ to /api/socket.io/ manually, but still redirection happens to /socket.io/ instead of /api/socket.io/
# Socket.io
location /socket.io/ {
proxy_pass http://localhost:3000/api/socket.io/;
}
Trying to have both apps one react create the other Nodejs run behind Nginx proxy. The followings are my configs:
server {
listen 443 ssl;
server_name site.com;
ssl_certificate /etc/site.com.pem;
ssl_certificate_key /etc/site.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location /nodejs {
root /usr/share/nodejs;
proxy_pass http://my.url.com:3009;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
}
location / {
root /usr/share/react-create;
proxy_pass http://my.url.com:3011;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
}
React app is being served at root but nodejs app files are not being served correctly:
// Please try with this configuration.
upstream nodejs {
server http://my.url.com:3009;
}
upstream reactjs {
server http://my.url.com:3007;
}
server {
listen 443 ssl;
server_name site.com;
ssl_certificate /etc/site.com.pem;
ssl_certificate_key /etc/site.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location /node {
root /usr/share/nodejs;
proxy_pass http://nodejs/api;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
}
location /react {
root /usr/share/react-create;
proxy_pass http://reactjs;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
}
First let Nginx handle serving your react static files form their build file, and reorder the location matching for Nginx and let the nodejs or the api server for later catch for Nginx:
server {
listen 443 ssl;
server_name site.com;
ssl_certificate /etc/site.com.pem;
ssl_certificate_key /etc/site.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
root /path/to/project-base/build-live/;
index index.html;
location / {
try_files $uri /index.html =404;
}
location /api {
proxy_pass http://myapistream;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
}
}
I have my server setup on AWS EC2 instance. My APIs on the IP work perfectly, i.e. on
http://myIpAddress:3000 // Working fine
But when I configure my nginx server and pass proxy then my domain is not working as I expected:
https://myDomainAddress // Working too slow
Here is my nginx file:
server {
listen 80;
server_name myDomainAddress;
return 301 https://myDomainAddress$request_uri;
}
upstream main {
server myIpAddress:3000; #ip to nodejs server
}
server {
listen 443;
server_name myDomainAddress;
client_max_body_size 8M;
ssl on;
ssl_certificate myCert.crt;
ssl_certificate_key myKey.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://main;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
I have node.js app which is served by NGINX. I can't connect socket.io and keep getting 404 for POST requests to establishing a connection.
It's working locally, so it must be an NGINX problem.
# HTTP - redirect all requests to HTTPS:
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
# HTTPS - proxy requests on to local Node.js app:
server {
listen 443 ssl http2;
server_name example.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://127.0.0.1:8080;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
Thanks for any help.
Since Websockets are using the Upgrade header introduced in HTTP 1.1, you'll need to specifically use this protocol in your route and set the Connection header to upgrade.
You'll also need to specify a proxy_pass directive with a unique name.
Your config would be something like that:
upstream sockets {
server localhost:8080;
}
# HTTP - redirect all requests to HTTPS:
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
# HTTPS - proxy requests on to local Node.js app:
server {
listen 443 ssl http2;
server_name example.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
proxy_pass http://sockets;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_ssl_session_reuse off;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
Take a look a the NGINX docs.
https://www.nginx.com/blog/websocket-nginx/
enter chttp {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server 192.168.100.10:8010;
}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
I know there are many such questions on stack exchange. But nothing could help to the scenario that I have.
Here is my situation.
I have a webserver running on apache2 listening to the port numbers 7080 and 7081. I have used reverse-proxy method on my server and installed nginx which is listening to the port 80. So now nginx is the front end. I have my wordpress website running on http://www.example.com.
Now I am trying to install node.js app on my server which I could not. It makes sense because port 80 is being used by nginx.
I referred to the following posts on SO
Node.js + Nginx - What now?
Apache and Node.js on the Same Server
I tried the following
upstream example.com/my-app {
server 1**.*.**.**:3010;
}
# the nginx server instance
server {
listen 1**.*.**.**:80;
server_name example.com/my-app;
server_name www.example.com/my-app;
server_name ipv4.example.com/my-app;
access_log off;
# pass the request to the node.js server with the correct headers and much more can be added, see nginx config options
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Accel-Internal /internal-nginx-static-location;
proxy_pass http://example.com/my-app;
proxy_redirect off;
}
location /internal-nginx-static-location/ {
alias /var/www/vhosts/example.com/httpdocs/node;
access_log /var/www/vhosts/example.com/httpdocs/node/statistics/logs/proxy_access_ssl_log;
add_header X-Powered-By PleskLin;
internal;
}
}
I wrote the above conf in a file and included it in /etc/nginx/conf.d/xzzeaweae_nginx.conf.
It is not working. but the app is running properly on 1++.+.++.++:3010 though.
My directory structure.
/var/www/vhosts/example.com/httpdocs/
my wordpress website root directory : /var/www/vhosts/example.com/httpdocs/
my nodejs app directory: /var/www/vhosts/example.com/httpdocs/my-nodejsapp-folder/
UPDATE
Here is my reverse proxy config for my apache application
server {
listen +++.+.++.++:80 ;
listen ++.+.+++.++:80 ;
location / {
proxy_pass http://127.0.0.1:7080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Since I have more than one website running on my server,
I have reverse proxy config for every website.
Here it is for one of my website
server {
listen +++.+.++.++:443 ssl;
server_name example.com;
server_name www.example.com;
server_name ipv4.example.com;
ssl_certificate /opt/psa/var/certificates/certaqnxHd2;
ssl_certificate_key /opt/psa/var/certificates/certaqnxHd2;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
client_max_body_size 128m;
location / { # IPv6 isn't supported in proxy_pass yet.
proxy_pass https://+++.+.++.++:7081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Accel-Internal /internal-nginx-static-location;
access_log off;
}
location /internal-nginx-static-location/ {
alias /var/www/vhosts/example.com/httpdocs/;
access_log /var/www/vhosts/example.com/statistics/logs/proxy_access_ssl_log;
add_header X-Powered-By PleskLin;
internal;
}
}
server {
listen +++.+.++.++:443 ssl;
server_name webmail.example.com;
ssl_certificate /opt/psa/var/certificates/certaqnxHd2;
ssl_certificate_key /opt/psa/var/certificates/certaqnxHd2;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
client_max_body_size 128m;
location / { # IPv6 isn't supported in proxy_pass yet.
proxy_pass https://+++.+.++.++:7081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
access_log /var/www/vhosts/example.com/statistics/logs/webmail_access_ssl_log;
}
}
server {
listen +++.+.++.++:80;
server_name example.com;
server_name www.example.com;
server_name ipv4.example.com;
client_max_body_size 128m;
location / { # IPv6 isn't supported in proxy_pass yet.
proxy_pass http://+++.+.++.++:7080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Accel-Internal /internal-nginx-static-location;
access_log off;
}
location /internal-nginx-static-location/ {
alias /var/www/vhosts/example.com/httpdocs/;
access_log /var/www/vhosts/example.com/statistics/logs/proxy_access_log;
add_header X-Powered-By PleskLin;
internal;
}
}
server {
listen +++.+.++.++:80;
server_name webmail.example.com;
client_max_body_size 128m;
location / { # IPv6 isn't supported in proxy_pass yet.
proxy_pass http://+++.+.++.++:7080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
access_log /var/www/vhosts/example.com/statistics/logs/webmail_access_log;
}
}
Note: sites-available and sites-enabled files are present inside apache2. Not in nginx.
I want my nodejs app to run on example.com/my-nodejsapp-folder/ without any port number.
Any help would be highly appreciated.
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
I haven't seen where it says you can use dots and slashes in the upstream name
upstream mynodeapp {
server 1**.*.**.**:3010;
}
then
server {
listen 1**.*.**.**:80;
server_name example.com/my-app;
#...etc.
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# not this.
# proxy_set_header X-Accel-Internal /internal-nginx-static-location;
proxy_pass http://mynodeapp/my-app;
proxy_redirect off;
}
}
Then your node app needs to write a header containing:
X-Accel-Redirect: /internal-nginx-static-location/somefile
There are restrictions, as in, it may not work if you start returning content (e.g. print statements) before returning all headers. It's simpler to first test with only the interesting header.
Example:
# /etc/nginx/conf.d/default.conf
upstream mynodeapp {
server 127.0.0.1:8000;
}
server {
listen 127.0.0.1:80;
location /secret {
alias /tmp/secret;
internal;
}
location /my-app {
proxy_pass http://mynodeapp/my-app;
}
}
And let's try the following:
// /tmp/index.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'X-Accel-Redirect': '/secret/foo'});
res.end('Hello World\n');
}).listen(8000, '127.0.0.1');
And now the command line:
[root#localhost secret]# pwd
/tmp/secret
[root#localhost secret]# echo bar > foo
[root#localhost secret]# curl http://127.0.0.1:80/my-app
bar
[root#localhost secret]# curl http://127.0.0.1:80/secret/foo
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.0.15</center>
</body>
</html>
[root#localhost secret]#
You can take a look into my Nginx config https://github.com/zoonman/ruliq/blob/master/etc/nginx/www.linuxquestions.ru.conf