nginx websocket proxy: using defined location - nginx

I'm trying to setup websocket proxy for a defined location (/ws) and it doesn't work. But using root (/) as location works for me.
works:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}
}
doesn't work:
server {
listen 80;
server_name localhost;
location /ws {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}
}
I also inspected the server response:
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: localhost:8888" -H "Origin: http://localhost:8888/ws" http://localhost:8888/ws
HTTP/1.1 404 WebSocket Upgrade Failure
Server: nginx/1.13.12
Date: Thu, 17 Jan 2019 15:15:50 GMT
Content-Type: text/html
Content-Length: 77
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Access-Control-Allow-Origin: http://localhost:8888/ws
<html><head></head><body><h1>404 WebSocket Upgrade Failure</h1></body></html>
what am I doing wrong?

I think the problem here is with the pattern matching. You first have to give websocket url from client side as ws://localhost:80/ws/
Note here you have to give (/) at the end of the url, and at the NGINX server side, configure it in this way :
server {
listen 80;
server_name localhost;
location /ws/ {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
}}
Note here that you have to give /ws/ reference to location.

Related

Nginx empty Accept-Encoding leads to timeout

When I want to replace a string in a Nginx reverse proxy I use
sub_filter 'https://upstream.com' 'http://www.localhost:8080';
sub_filter_once off;
But it doesn't work (because its gzipped) so I add
proxy_set_header Accept-Encoding "";
But then the request times out (gateway timeout). I wonder how this could be possible, I tried to do a GET to upstream.com with postman with Accept-Encoding header set to empty and it worked fine, so it is an issue on my side.
My config looks like:
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
server_name localhost;
location / {
proxy_pass https://www.upstream.com;
proxy_hide_header 'x-frame-options';
proxy_cookie_domain ~^(.*)$ "http://www.localhost:8080";
proxy_set_header X-Real-IP $remote_addr;
proxy_cookie_path / "/; secure; HttpOnly; SameSite=none";
sub_filter 'https://www.upstream.com' 'http://www.localhost:8080';
sub_filter_once off;
sub_filter_types text/html;
proxy_set_header Accept-Encoding "";
}
}
}
PS: upstream.com is just an example, I use another URL.

Nginx doesn't pass response headers of NodeJS Server

