Skip to content

Instantly share code, notes, and snippets.

@andris9
Last active December 29, 2022 02:38
Show Gist options
  • Save andris9/8093905 to your computer and use it in GitHub Desktop.
Save andris9/8093905 to your computer and use it in GitHub Desktop.
Extremely simple HTTP proxy for changing Host: header Useful when proxying requests to virtual hosts that require Host: header to be set.

Setup reverse tunnel

Run the following in your client machine

ssh -R EXPOSED_PORT:localhost:SERVICE_PORT USER@HOST

Where

  • EXPOSED_PORT is the port exposed to the internet in the proxy server
  • SERVICE_PORT is the port your application is listening in your machine
  • USER is the username of the ssh user
  • HOST is the proxy server host

EXPOSED_PORT is the same as PORT_TARGET in proxy.js

If proxying does not work, check if you have set the following line in your sshd config of the proxy server

GatewayPorts clientspecified

After you haved logged in to the ssh server, run the proxy

"use strict";
/*
Creates a HTTP proxy that rewrites Host: header to a predefined value
Useful when forwarding requests to Apache or Nginx virtual hosts
Usage:
PORT_LISTEN=123 PORT_TARGET=456 HOST_TARGET=127.0.0.1 HOST_ORIGIN="tere.ee" node proxy.js
Where
* PORT_LISTEN is the port the proxy should be listening for incoming requests
* PORT_TARGET is the port the target server is listening for
* HOST_TARGET is the hostname or IP where the target server is listening on
* HOST_ORIGIN is the value that is set for the Host: header
*/
var http = require("http"),
url = require("url");
var listenPort = process.env.PORT_LISTEN || 8080,
targetPort = process.env.PORT_TARGET || 9000,
targetHost = process.env.HOST_TARGET || "localhost",
origin = process.env.HOST_ORIGIN || "origin";
var server = http.createServer(function(request, response){
var options, proxyRequest, user;
request.headers.host = origin;
request.headers['x-forwarded-for'] = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
options = url.parse("http://" + targetHost+(targetPort?":"+targetPort:"") + request.url);
options.method = request.method;
options.headers = request.headers;
proxyRequest = http.request(options);
proxyRequest.addListener("response", function (proxyResponse) {
proxyResponse.pipe(response);
response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
// Log requests to console
console.log("%s [%s] \"%s %s\" %s",
request.headers['x-forwarded-for'],
new Date().toISOString().replace(/T/, " ").replace(/\.\d+Z/i, ""),
request.method,
request.url,
proxyResponse.statusCode);
});
request.pipe(proxyRequest);
});
server.listen(listenPort, function(){
console.log("Proxy listening on port %s", listenPort);
console.log("Forwarding requests to http://%s as %s", targetHost+(targetPort?":"+targetPort:""), origin);
});
@tjcrowder
Copy link

Fantastic, thank you for this! I've forked it to add handling rewriting the Location header on 3xx responses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment