ryanb / private_pub

Handle pub/sub messaging through private channels in Rails using Faye.
MIT License
863 stars 226 forks source link

SSL / HTTPS #18

Open mrrooijen opened 13 years ago

mrrooijen commented 13 years ago

Hi Ryan,

I'm using PrivatePub in one of my projects and it seems that I'm getting the HTTPS:// warning from Chrome because PrivatePub is trying to do something over HTTP://. I believe it may be either:

By "warning" i don't mean the huge WARNING screen, but simply this: http://cl.ly/2x0G0L3R2s092P0B282U

I was wondering if you know a way to get around this? Would it require me to purchase a new SSL certificate specifically for the Faye server?

I'm running on NGINX as my web server, Unicorn as my App Server and Thin for the Faye server.

Any pointers are greatly appreciated! Thanks

mrrooijen commented 13 years ago

Well I actually figured out how to route requests of my main domain that are coming in at the /faye url and proxy_pass them to my Thin Faye server.

server {
  listen                443;

  server_name           myapp.com;
  root                  /var/applications/current/rails/public;

  ssl                   on;
  ssl_certificate       /etc/ssl/my.crt;
  ssl_certificate_key   /etc/ssl/my.com.key;

  # Thin Faye Server
  location /faye {
    proxy_pass http://127.0.0.1:4001;
    break;
  }

  # Unicorn Main App
  location / {
    ...
  }
}

So now https://mydomain.com/faye.js properly without warning returns the javascript, but it seems that privatepub still can't connect to it or subscribe to channels when using HTTPS. Any idea why this is?

Thanks!

mrrooijen commented 13 years ago

I think the problem is that PrivatePub only assumes HTTP. I see you're loading in net/http here: https://github.com/ryanb/private_pub/blob/master/lib/private_pub.rb#L2

From recent experiences that doesn't work with HTTPS by default. I'll have a look and see if I can fix this to work over HTTPS as well.

mrrooijen commented 13 years ago

Well, I've been trying for the past 2-3 hours to get this working but without any luck.

I have no idea why PrivatePub or Faye won't accept HTTPS requests. I've also tried various http clients such as rest-client and nestful but still no luck. I'm probably doing it wrong though.

My https:// in the address bar is nice and green, but now PrivatePub won't work. :/ I personally don't really care whether it goes over https or http, as long as it doesn't show the https:// warning, which it's showing because the site is https:// but PrivatePub is sending or receiving data over http:// (in some way) which Chrome apparently doesn't like.

You have more in-depth knowledge about Faye/PrivatePub than I do of course, so I may just be missing something obvious. Any feedback, idea's or suggestions much appreciated! :)

mrrooijen commented 13 years ago

Just a heads up, it seems I fixed it and it now properly works over HTTPS.

I'm going to clean up the mess I made, so much code snippets commented out and combinations used ha.

I'll submit the details here once I clean up everything, and if applicable I'll submit a pull request so you can support HTTPS:// with PrivatePub as well.

mrrooijen commented 13 years ago

This is my current setup that's working:

In my /etc/nginx/conf/nginx.conf inside the server {} block listening on port 433 (ssl):

location /faye {
  proxy_set_header  X-Real-IP  $remote_addr;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect off;

  root /var/applications/current/faye;
  proxy_pass http://127.0.0.1:4001; # im running faye on port 4001
  break;
}

Here I basically use my main domain, but add a location /faye {} to catch incoming requests starting with /faye and I proxy-pass them to my Faye Thin instance.

Next the config/private_pub.yml file:

server: "http://123.45.67.89:4001/faye"
secret_token: "my_secret_token"

Here I specify the IP address (on port 4001 / faye) directly, so it won't go through NGINX. Notice I am using HTTP and not HTTPS here. This is mainly because PrivatePub currently cannot do POST requests with SSL, so we submit post requests via the regular http protocol.

However, this means that the faye.js file will be fetch over HTTP, and the Faye Browser Client will also connect via HTTP to the Faye server. This is what's causing browsers like Chrome to throw a warning in the address bar. Not so elegant. So I opened up the private_pub.js file and changes the urls to the js file and the faye server:

// script.src = self.subscriptions.server + ".js";
script.src = 'https://mydomain.com/faye.js'

and

// self.fayeClient = new Faye.Client(self.subscriptions.server);
self.fayeClient = new Faye.Client("https://mydomain.com/faye");

Now they connect over HTTPS instead of HTTP (as defined in the private_pub.yml) while the POST requests happen from the Ruby app through regular HTTP.

This works fine at the moment for me, but I believe PrivatePub should support HTTPS POST requests as well since it's common that people will be using HTTPS for their apps. I've attempted to get that working, but have had no success yet.

Let me know what you think!

ryanb commented 13 years ago

Thanks for reporting this issue. I agree it would be great if HTTPS were supported. The protocol should probably be stripped out and use whichever one the browser is using when fetching the faye.js file and connecting to the faye server.

It should also support https in the internal post request so you can specify it in the server config.

mrrooijen commented 13 years ago

Definitely. I haven't figured out how to get HTTPS working. Googled around for solutions but it all seems a bit vague to me. Maybe you know whats up. An easy way to determine whether it's HTTPS would be when parsing the URI:

uri = URI.parse("https://mydomain.com/faye")
if uri.scheme == "https"
  # enable ssl
end

I believe this would also work:

uri = URI.parse("https://mydomain.com/faye")
if uri.port == 443
  # enable ssl
end

Something along those lines. You could also use uri.port which assumably would return 443. Though even with that I wasn't able to figure out how to make the net/http or net/https libraries submit a proper post request over https/ssl. Faye itself with PrivatePub (the browser/client) properly connect to the Faye server over HTTPS, that's no problem.

Let me know if you find anything. :)

BinaryMuse commented 13 years ago

What do you think of a change like BinaryMuse@fbd0209827c5069d5b9941ec483c74bfc09af276? I haven't tested it with an actual SSL server yet--any feedback is appreciated.

ryanb commented 13 years ago

@BinaryMuse that looks good, test it out and submit a pull request if it's working for you. Thanks!

mrrooijen commented 13 years ago

Looks similar to what I tried, but I couldn't get it to work when I tried.

Any luck on your end @BinaryMuse? This is quite an important commit if it works.

mrrooijen commented 13 years ago

Oh, I think one of the issues I faced was the fact that you need to enable SSL with Thin:

thin start -e production -p 4000 --ssl

One problem is that when you browse to that page, you get an "SSL not-verified" warning which messes with the POST request. You may want to try:

