What is reverse proxy ?
In computer networks, a reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client, appearing as if they originated from the proxy server itself.[1] Unlike a forward proxy, which is an intermediary for its associated clients to contact any server, a reverse proxy is an intermediary for its associated servers to be contacted by any client. In other words, a proxy acts on behalf of the client(s), while a reverse proxy acts on behalf of the server(s). https://en.wikipedia.org/wiki/Reverse_proxy
Our example use case
We have an application say Grafana in our case in which you can create dashboards and later embed those dashboards in your own application. A user needs to log into your application first and then can see the embedded dashboard. However our third party application, Grafana, also needs authentication and as result will ask for login inside the embedding frame. Since this is not desirable, what we can do is create a reverse proxy in our backend service and the url in iframe would point to our app which in turn will forward the request to the 3rd party server (Grafana), authenticating on the user’s behalf and then send the response back.
Let us see it in action
We will develop a simple backend service in node and embed a dashboard from Grafana which is running on http://localhost:3000/. The node service run on port 8000. So initiliaze a node application with expressjs. The package.json looks like following. Nodemon is only for auto reloading our server while development.
// package.json { "name": "rev-proxy-grafana", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "nodemon index.js" }, "author": "", "license": "ISC", "devDependencies": { "nodemon": "^1.19.2" }, "dependencies": { "express": "^4.17.1", "http-proxy": "^1.17.0" } }
<!-- public/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Reverse Proxy</title> </head> <body> <h5>This is an example of Reverse Proxy and embedding Grafana dashboard</h5> <!--Link to Grafana dashboard--> <iframe src="http://localhost:8000/d/63Nbd_5Zk/testdashboard?from=1568435814835&to=1568457414837&orgId=1" frameborder="0" height="500" width="800"></iframe> </body> </html>
Note above that the entire iframe src path should link to the dashboard URL of grafana. The host and port should, however, point to our new node service with proxy.
The next step is write our index.js. Here we will use http-proxy (https://www.npmjs.com/package/http-proxy) to pipe request and response to and from Grafana. We can also use http-proxy‘s events like proxyReq, proxyRes, error etc to modify our requests and responses. Example could be checking for some authentication token, adding such tokens, adding/modifying headers etc. The code for the index.js is shown below:
//index.js var express = require('express'); const app = express(); const port = 8000; app.use(express.static('view')) var http = require('http'); var httpProxy = require('http-proxy'); var proxy = httpProxy.createProxyServer({}); proxy.on('proxyReq', function (proxyReq, req) { proxyReq.setHeader('X-WEBAUTH-USER', 'admin') }); proxy.on('proxyRes', function (proxyRes, req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); }); proxy.on('error', function (err, req, res) { res.writeHead(500, {'Content-Type': 'text/plain'}); res.end("An error occured"); }); app.all("/*", function (req, res) { console.log("Forwarding...") proxy.web(req, res, { target: 'http://localhost:3000/', // link to our target service secure: false }); }) app.listen(port, () => console.log(`Listening on port ${port}!`))
The last step is to change some Grafana config to allow for proxy authentication. Checkout https://grafana.com/docs/auth/auth-proxy/ for that. For authenticating any other service, we might need to do similar configurations or add the required token to the request in our proxy service before forwarding the request. Any yes, that’s it. Run the server and see it in action. Note that in this example, both our application and proxying is done in the same service. They can be made separate.
0 Comments