NGINX cannot forward https POST request to another port - nginx

I am running a NodeJS application and deployed using pm2 running on port 5000, this works fine with http requests. To get the https working I have created a reverse proxy in nginx to forward https request on port 5001 to forward to port 5000. It works fine if I disable the SSL, http request is correctly forwarded from port 5001 to port 5000 but https works only for GET method, but not for POST method.
server {
listen 5001 default_server;
ssl on;
ssl_certificate /home/ubuntu/xyz.crt;
ssl_certificate_key /home/ubuntu/xyz.key;
server_name mydomain.com www.mydomain.com;
root ~/mynodeapp; location / {
proxy_pass http://127.0.0.1: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; proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
I need to be able to call my API endpoint running on port 5000 over SSL through port 5001

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
I have no idea what the purpose of these headers is since they should only be used when forwarding WebSockets - which also means only in the context of GET. Thus it is likely wrong and might explain the problems you have.

Related

Reverse Proxy HTTPS Requests as HTTP to Upstream Server

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 working with Server IP but not With Domain Name

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

Proxying NGINX Traffic To Secondary Proxy with Proxy_Protocol Enabled

I am trying to route requests such that those requiring websockets will route to a long-lived nginx process, and all others will go to the general reverse-proxy which handles all other traffic. These nginx processes exist in our AWS cloud behind an ELB that has been configured to use Proxy Protocol. Note that all of this works correctly with our current setup which uses only one nginx process that is configured to use proxy_protocol.
The change to this setup is as follows:
The first nginx server handling all ingress uses proxy_protocol and forwards requests to either the websocket or non-websocket nginx servers locally:
server {
listen 8080 proxy_protocol;
real_ip_header proxy_protocol;
charset utf-8;
client_max_body_size 20M;
#send to websocket process
location /client {
proxy_pass http://localhost:8084;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Proxy-Scheme $scheme;
proxy_set_header X-Proxy-Port $proxy_port;
proxy_set_header X-ELB-Proxy-Scheme "https";
proxy_set_header X-ELB-Proxy-Port "443";
# Always support web socket connection upgrades
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
#send to non-websocket process
location / {
proxy_pass http://localhost:8082;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Proxy-Scheme $scheme;
proxy_set_header X-Proxy-Port $proxy_port;
proxy_set_header X-ELB-Proxy-Scheme "https";
proxy_set_header X-ELB-Proxy-Port "443";
# Always support web socket connection upgrades
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
When any non-websocket request is sent to localhost:8082, I get an empty reply. If I remove proxy_protocol from the first server, I get a response as expected. Obviously, I need proxy_protocol to support the ingress from our ELB, so removing it is not an option. However, I would like to know what pieces I am missing to route traffic correctly -- and I would also like to know why proxying a request locally from a proxy_protocol enabled server to another nginx process (regardless of this second process using proxy_protocol or not) fails.
For reference, the basic configuration of this secondary nginx process is below:
upstream console {
server localhost:3000 max_fails=3 fail_timeout=60 weight=1;
}
server {
listen 8082;
client_max_body_size 20M;
location /console {
proxy_pass http://console
}
.
.
.
}
Turns out the non-websocket proxy block should not set the various proxy and upgrade headers:
location / {
proxy_pass http://localhost:8082;
proxy_set_header Host $host;
}

how to configure Ngnix as reverse proxy for Phabricator ( Unhandled Exception ("AphrontMalformedRequestException"))

I am using phabricator by Docker image (https://hub.docker.com/r/hachque/phabricator/).
Because my phabricator server is in the LAN of a company, I cannot access it from the outside. I'm trying to use Ngnix as reverse proxy. I can access the login page, but when I try to login, following message was displayed:
Unhandled Exception ("AphrontMalformedRequestException") You are
trying to save some data to Phabricator, but the request your browser
made included an incorrect token. Reload the page and try again. You
may need to clear your cookies. This was a Web request. This request
had an invalid CSRF token.
Here is part of my Nginx reverse proxy configuration:
# phabricator proxy.
#
server {
listen 8080;
server_name 0.0.0.0;
location / {
proxy_pass http://193.177.1.238/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
I'm not using the same image as you, but what i've installed PHP 7.1 with Nginx and the Phabricator sources on the Docker image, then the Nginx from docker listen to the 9000 port (in my case).
Then i run this image using the 8081:9000 port mapping, and the following VirtualHost config on the Nginx from the host machine:
upstream api_upstream {
server 0.0.0.0:8080;
}
server {
listen 80;
server_name phabricator.local.com;
location / {
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_pass http://api_upstream;
}
}
the phabricator.local.com host only works if you add this entry to the /etc/hosts file:
127.0.0.1 phabricator.local.com

Move nginx to different server

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

Resources