http = Net::HTTP.new(‘secure.somehost.com’, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = http.get(“/secured/page”)

Notice the http.verify_mode = OpenSSL:SSL::VERIFY_NONE which basically ignores verifications and should just do it. You probably want to give that a try if your current implementation isn't working.

jpawlowski commented 11 years ago

I can also recommend using pound as a reverse proxy: http://www.apsis.ch/pound

Obviously this is also working for SSL traffic transparently.

manoj2411 commented 11 years ago

I don't know how to do it with apache2. I just followed the guide that is given on readme. I created a config/private_pub_thin.yml which has

---
port: 4443
ssl: true
ssl_key_file:  /certs_path/sub.class1.server.ca.pem
ssl_cert_file: /certs_path/ca.pem
environment: production
rackup: private_pub.ru

when I run

RAILS_ENV=production bundle exec thin -C config/private_pub_thin.yml start

I get

>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4443, CTRL+C to stop

which seems fine I think. My config/private_pub.yml has

development:
  server: "http://localhost:9292/faye"
  secret_token: "secret"
test:
  server: "http://localhost:9292/faye"
  secret_token: "secret"
production:
  server: "https://interakt.co/faye"
  secret_token: "51e53bf7dc372a865b68083d9641f8871eea859e182212e36127b701bb8c6303"
  signature_expiration: 3600 # one hour

When I try https://interakt.co:4443/faye.js then it just keeps loading and doesn't load anything.

I don't know what wrong I am doing. Please help

gregmolnar commented 11 years ago

The current version of private pub won't play nicely with https unfortunately. Ryan seems to have a time off from development so the project is a bit abandoned. I will try to contact him and ask him his plans about private_pub.

manoj2411 commented 11 years ago

@gregmolnar Thanks a lot. Do you have any clue about the last stable version that works smoothly with https?

gregmolnar commented 11 years ago

You can give a try to this fork at the ssl branch https://github.com/BinaryMuse/private_pub/tree/ssl. I had a quick look and it should work ok.

manoj2411 commented 11 years ago

Its not compatible with rails 3.2 I guess because it is giving error when I tried rails g private_pub:install

WARNING: Nokogiri was built against LibXML version 2.8.0, but has dynamically loaded 2.7.8
      remove  config/initializers/private_pub.rb
      remove  app/helpers/private_pub_helper.rb
(erb):9:in `template': uninitialized constant ActiveSupport::SecureRandom (NameError)
    from /Users/manoj/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/erb.rb:838:in `eval'
    from /Users/manoj/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/erb.rb:838:in `result'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/file_manipulation.rb:117:in `block in template'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/create_file.rb:54:in `call'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/create_file.rb:54:in `render'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/create_file.rb:47:in `identical?'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/create_file.rb:73:in `on_conflict_behavior'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/empty_directory.rb:114:in `invoke_with_conflict_check'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/create_file.rb:61:in `invoke!'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions.rb:95:in `action'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/create_file.rb:26:in `create_file'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/actions/file_manipulation.rb:116:in `template'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/bundler/gems/private_pub-fbd0209827c5/lib/generators/private_pub/install_generator.rb:11:in `copy_files'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/command.rb:27:in `run'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/invocation.rb:127:in `block in invoke_all'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/invocation.rb:127:in `each'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/invocation.rb:127:in `map'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/invocation.rb:127:in `invoke_all'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/group.rb:233:in `dispatch'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/railties-3.2.14/lib/rails/generators.rb:171:in `invoke'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/railties-3.2.14/lib/rails/commands/generate.rb:12:in `<top (required)>'
    from /Users/manoj/.rvm/gems/ruby-1.9.3-p448@intercom.com/gems/railties-3.2.14/lib/rails/commands.rb:29:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

Module SecureRandom is directly accessible in rails 3.2

gregmolnar commented 11 years ago

It should pick it up if directly accessible: https://github.com/ryanb/private_pub/blob/master/lib/generators/private_pub/templates/private_pub.yml#L9 Not sure why it doesn't work for you. What do you get in rails console for defined?(SecureRandom) ?

manoj2411 commented 11 years ago

You are right but I was using ssl branch of https://github.com/BinaryMuse/private_pub/tree/ssl because I was having issue with ssl https://github.com/BinaryMuse/private_pub/blob/ssl/lib/generators/private_pub/templates/private_pub.yml

gregmolnar commented 11 years ago

I see. That fork made before the refactor. The quickest route for now is to skip the use of the generator and just create the config file by hand.

manoj2411 commented 11 years ago

I having this issue with http too, I think first it is the problem of apache2 then https comes into picture I guess. Any idea about apache2 configuration?

gregmolnar commented 11 years ago

You should setup apache to forward domain.tld/faye request to the port you are starting thin on. I am not using apache for a long time so not sure how to set that up but I am sure you find a lot of help if you google apache proxy pass.

gregmolnar commented 11 years ago

Ok, I just had some time to look into this and realized that Ryan already added the https support. At the bottom of the readme (https://github.com/ryanb/private_pub/commit/41a614c3b7b2bf8cd8e3e855b628e13a52f0428f) an example of how to set it up. The actual PR: https://github.com/ryanb/private_pub/commit/914871a67eca1b787ef72d05e6257c2131ba6111 This ticket should be closed.

chrise86 commented 10 years ago

@manoj2411 your config is wrong I think:

production:
  server: "https://interakt.co/faye"

Should be:

production:
  server: "https://interakt.co:4443/faye"

I'm having a problem where I can access faye.js, but when trying to publish_to I get:

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

gregmolnar commented 10 years ago

@chrise86 Is you certificate working in a browser? It looks like it is more of a certificate issue than anything with private_pub

chrise86 commented 10 years ago

@gregmolnar yep, the SSL is working on the site, green https :(

My private_pub_thin.yml:

---
port: 4443
ssl: true
pid: tmp/pids/faye.pid
# daemonize: true
ssl_key_file: certs/<file name>.key
ssl_cert_file: certs/<file name>.crt
environment: production
rackup: private_pub.ru
gregmolnar commented 10 years ago

This looks good to me. I will do some tests and will come back to you.

chrise86 commented 10 years ago

@gregmolnar thanks Greg. I have no idea what it could be. I have noticed however, when ssh'ing into the server and running thin -C config/private_pub_thin.yml start without the daemonized option, and then using PrivatePub.publish_to in the console, that the thin server returns <SSL_incomp>

Beatgodes commented 10 years ago

Any news on this? I'm having the same problem

rbcs commented 9 years ago

I am getting the same issue. I have also followed all steps but not getting result. Is anyone have idea ?

balla121 commented 9 years ago

hey guys, i got my private pub to work over https... anyone that is still struggling with this, I just ignored the port in the private_pub.yml file for both my app and the faye server and it worked fine!

rbcs commented 9 years ago

Hey guys, i have solved the issue by adding ca-bundle files's content into .crt files.

cfonseca-dev commented 8 years ago

@meskyanichi Oh man! Thanks for your comments! Your method is the only one that worked for me!

carlosc77 commented 8 years ago

hello private_pub only run on localhost and with server in other terminal or this can run on a hosting real that not be heroku and without other terminal?