I have trouble configuring my nginx reverse proxy. As it stands the requests look like this:
root#devserver:~# curl -I https://example.com
HTTP/2 401
server: nginx
date: Fri, 15 Oct 2021 11:42:00 GMT
content-type: text/html; charset=utf-8
content-length: 172
www-authenticate: Basic realm="please login"
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'self' http: https: data: blob: 'unsafe-inline'; frame-ancestors 'self';
permissions-policy: interest-cohort=()
strict-transport-security: max-age=31536000; includeSubDomains
root#devserver:~# curl -I http://127.0.0.1:5000
HTTP/1.1 500 Internal Server Error
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: *
Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 1386
Date: Fri, 15 Oct 2021 11:42:52 GMT
Connection: keep-alive
Keep-Alive: timeout=5
The Access-Control headers are missing, and I cannot figure out how I can configure nginx to pass them to the browser.
My nginx configuration looks currently something like this:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
root /var/www/example.com;
# SSL
...
# reverse proxy
location / {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Forwarded $proxy_add_forwarded;
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;
# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
Thanks for the help in advance :)
location / {
proxy_pass https://127.0.0.1:80;
proxy_set_header Host $host;
proxy_hide_header X-Frame-Options;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Accept-Encoding "";
client_body_timeout 3000;
fastcgi_read_timeout 3000;
client_max_body_size 128m;
fastcgi_buffers 8 128k;
fastcgi_buffer_size 128k;
Please use this and try .

How to configure nginx reverse proxy to use SECURE websockets upstream?

I want to use nginx as a reverse proxy for websocket connections.
Consider echo.websocket.org to be my backend websocket service. As a test client I use wscat from https://github.com/websockets/wscat.
What works:
client <-- ws --> backend:
wscat --connect ws://echo.websocket.org
client <-- wss -->: wscat --connect wss://echo.websocket.org
client <-- ws --> proxy <-- ws --> backend: wscat --connect ws://localhost with the following nginx configuration:
events {
}
http {
server {
listen 80;
location / {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
}
client <-- wss --> proxy <-- ws --> backend: wscat -n --connect wss://localhost with the following nginx configuration:
events {
}
http {
server {
listen 443 ssl;
ssl_certificate /pki/cert.pem;
ssl_certificate_key /pki/key.pem;
location / {
proxy_pass http://echo.websocket.org;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
}
What I want and what I need help with is configuring nginx to use secure websockets to connect to the backend. I want this configuration:
client <-- wss --> proxy <-- wss --> backend
I tried changing http://echo.websocket.org to https://echo.websocket.org without success. This leads to a 504 Gateway Timeout.
You need to use proxy_ssl_certificate and proxy_ssl_certificate_key as specified in Nginx Docs
This is my config upstream, server_name, ssl_certificate, HTTP 301:
server {
listen 80; # nginx 80
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
# Set correct content type. According to this:
# https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29
# Current specification requires "text/plain" or no content header at all.
# It seems that "text/plain" is a safe option.
default_type "text/plain";
# This directory must be the same as in /etc/letsencrypt/cli.ini
# as "webroot-path" parameter. Also don't forget to set "authenticator" parameter
# there to "webroot".
# Do NOT use alias, use root! Target directory is located here:
# /var/www/common/letsencrypt/.well-known/acme-challenge/
root /var/www/html;
}
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/***0***0.ru/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/***0***0.ru/privkey.pem; # managed by Certbot
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name ***0***0.ru; # server name
location /sockjs-node/ {
proxy_pass http://node; # wep application
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location / {
proxy_pass http://node;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /smpp {
rewrite /smpp(.*) /$1 break;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
proxy_pass http://smpp;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
upstream smpp {
server localhost:5001;
}
upstream node {
server localhost:5000;
}

How to redirect websocket session with an Nginx proxy to an IBM Bluemix webapp?

Here is my nginx.conf :
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log debug;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server myapp.onbluemix.net:80;
}
server {
listen 80;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://websocket;
}
}
}
I can ping from nginx proxy server my webapp on bluemix.
Here the nginx's logs :
HTTP/1.1 500 Error
Server: nginx/1.13.3
Content-Type: text/xml
Transfer-Encoding: chunked
Connection: keep-alive
X-Backside-Transport: FAIL FAIL
I added the webapp's IP address to the nginx's hosts file just in case, same error.
Nginx proxy works if i run the webapp on my local machine.
I don't understand that assertion X-Backside-Transport: FAIL FAIL
What's wrong ?
It seems the internal IBM Proxy is involved, you have to add the host you want to reach in the header (proxy_set_header host myapp.onbluemix.net;) like:
location / {
proxy_http_version 1.1;
proxy_set_header host myapp.onbluemix.net;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://websocket;
}

Elasticsearch : Connection refused while connecting to upstream

I've set up an Elasticsearch server with Kibana to gather some logs.
Elasticsearch is behind a reverse proxy by Nginx, here is the conf :
server {
listen 8080;
server_name myserver.com;
error_log /var/log/nginx/elasticsearch.proxy.error.log;
access_log off;
location / {
# Deny Nodes Shutdown API
if ($request_filename ~ "_shutdown") {
return 403;
break;
}
# Pass requests to ElasticSearch
proxy_pass http://localhost:9200;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;
# For CORS Ajax
proxy_pass_header Access-Control-Allow-Origin;
proxy_pass_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type';
add_header Access-Control-Allow-Credentials true;
}
}
Everything works well, I can curl -XGET "myserver.com:8080" to check, and my logs come in.
But every minute or so, in the nginx error logs, I get that :
2014/05/28 12:55:45 [error] 27007#0: *396 connect() failed (111: Connection refused) while connecting to upstream, client: [REDACTED_IP], server: myserver.com, request: "POST /_bulk?replication=sync HTTP/1.1", upstream: "http://[::1]:9200/_bulk?replication=sync", host: "myserver.com"
I can't figure out what it is, is there any problem in the conf that would prevent some _bulk requests to come through ?
Seems like upstream and a different keepalive is necessary for the ES backend to work properly, I finally had it working using the following configuration :
upstream elasticsearch {
server 127.0.0.1:9200;
keepalive 64;
}
server {
listen 8080;
server_name myserver.com;
error_log /var/log/nginx/elasticsearch.proxy.error.log;
access_log off;
location / {
# Deny Nodes Shutdown API
if ($request_filename ~ "_shutdown") {
return 403;
break;
}
# Pass requests to ElasticSearch
proxy_pass http://elasticsearch;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;
# For CORS Ajax
proxy_pass_header Access-Control-Allow-Origin;
proxy_pass_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
add_header Access-Control-Allow-Headers 'X-Requested-With, Content-Type';
add_header Access-Control-Allow-Credentials true;
}
}

Resources