44 comments

[ 4.8 ms ] story [ 87.6 ms ] thread
I spent almost an entire day doing this today, and in the course of getting documentation the traditional Rails way -- Googling for blog posts from 2007 and finding what changed right after it took the site down -- got a little frustrated. To vent a bit, I wrote it up cookbook-style so that someone in 2014 can curse my name.
Well someone in 2010 is extremely grateful for your effort.
At least you have a date on your article. Half the articles I find have no date, and so then you're left wondering, 'exactly how out-of-date is the information I just found?'
I hate that. It really perplexes me when things pretending to be News Papers leave off dates.
I was surprised to see Tim Ferriss advocating something like this in the video of his that was posted over the weekend.
That is one of the best actionable pieces of advice I have ever seen him give, because the vast majority of his work, and well thought blog posts on nontechnical topics, is evergreen: it continues to be worthwhile years after publication. The preference for the new because it is new is irrational, and the constant content treadmill aping newspapers (who need it because they have a new paper to put out every day to wrap ads around) is a terrible idea for most bloggers. Ditto for those of us who do publishing for our businesses.
I agree, and I'm not advocating that everyone should always have a date on every piece of content they produce. Rather, one should think rationally about whether or not a specific piece of content will age well or not, and date it appropriately. In my opinion code tutorials and how-to's do not age well.
It may be actionable, but it's also user-hostile.
And you place the date at the top, so we don't have to scroll down an indefinite amount and maybe find one, maybe not. :-)
My one and old Rails app is running using Apache + Passenger. When I set it up, I wanted to get it using SSL site wide as easily as possible, so I just stuck in a rewrite rule in Apache:

  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
It's been a year since I did that, but I think that's what I used to force the entire site into https only requests.
I don't understand why you go through the trouble of letting Mongrel/Rails handle the SSL. I've always opted to just let Apache handle it and I don't doubt nginx could just as well. Our Passenger simply doesn't know that everything between client and server happens to be encrypted.
nginx has a SSL module[1], so you could do that. Just redirect all traffic coming to port 80 to https[2]. But he might have had a good reason to handle it in Mongrel.

[1] http://wiki.nginx.org/NginxHttpSslModule

[2] Add this to your config: server { listen 80; server_name example.com; rewrite ^/(.*) https://example.com/$1 permanent; }

Keep in mind that if you do any kind of proxy caching (Rack::Cache, etc.), AssetHostingWithMinimumSsl is going to cause problems (if, say, Safari generates a cached response, serves images and CSS from http:, and then any other browser is served that response).
SSL certs for $13.99? I don't see this anywhere on the GoDaddy page.
Don't know where GoDaddy's cheap ones went, but NameCheap has them for $10. http://www.namecheap.com/learn/other-services/ssl-certificat...
you can also get them for free at startssl.com (yes - they are recognized by major browsers, but you need to know how to configure a "chained" certificate in your server).
Just be aware, HTC stock browser on android (obscure I know), doesn't have StartSSL as a root certificate authority so it will give you a warning.
Fuck GoDaddy, they always cost twice as much by the time you're ready to enter your CC info. I buy my certificates from a RapidSSL reseller for $12/year. Single root, no chains, recognized everywhere.
Google for "godaddy ssl" and click the $12.99 ad to get that price.
Also keep in mind that SSL makes serving sites based on the host header much more difficult, and is one of a handful of justifications for additional IPs according to ARIN. Last I checked running multiple sites from a single IP with one of them using SSL was against something, but I can't seem to find that now.

Although it is trivial to implement SSL, you should only do it if you need to because of the above, using up all the IPv4 addresses because your random video sharing website might have a user somewhere on a wireless network where their cookies are hijacked. This attack has existed for pretty much ever and isn't very useful for a dedicated focused attack.

It is not generally possible to serve more than one https domain from a server, because browsers won't accept more than one certificate.

However just because you serve one site doesn't mean that you use one IP more, nor do you contribute to the exhausting of ipv4 addresses -- you already use your ip to connect to your server.

There's something called Server Name Indication that allows name-based virtual hosting with https. There's some good information here about it: http://wiki.apache.org/httpd/NameBasedSSLVHostsWithSNI

The problem is browser support isn't quite where it needs to be, with IE only supporting it in 7.0+ on Vista or later (IE 6 or IE anything running on Windows XP is out of luck).

I was testing an app with SNI SSL today and can confirm Firefox on Windows 7 throws an error.
It's also possible to run multiple SSL sites on one IPv4 address by assigning them to ports other than 443. It won't look pretty, but not too much hassle if you absolutely want to protect your logins.
There are three options that I know of:

1) SNI -- this has just too poor support at this time

