Reverse proxy not working - node.js

I am trying to create a reverse proxy using Apache. I'm using Apache to serve a php application and I have written an API in node which uses Express.
Inside my PHP application I use AJAX calls to node to retrieve JSON. I want to use port 80 for the calls in the PHP app and a reverse proxy using Apache to Express.
The issue I have is that I get an error 500 (proxy request).
My suspicion is that it has something to do with SSL.
Here's part of the configuration I have for Apache:
SSLEngine On
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass /stats https://127.0.0.1:8081/
ProxyPassReverse /stats https://127.0.0.1:8081/
ProxyRequests on
Here's how I configured node:
app.listen(8081, function () {
console.log('Listening on port 8081!')
})

I got the proxy to work correctly. The issue was that in ProxyPass and ProxyPassReverse were set to https when https was not enabled.

Related

Apache 2.4 - Simple reverse proxy - not working for multiple entries

I referred the below link and configured the proxy.
https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
When I configure a proxy for a single application as below in Apache 2.4 in the httpd.conf file, the proxy configuration is working fine. I am able to access my application through the proxy server URL.
ProxyPass / http://host1:8888/
ProxyPassReverse / http://host1:8888/
However If I try configure for two application like below, I am not able to access any of the application.
ProxyPass /nifi http://host1:8888/
ProxyPassReverse /nifi http://host1:8888/
ProxyPass /kibana http://host2:5601/
ProxyPassReverse /kibana http://host2:5601/
Not knowing how you try to reach the application makes it difficult to guess what's might be wrong.
I suggest you to change the proxies config as following:
ProxyPass /nifi/ http://host1:8888/
ProxyPassReverse /nifi/ http://host1:8888/
ProxyPass /kibana/ http://host2:5601/
ProxyPassReverse /kibana/ http://host2:5601/
then try to reach the endpoint pointing your browser to http://youdomain/nifi/ and http://youdomain/kibana/ and check the logs for errors.

NodeJS + Apache Proxy, having trouble with routing a secured websocket through (apache config help please)

I've looked through countless of posts on here on how to do this, and I wasn't able to get this simple task working. I'm using Apache as a proxy that is suppose to encrypt/decrypt TSL packets, and then have an unsecured communication with the NodeJS server. The problem is that the web application loads fine, however the websocket fails with an error 404 (not found) and I've had an error 200 before (handshaking issue). I've tried many different configurations and it's not working.
This is what I have on the client side.
const connection = new WebSocket('wss://example.com/wss');
Using wss:// instead of ws:// here because I want to have a secured connection.
On the server side, I have just the standard
ws.on('connection', w => {
w.on('message', msg => {
var data = JSON.parse(msg);
// do something with the message ...
});
});
This is my Apache config file
ServerName www.example.com RewriteEngine on
RewriteCond %{HTTP:Upgrade}=websocket [NC]
RewriteRule /(.*) wss://127.0.0.1:3000/$1 [P,L]
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLProxyEngine on
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
ProxyPass /wss ws://127.0.0.1:3000/
ProxyPassReverse /wss ws://127.0.0.1:3000/
On the Apache side I'm not certain if I should have wss:// or ws:// for ProxyPass since it should be insecure between Apache and NodeJS. I put it as ws:// here but both ways didn't work. For this configuration I get 404 error.
Any help would be greatly appreciated! Thanks
I solved this problem with the Nginx reverse proxy,
The problem is the fact that I set up socket connection to be on the port 8080, but the proxy is set up for the port 3000. The issue should resolve if you put them on the same port.
i.e.
App server,
const ws = new WebSocket.Server({port: 3001});
Apache
ProxyPass /wss ws://127.0.0.1:3001/
ProxyPassReverse /wss ws://127.0.0.1:3001/

Proxy Error 502 on Apache2 for Reverse Proxy to NodeJs Subdomain App on Digital Ocean

Hello guys
Im trying to deploy my nodejs api on Digital Ocean, under subdomain https://api.host.com. Its has some path bellow, all starting by /v0.1.
For example https://api.host.com/v0.1/users
On this droplet the nodejs app is running over http://localhost:3000
At the same droplet i have got other app, a website hosted on Apache and responds at https://host.com it works fine.
Im using Apache for Reverse Proxy make all calls from https://api.host.com/ to http://localhost:3000.
Actually It works only for root path, i mean try to access https://api.host.com/ responds right but when i try to access other path i get error
Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request
Reason: DNS lookup failure for: 127.0.0.1:3000v0.1
Apache/2.4.29 (Ubuntu) Server at api.host.com Port 443
HTTP Status Code: 502 Proxy Error
my vhost looks like...
<VirtualHost *:80>
...
...
ServerName api.host.com
ProxyPass /.well-unknown/ !
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
...
...
</VirtualHost>
Help please!
I am doing the same thing with an Apache server forwarding requests from a subdomain via a proxy to my nodeJS app listening on port 8080.
I believe that you only need to proxy pass the root to localhost:3000 and the nodeJS app is supposed to handle the routing.
For instance, if you are using express, something like.....
app.get('/v.01/users/', function (req, res) {
res.sendFile('/v.01/users/index.html'); });

