Browser-sync: Proxy mode missing critical headers

Created on 6 Feb 2015  Â·  15Comments  Â·  Source: BrowserSync/browser-sync

Given:

When running in proxy mode, we need the following headers in order for the application to work properly:

  • X-Forwarded-For: The IP address of the client (because the incoming request is coming from the proxy, which masks the client's real IP address)
  • X-Forwarded-Host: The host requested by the client (i.e. the proxy address, not the existing server's address)
  • Host: The existing server's address (right now it is the proxy server's address, which is wrong). In https://github.com/BrowserSync/browser-sync/pull/120#issuecomment-39418996 you confirmed the behavior I am asking for, but the implementation does not match what you said it should be.

The first header is needed for security reasons (ability to detect local vs remote clients). The second header is needed for redirecting clients (e.g. redirect the user to the login page).

Most helpful comment

version 2.7.0 allows any of the node-http-proxy options to be passed through, so in your case, xfwd is the one you want.

var bs = require('browser-sync').create();

bs.init({
    proxy: {
        target: "www.bbc.co.uk",
        proxyOptions: {
            xfwd: true
        }
    }
});

All 15 comments

this will be landing in BrowserSync soon which will allow you to define your own headers for each request.

:)

@shakyShane Hmm, I don't fully understand https://github.com/BrowserSync/browser-sync/blob/master/examples/proxy.headers.js#L27. Where is config.urlObj documented?

@cowwoc sorry it's not documented yet, but it's just the foxy config object https://github.com/shakyShane/foxy/blob/master/lib/server.js#L16-L21

You could log it out for now to see what you have access to.

browserSync({
    files: ["app/css/*.css"],
    proxy: {
        target: "localhost:8000",
        reqHeaders: function (config) {
            console.log(config);
            return {
                "host":            config.urlObj.host,
                "accept-encoding": "identity",
                "agent":           false
            }
        }
    }
});

Thank you, @shakyShane, it works:

 browserSync({
            proxy: {
            target: '127.0.0.1:5000',
            reqHeaders: function (config) {
                return {
                    // prevent Host header overriding
                    //"host":            config.urlObj.host,
                    "accept-encoding": "identity", // disable any compression
                    "agent":           false
                };
            },
            middleware: function (req, res, next) {
                res.setHeader("X-Forwarded-For", req.ip);
                res.setHeader("X-Forwarded-Host", req.headers.host);
                next();
            }
        }
    });

It seems bit tricky because 'http-proxy' has xfwd option.

Thanks @generalov .

@cowwoc - does the example from @generalov work for you?

If it does and this is a common use-case I will add to core behind a single option. :)

version 2.7.0 allows any of the node-http-proxy options to be passed through, so in your case, xfwd is the one you want.

var bs = require('browser-sync').create();

bs.init({
    proxy: {
        target: "www.bbc.co.uk",
        proxyOptions: {
            xfwd: true
        }
    }
});

Thanks!

Seems xfwd is missing "x-forwarded-host"

@ericfong I ran into the same issue -- X-Forwarded-Host wasn't populated by xfwd.
Here's how I ended up populating it:

#!/usr/bin/env node
var path = require('path')
var home = path.normalize(__dirname + '../../..')

var bs = require('browser-sync').create()

bs.init({
  files: [
    path.join(home, 'server/static/*.*')
  ],
  proxy: {
    target: 'localhost:8000',
    middleware: function (req, res, next) {
      req.headers['X-Forwarded-Host'] = req.headers.host
      next()
    }
  }
})

How to enable Host: header forwarding using the command line browser-sync? Is this the function of the --host option (its description, Specify a hostname to use is not very clear)?

Good question -- I assumed that it wasn't because that flag would traditionally control what interface the server would accept requests on. Not sure my assumption holds in this case. If it is a way to control the X header, the flag should probably be renamed.

If you want to pass the Host header to the backend unchanged, use the following config:

  proxy: {
    target: "...",
    proxyOptions: {
      changeOrigin: false
    }
  },

By default, browser-sync passes changeOriginal: true to node-http-proxy, and this will change the Host header.

there is no proxy.proxyOptions description in API Documention

I think this is interesting. I found this by luck and some googleing and @dancon is right, I also did not find any mention of this proxy.proxyOptions nore the changeOrigin in the docs anywhere — despite finding it very useful.

So happy I found this here now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kraf picture kraf  Â·  3Comments

ngryman picture ngryman  Â·  3Comments

Zver64 picture Zver64  Â·  3Comments

zewa666 picture zewa666  Â·  3Comments

Mil00Z picture Mil00Z  Â·  3Comments