2) Separate ports -- you can make make Apache listen on for example port 446 and use links like https://subdomain.foobar.com:446/.... -- however some corporate firewalls etc. may be blocking connections out on non-standard ports; we just that just for multiple testing environments. This still requires multiple certs or a wildcard cert.

3) Wildcard certs -- they are are usually quite bit more expensive but they'll let you register *.domain.com. So if a client wants a subdomain you can let them have client.yourdomain.com that way without multiple certs or IPs -- FogBugz uses that for example.

That's quite interesting. Don't forget to make sure you have the secure flag set on your cookies, that way you won't send the cookies over non-SSL connections.

You should also set the HttpOnly flag, which implements some XSS-limiting features, dependent on the browser.

While you're looking at securing session management, it's probably worth looking at Cross-Site Request Forgery:

http://www.owasp.org/index.php/Cross-Site_Request_Forgery_(C...

Some frameworks, such as Django have Cross-Site Request Forgery protection built in for free. The OWASP site linked earlier is an invaluable resource for all things web application security, and is definitely worth bookmarking.

That's what I came here to say. You almost might as well not use SSL at all if you're not going to set the secure flag, because the same vulnerability that makes "FireSheep" work also allows you to intercept requests and coerce cookies out of them.

Of course, there's no trivially installable exploit with a pretty UI that plugs into Firefox to do that yet, so it'll be at least another few years before anyone takes that attack seriously.

A more agnostic way of doing this is to serve all your non-security required static content from a subdomain over HTTP, set the secure flag on your cookies, and scope the cookie to the fully qualified domain name (e.g. www.myapp.com rather than myapp.com).
if a page contains mixed content (secured and nonsecured), browsers will complain (and rightfully so). If you want to go the SSL route, then you'll have to serve all assets over SSL too.

Also note that SSL doesn't really work with name based virtual hosts (Host:-header), so every site you enable SSL with requires its own IP address.

With addresses in general running out quickly, this might be a problem for you (or your host).

You are of course, completely correct. Thanks for pointing that out.

With larger SSL sites, it's not uncommon to use SSL accelerators and reverse proxy through to the HTTP servers at the back. It's definitely not cheap though.

For those who have sites built on Drupal the combination of two modules can keep you relatively safe. First secure pages (http://drupal.org/project/securepages) and secure pages hijack prevention (http://drupal.org/project/securepages_prevent_hijack). With the combination of the two, a user session can still be hijacked. However, it will only allow them to go to non-SSL pages. In the case where a user may login and visit a lot of pages that aren't sensitive, but some that are this is a good option and pretty easy to set up.
Wow, I use one before_filter on my Heroku hosted app. Am I doing something wrong here, or is this just Heroku's awesomeness?

  def redirect_to_ssl
    redirect_to :protocol => "https://" unless (request.ssl? or request.local?)
  end
Heroku is awesome, but one of the drawbacks (to my knowledge) is that you can't set up nginx redirects. So with that setup each user incurs an extra rails request once per session.
Why are these tutorial framework specific? Just set up your nginx/lighttpd/apache to server traffic over HTTPS and set up redirects from http://example.com to https://example.com.
"Just" setting up Nginx to redirect http:// to https:// just comprehensively broke your site if it previously existed on HTTP only and used some fairly common web dev practices, like splitting images over multiple domains to reduce load time. You now pop Big Scary Warnings all over the place.
https for a static content? No, thank you.