How to Establish a Ssl Enabled Tcp/Ip Connection in Ruby

How to establish a SSL enabled TCP/IP Connection in Ruby

require 'socket'
require 'openssl'

myXML = 'my_sample_data'
host = 'my_host.com'
port = my_port

socket = TCPSocket.open(host,port)
ssl_context = OpenSSL::SSL::SSLContext.new()
ssl_context.cert = OpenSSL::X509::Certificate.new(File.open("certificate.crt"))
ssl_context.key = OpenSSL::PKey::RSA.new(File.open("certificate.key"))
ssl_context.ssl_version = :SSLv23
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
ssl_socket.sync_close = true
ssl_socket.connect

ssl_socket.puts(myXML)
while line = ssl_socket.gets
p line
end
ssl_socket.close

TCPSocket connection reset by peer

First thing, you should replace the string '443' by an integer :

TCPSocket.open('stream-api.betfair.com', 443)

Anyway, it seems to be related with the SSL negociation : the following Stackoverflow post gives a quick idea about what would work : How to establish a SSL enabled TCP/IP Connection in Ruby. Using this method, I works.

require 'socket'
require 'openssl'

host = 'stream-api.betfair.com'
port = 443

socket = TCPSocket.open(host,port)
ssl_context = OpenSSL::SSL::SSLContext.new()
ssl_context.ssl_version = :SSLv23
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
ssl_socket.sync_close = true
ssl_socket.connect
while line = ssl_socket.gets
p line
end
ssl_socket.close

Result :

"{\"op\":\"connection\",\"connectionId\":\"001-151118094105-259478\"}\r\n"

Dealing with SSL/TLS protected connection is sometime quite verbose with Ruby. In the example you gave, in NodeJS, the hint is the first line :

var tls = require('tls');

Why is this Ruby SSL-enabled server/client test working?

Depending on the version of Ruby you are using, the default verify mode for the SSLContext object may not be enforcing certificate verification. You can force the verify mode with:

context = OpenSSL::SSL::SSLContext.new
context.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT

This should cause the client's connection attempt to fail, as expected.

How to make a secure HTTP/2 connection to Ruby server with Chrome and Firefox?

It seems that Chrome insists on using ephemeral ECDH key exchange for HTTP/2, and to get that to work you need to set tmp_ecdh_callback:

ctx.tmp_ecdh_callback = lambda do |*args|
OpenSSL::PKey::EC.new 'prime256v1'
end

I’ve based this on the example code from the Ruby http-2 gem, which I think is where you’ve got your code from too. Note that in that code it uses lambda do |_args|, (with the underscore but no *) and this causes problems because the number of args is wrong and lambda is strict about passing the right number, so you get errors. I’ve changed it back to the original *args here, it appears to have been changed to fix Rubocop warnings. As you seem to be active in that repo, you might want to change it to something like |*_args|.

Socket timeout in Ruby

I have tested and my ISP has something to do with the time limitation issues of my longer connections.

Why isn't my Sinatra app working with SSL?

Generally you don't want any ruby webservers actually handling SSL. You make them serve plain HTTP (that is accessible only via localhost). Then you install a reverse proxy that handles all of the SSL communicate.

For example

  1. Install nginx (reverse proxy) and configure it to listen on port 443.
  2. Set your
    ruby app server to listen on port 127.0.0.1:80 (accept local
    connections only)
  3. All requests hit nginx, which strips the SSL,
    and send the plain HTTP request to your ruby webserver.

A very simple nginx config to get you started:

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/your.key;
ssl on;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";

server {
listen 443 ssl;
server_name you.example.com;

location / {
proxy_pass http://localhost:8080; # your ruby appserver
}
}

Using Net::HTTP.get for an https url

Original answer:

uri = URI.parse("https://example.com/some/path")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
@data = http.get(uri.request_uri)

As pointed out in the comments, this is more elegant:

require "open-uri"
@data = URI.parse("https://example.com/some/path").read

Ruby HTTP2 GET request

Public servers like google.com do not support HTTP/2 in clear text.

You are trying to connect to http://google.com, while you should really connect to https://google.com (note the https scheme).

In order to do that, you may need to wrap the TCP socket using TLS (see for example here), if http-2 does not do it for you.

Note also that HTTP/2 requires strong TLS ciphers and ALPN, so make sure that you have an updated version of OpenSSL (at least 1.0.2).

Given that the author of http-2 is a strong HTTP/2 supporter, I am guessing that your only problem is the fact that you tried clear-text http rather than https, and I expect that TLS cipher strength and ALPN are taken care of by the http-2 library.



Related Topics



Leave a reply



Submit