webmachine/webmachine-ruby

Cannot detect if a request comes in via https when behind a Proxy

Asmod4n opened this issue · 8 comments

Currently https://github.com/seancribbs/webmachine-ruby/blob/master/lib/webmachine/request.rb#L99 cannot detect if a request comes in via https when webmachine runs behind a proxy, what rack does isn't complete either https://github.com/rack/rack/blob/master/lib/rack/request.rb#L70

what i am doing at the moment is to set request.uri.scheme to this on Resource.new

def scheme
  if request.x_forwarded_https == 'on' || request.x_forwarded_ssl == 'on'
    'https'
  elsif request.x_forwarded_scheme
    request.x_forwarded_scheme
  elsif request.x_forwarded_proto
    request.x_forwarded_proto.split(',').any?{|x| x.strip == 'https' } ? 'https' : 'http'
  else
    request.uri.scheme
  end
end

It works behind Pond, Apache and Nginx.
Does this even belong in Webmachine or should each adapter do it on its own?

@Asmod4n I believe those headers are fairly well-known. The solution above looks sane, but I'd love to see several people test it in different combinations.

@seancribbs What is a real let down is that anyone can send those headers, so you probably need a option in https://github.com/seancribbs/webmachine-ruby/blob/master/lib/webmachine/configuration.rb#L11 specifying which headers to trust.

@Asmod4n Yes, this is not as cut-and-dry as I had hoped. Maybe some of our more security-savvy folks can chime in? @tarcieri maybe?

Definitely should be gated by some sort of "I'm behind a proxy I trust" setting

I belive i came up with something useful.

By default Webmachine believes it connects directly to clients, passing along request.headers unmodified to your app.

When you set a new option like :runs_behind_proxy to true you also have to give it a hash of trusted headers like X-Forwarded-For and X-Forwarded-Port. It then duplicates the request.headers hash, modifies all entries which start with "X-" passing along only those which are trusted and also automagically changes request.uri.

Proxies tend to send X-Forwarded-Port, X-Forwarded-Host and X-Forwarded-Proto so changing request.uri to reflect those values can come handy.

I am just at a loss how to implement that once you use Webmachine like here https://github.com/seancribbs/webmachine-ruby/blob/master/examples/application.rb#L21, how would one get a hold of the configuration stored in MyApp :?

Made probably the most hackish attempt to support it the way it currently is in #153

Closing in favor of #153