How do I use nginx as proxy for a websocket ?
If I need to connect to socketSite.com:port from clientSite.com( javascript)
And I won't to show user's link "socketSite.com:port "
Can I use nginx proxy for redirecting requests from/to websocket server ?
Absolutely, you can! Use the following configuration:
location /myHandler{
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header HOST $host;
proxy_set_header X_Forwarded_For $remote_addr;
proxy_pass http://localhost:8880;
proxy_redirect default;
client_max_body_size 1000m;
}
I use spring websocket. /myHandler is my URL to create the websocket connection, http://localhost:8880; is my Tomcat server address. Nginx server and Tomcat are running on the same machine.
Related
We are using NGINX on our cPanel server to reverse proxy ZKTeco ZKBioSecurity servers. Due to compatibility with some of their devices not supporting HTTPS, all our servers use HTTP, but, of course, all sessions to our NGINX server is secured with HTTPS and a Sectigo certificate provided by cPanel’s AutoSSL.
Here’s the problem: it seems that the ZKBioSecurity servers are detecting that the client is using HTTPS to connect to them through NGINX, and because of this, give the following prompt each time you want to log in, advising you to download and install the ISSOnline driver and certificate. The certificate, however, is issued to the ZKBioSecurity server for 127.0.0.1, so of course this is rather pointless as we are connecting to the NGINX server using a FQDN. This does not happen if we use HTTP:
So my question: is there something in the request (the HTTP header perhaps?) that NGINX forwards to the upstream server that contains the protocol (HTTPS) the client used to connect to the server? Because this somehow seems to be the case.
Here’s our NGINX config for ZKBioSecurity servers:
location /.well-known {
root /home/novacloud/public_html/subdomain/.well-known;
allow all;
try_files $uri = 404;
}
location / {
if ($scheme = http) {
return 301 https://$host$request_uri;
}
proxy_pass http://192.168.0.1:8080;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
The server_name directive is, of course, managed by cPanel. The above is an example of the include files we use in the main cPanel NGINX configuration file. I thought it was the proxy_set_header X-Forwarded-Proto $scheme, but even if I remove this, I still get the Driver Detection Exception prompt.
Here’s a Pastebin of a cURL of the ZKBioSecurity server from our cPanel/NGINX server
Node.js app is running fine on port 80 (using PM2 and Nginx) and can browse through server IP well. But through domain it isn't working [This site can’t be reached]. On pinging the domain can see the server IP on the response.
Here is the Nginx config I used:
location / {
proxy_pass "http://127.0.0.1:8000";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
You need to use a server_name declaration in your Nginx configuration.
server_name example.org www.example.org;
http://nginx.org/en/docs/http/server_names.html
I have a server with ubuntu 16.04, kestrel and nginx as a proxy server that redirects to localhost where my app is. And my app is on Asp.Net Core 2. I'm trying to add push notifications and using SignalR core. On localhost everything is working well, and on a free hosting with iis and windows as well. But when I deploy my app on the linux server I have an error:
signalr-clientES5-1.0.0-alpha2-final.min.js?v=kyX7znyB8Ce8zvId4sE1UkSsjqo9gtcsZb9yeE7Ha10:1
WebSocket connection to
'ws://devportal.vrweartek.com/chat?id=210fc7b3-e880-4d0e-b2d1-a37a9a982c33'
failed: Error during WebSocket handshake: Unexpected response code:
204
But this error occurs only if I request my site from different machine via my site name. And when I request the site from the server via localhost:port everything is fine. So I think there is a problem in nginx. I read that I need to configure it for working with websockets which are used in signalr for establishing connection but I wasn't succeed. May be there is just some dumb mistake?
I was able to solve this by using $http_connection instead of keep-alive or upgrade
server {
server_name example.com;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
I did this because SignalR was also trying to use POST and GET requests to my hubs, so doing just an Upgrade to the connection in a separate server configuration wasn't enough.
The problem is the nginx configuration file. If you are using the default settings of the ASP.NET Core deployment guide then the problem is the one of the proxy headers. WebSocket requires Connection header as "upgrade".
You have to set a new path for SignalR Hub on nginx configuration file.
such as
location /api/chat {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
You can read my full blog post
https://medium.com/#alm.ozdmr/deployment-of-signalr-with-nginx-daf392cf2b93
For SignalR in my case, besides the "proxy_set_header" settings, there is another critical setting "proxy_buffering off;".
So, a full example is now like,
http {
map $http_upgrade $connection_upgrade {
default Upgrade;
'' close;
}
server {
server_name some_name;
listen 80 default_server;
root /path/to/wwwroot;
# Configure the SignalR Endpoint
location /hubroute {
proxy_pass http://localhost:5000;
# Configure WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache_bypass $http_upgrade;
# Configure ServerSentEvents
proxy_buffering off;
# Configure LongPolling
proxy_read_timeout 100s;
proxy_set_header Host $host;
}
}
}
See reference: Document reverse proxy usage with SignalR
I have a scenario that i'm trying to configure in nginx where I have a number of processes each listening from ports 8000,8001... Upon establishing a http connection to one of these ports I then get the client (within javascript) to establish a WebSocket connection. All the listening processes have the same /SS websocket endpoint. However if a http connection initially makes a connection to 8000 it needs to also establish the websocket connection to 8000 too. I have the following nginx configuration:
upstream backends {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}
include /etc/nginx/conf.d/*.conf;
server {
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass http://backends;
}
location /SS {
proxy_set_header Host $host;
proxy_pass http://backends;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
However this doesn't route the the websocket to the same place as the initial connection.
I thought of a way to do this where I setup different endpoints for each process and pass this through the initial http request. I would get the client to then use this endpoint for the WebSocket connection. This would however need me to configure all the different endpoints in nginx. I was wondering if there's a better way to solve this just within the nginx configuration?
I'm running a node app and nginx 1.8.0. on the same server. Nginx routes requests using
server_name subdom.domain.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
Everything works perfectly fine. I now want to put my nginx on a different server changing the configuration to:
server_name subdom.domain.com;
location / {
proxy_pass http://<ipofthenewserver>:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
All I get is "504 Gateway Time-out".
I just re-read your topic, you have to configure nginx in new server
http://ipoftheoldserver:3000
Not:
http://ipofthenewserver:3000
and Make sure port application 3000(in old server) is open in over the world.
If connection had been refused by the back-end server, you would have got "502 Bad Gateway" error.
There are several methods to check it:
Look what happens on the new nginx server: tcpdump -i <name_of_iface> tcp and host <ip_of_be_server> and port 3000 -A
Make requests using curl from the new nginx server to back-end server
Look what happens on the back-end server using tcpdump
and so on