Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SSL with Puma, HTTP parse error, malformed request

Attempting to configure Puma with HTTPS for a rails application being served in a private network on a remote server. Puma Docs make it look like it is possible, and they provide this command:

puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'

Steps taken (for testing purposes):

Generate private key and self-signed certificate

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/puma_test.key -out /etc/zzz_puma_test.crt


Boot up Puma

rvmsudo rails s -p 443 -b 'ssl://127.0.0.1?key=/etc/puma_test.key&cert=/etc/zzz_puma_test.crt'


When I boot up the server, in the logs I see this which I think is odd: Listening on tcp://0.0.0.0:443 It is like Puma is still booting up in http as opposed to https. Here is terminal logs in its entirety when booting up puma:

=> Booting Puma
=> Rails 4.2.8 application starting in development on http://ssl://127.0.0.1?key=/etc/puma_test.key&cert=/etc/zzz_puma_test.crt:443
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Puma starting in single mode...
* Version 3.12.0 (ruby 2.3.3-p222), codename: Llamas in Pajamas
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:443

When I attempt to access the site, I get this error in terminal:

HTTP parse error, malformed request (): #Puma::HttpParserError: Invalid HTTP format, parsing fails.

In the firefox browser itself, it provides this feedback:

SSL received a record that exceeded the maximum permissible length. Error code: SSL_ERROR_RX_RECORD_TOO_LONG

What is odd is that I do the exact steps above locally on my computer, for an app being served locally on my computer, and it all works fine.

  • I created a new app
  • Ran the above line to generate the secret key and the self-signed certificate
  • Ran the above line to boot up the server
  • In terminal when the server is booted up, it shows it is listening properly (in other words: never mentions http): Listening on ssl://127.0.0.1:443?key...cert...
  • Connecting to https://localhost/blogs works just fine.

Perhaps it has something to do with the fact that I am using linux machine as opposed to my mac? Or, perhaps it is that my testing app lives on a remote server in my network? I looked at the method that generates this error. It is parse_error, line 95 of events.rb.

Resources already looked at:

  • SO Post
  • GithubGist
  • Open Issue, closed issue,

I have tried tweaking the rails s command above with a number of different small changes:

  • changed IP from 127.0.0.1 to 0.0.0.0
  • do not specify the -p 443 option
  • specify the actual, internal IP address instead of 127.0.0.1 (this is being served on an internal network)

I have also tried deleting my browsing history, and tried accessing the site from multiple browsers.

Any help is appreciated, thanks!

like image 842
Neil Avatar asked Sep 11 '25 20:09

Neil


2 Answers

Here is the solution that finally worked for me:

First I had to create a puma config file with the ssl_bind directive:

# /<path_to_app>/puma/development.rb
ssl_bind '127.0.0.1', '9292', {
   cert: ‘/etc/puma_test.key',
   key: ‘/etc/zzz_puma_test.crt'
}

Then I had to boot up the server with puma as opposed to rails s. For whatever reason, I just could not get rails s to work. In the command to boot up puma, I had to make sure to specify -C and the path to the puma config file:

rvmsudo puma -b 'ssl://0.0.0.0:443?key=/etc/puma_test.key&cert=/etc/zzz_puma_test.crt' -C /<path_to_app>/puma/development.rb
like image 197
Neil Avatar answered Sep 14 '25 10:09

Neil


I built a fresh VM with Ubuntu 16.04.5 LTS server (HWE kernel), installed RVM, Ruby 2.3.3, and Rails 4.2.8, followed your repro instructions, and... it works great. I used 0.0.0.0 as the listening address and accessed the guest's address from the host machine.

Guest:
mwp@ubuntu:~/Code/blag$ export rvmsudo_secure_path=1
mwp@ubuntu:~/Code/blag$ rvmsudo rails s -p 443 -b 'ssl://0.0.0.0?key=/etc/puma_test.key&cert=/etc/zzz_puma_test.crt'
=> Booting Puma
=> Rails 4.2.8 application starting in development on http://ssl://0.0.0.0?key=/etc/puma_test.key&cert=/etc/zzz_puma_test.crt:443
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Puma starting in single mode...
* Version 3.12.0 (ruby 2.3.3-p222), codename: Llamas in Pajamas
* Min threads: 0, max threads: 16
* Environment: development
* Listening on ssl://0.0.0.0:443?key=/etc/puma_test.key&cert=/etc/zzz_puma_test.crt
Use Ctrl-C to stop
Host:
mwp@macos:~$ curl -Ik https://192.168.10.137
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
ETag: W/"b56dd5f9363ed0f7bd4d11c36d9471dd"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 555223a6-3f70-49cf-8b30-92d3047ff8a6
X-Runtime: 0.009792
Guest:
Started HEAD "/" for 192.168.10.112 at 2019-02-28 15:39:19 -0600
Cannot render console from 192.168.10.112! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by Rails::WelcomeController#index as */*
  Rendered /home/mwp/.rvm/gems/ruby-2.3.3/gems/railties-4.2.8/lib/rails/templates/rails/welcome/index.html.erb (0.6ms)
Completed 200 OK in 5ms (Views: 4.4ms | ActiveRecord: 0.0ms)

So clearly something else is missing here: some configuration on your server, some Gem in your Gemfile, or some configuration in your Rails project.

like image 31
mwp Avatar answered Sep 14 '25 12:09

mwp