newby issue with rack-ssl gem

31 views
Skip to first unread message

Rich Morin

unread,
Dec 17, 2016, 8:03:14 PM12/17/16
to Rack Development

I'm using Rack via Sinatra and Thin, serving HTTPS on port 44567.  That works, but I'm not able to set up automated transfers from HTTP to HTTPS.  I'm trying to use the rack-ssl gem to force this, but not seeing any effect.


I assume that I'm simply calling it wrong.  Might anyone have suggestions?


FWIW, here's a Gist that documents and demonstrates the issue:


 https://gist.github.com/RichMorin/62d5594237e487242f027ca51cafa290


-r

James Tucker

unread,
Dec 17, 2016, 8:08:12 PM12/17/16
to Rack Development
This is a web server issue, not a rack issue. Most webservers will not let you serve plaintext and TLS over the same port. When I say most, I mean I don't know of any ruby webservers that support this, as all of them rely on openssl listen sockets for TLS.

--

---
You received this message because you are subscribed to the Google Groups "Rack Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rack-devel+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rich Morin

unread,
Dec 17, 2016, 8:42:26 PM12/17/16
to Rack Development
On Saturday, December 17, 2016 at 5:08:12 PM UTC-8, raggi wrote:
This is a web server issue, not a rack issue. Most webservers will not let you serve plaintext and TLS over the same port. When I say most, I mean I don't know of any ruby webservers that support this, as all of them rely on openssl listen sockets for TLS.

Hmmm.  A lot of web servers I've encountered force a switch from HTTP to HTTPS, but then, they're also switching from port 80 to port 443.  I suppose that I could redirect requests from (say) http://<IP>:34567/... to https://<IP>:44567/..., but I'm not sure how useful that would be.  Also, not exactly sure how to do this.

Any other suggestions, anyone?

-r

James Tucker

unread,
Dec 17, 2016, 8:49:15 PM12/17/16
to Rack Development


On Dec 17, 2016 5:42 PM, "Rich Morin" <r...@cfcl.com> wrote:
On Saturday, December 17, 2016 at 5:08:12 PM UTC-8, raggi wrote:
This is a web server issue, not a rack issue. Most webservers will not let you serve plaintext and TLS over the same port. When I say most, I mean I don't know of any ruby webservers that support this, as all of them rely on openssl listen sockets for TLS.

Hmmm.  A lot of web servers I've encountered force a switch from HTTP to HTTPS, but then, they're also switching from port 80 to port 443.

Thats precisely the point.

 I suppose that I could redirect requests from (say) http://<IP>:34567/... to https://<IP>:44567/..., but I'm not sure how useful that would be.  Also, not exactly sure how to do this.

Any other suggestions, anyone?

Your other option is to fingerprint the first few bytes, which are more than sufficient to determine http/http2/TLS clienthello/unknown. Like I said, I don't know of any ruby implementations of this, so you'd likely have to write one. It's not particularly tricky.

Rich Morin

unread,
Dec 17, 2016, 8:51:36 PM12/17/16
to Rack Development
On a related note, the Rack::SSL page (https://github.com/josh/rack-ssl) says that it "Redirects all 'http' requests to 'https'".  However, it says nothing about port numbers and offers no options that I can see in this area.  I'd like to understand the exact behavior I should expect from it and whether there are any ways to play with port numbers, etc.

-r

James Tucker

unread,
Dec 18, 2016, 2:01:31 AM12/18/16
to Rack Development
On Dec 17, 2016 5:51 PM, "Rich Morin" <r...@cfcl.com> wrote:
On a related note, the Rack::SSL page (https://github.com/josh/rack-ssl) says that it "Redirects all 'http' requests to 'https'".  However, it says nothing about port numbers and offers no options that I can see in this area.  I'd like to understand the exact behavior I should expect from it and whether there are any ways to play with port numbers, etc.

rack-ssl isn't an official rack project. I don't know if Josh still hangs around here.

rack-ssl works by inspecting the rack environment, as specified in http://www.rubydoc.info/github/rack/rack/file/SPEC#The_Environment

Specifically it looks for (in order):

env['HTTPS'] == 'on'   # this is not part of the rack spec, iirc, it was something mongrel and/or webrick do
env['HTTP_X_FORWARDED_PROTO] == 'https'  # this is the HTTP header X-Forwarded-Proto, which is often configured to be produced by upstream proxies. Further important notes anon.
env['rack.url_scheme'] == 'https' # this is the rack standard spec for a webserver to inform an application that the request was served with https.

Port numbers would not be useful for identifying whether or not a connection is https.

You should read the code for more details of rack-ssl's operation. It's only 89 lines long.

Important notes on X-Forwaded-Proto:

rack-ssl is not safe for use without an upstream proxy that always overwrites or sets X-Forwarded-Proto. Failure to prevent users from sending you this value could otherwise lead to certain rare cases of downgrade attacks on your service.

X-Forwaded-Proto while still extremely common is now a stale. RFC7239 was standardized in 2014 and defines a Forwarded-For header, the contents of which can specify this behavior. It is less used partly because it's new, and partly because it's harder to manage given that it requires more parsing. I'm also seeing a lot of cases in the wild now that the above RFC is getting talked about here and there, of people defining Forwarded-Proto instead, which is further incorrect.

In case it isn't clear, unless you make further adjustments to your server, using rack-ssl with the server from your gist is not safe.

HTH

Rich Morin

unread,
Dec 18, 2016, 1:04:44 PM12/18/16
to Rack Development
Thanks for the detailed response!  At the moment, I've taken rack-ssl out of my code and simply tell folks to use the https url.
Reply all
Reply to author
Forward
0 new messages