How do I redirect all calls on one port to the same URL on another port with apache?

I'm hosting a sails.js application on the default port 1337. I have an apache serving as its proxy on port 8080:
[root#ip-192-168-0-XX conf.d]# cat nodetest.conf
Listen 8080
<VirtualHost 192.168.0.XX:8080>
Options -Indexes
ProxyRequests on
ProxyPass / http://localhost:1337/
</VirtualHost>
The Sails application has an API. So for instance, if I want to post a message, I enter this into my browser:
http://localhost:1337/Message/postMessage
I want that to happen when I enter the same address on port 8080.
http://localhost:8080/Message/postMessage
I am brand new to this Apache stuff, so I don't even know what the thing I want to do right now is called? Reverse Proxy? Regular Proxy? Redirects? I just don't know.
Firstly, I guess you would really only need to do this if you have Apache hosting other sites on the same server.
If you have no intention of running other sites on the same server with Apache, you can always just hit the Sails server directly at port 80 or 8080 by changing the port in your sails application in the config/local.js file.
Change
// port: process.env.PORT || 1337,
To
port: process.env.PORT || 80,
For other applications, like load balancing or basic proxying, I think nginx would be a far better solution.
The standard configuration for using Apache as a proxy for Sails would be something like this:
<VirtualHost *:8080>
ServerName example.com
ServerAlias www.example.com
ProxyRequests off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass http://localhost:1337/
ProxyPassReverse http://localhost:1337/
</Location>
</VirtualHost>

Apache Reverse Proxy and localhost - "Mixed content, the content must be served over HTTPS"

I have created a reverse proxy for my node server that runs on localhost, so that it can be served over HTTPS.
The forwarding works grate, however when the app tries to make requests I get:
Mixed Content: The page at 'https://foo.com/' was loaded over HTTPS,
but requested an insecure XMLHttpRequest endpoint
'http://localhost:8888/graphql?query=%7Bnotifications(userid)%7Bid%2C…
This request has been blocked; the content must be served over HTTPS.
Vhost config:
<VirtualHost *:443>
ServerName www.foo.com
ServerAlias foo.com
DocumentRoot /var/www/foo/
ErrorLog /var/www/foo/error.log
CustomLog /var/www/foo/requests.log combined
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLCertificateFile "/etc/letsencrypt/live/foo.com/cert.pem"
SSLCertificateKeyFile "/etc/letsencrypt/live/foo.com/privkey.pem"
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://localhost:8888/
ProxyPassReverse / http://localhost:8888/
</VirtualHost>
What is missing from my setup?
You are openning the page on https://foo.com/, but URLs within your page contain hardcoded localhost domain and port. While rendering the page, client browser will try to fetch 'http://localhost:8888/graphql effectively skipping apache (which is running on port 80, on server foo.com) and hitting directly your node app, which will 1) work only if you run the browser from the very same machine where you have your node app running, and 2) even then, you will get the above error since some page assets are loaded using http.
When you use relative URLs (for example URL that begins with /), browser will prepend the base URL, resulting in https://foo.com/graphql.
Absolute vs relative URLs
You need to add a SSL certificate to your node.js app. Enabling it on apache won't help since the apache is forwarding the requests to your node.js app on port 8888 (which communicates on plain http and not https). That's why you get the mixed content error. The initial request is on https on apache then forwarded to http to node.js
Steps to configure node.js app with a SSL certificate (you can use a self-signed certificate or a commercial one).
First you have to use ssl-root-cas available via npm. The configure it as follows:
'use strict';
var https = require('https')
, cas
;
// This will add the well-known CAs
// to `https.globalAgent.options.ca`
require('ssl-root-cas').inject();
cas = https.globalAgent.options.ca;
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '01-ssl-intermediary-a.pem')));
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '02-ssl-intermediary-b.pem')));
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '03-ssl-site.pem')));
Try and see if that works!

Resources