ruby - 尝试通过 SSL 创建一个简单的 Ruby 服务器

标签 ruby openssl client-server

我正在尝试用 Ruby 创建一个简单的 SSL 客户端和服务器。但是我收到了一条神秘的错误消息,文档也没有帮助。

这是我的服务器代码:

#!/usr/bin/ruby

require "gserver"
require "openssl"

listeningPort = Integer(ARGV[0])

class Server < GServer
  def initialize(listeningPort)
    @sslContext = OpenSSL::SSL::SSLContext.new
    @sslContext.cert = OpenSSL::X509::Certificate.new(File.open("MyCert.pem"))
    super(listeningPort, "0.0.0.0")
  end
  def serve(io)
    begin
      ssl = OpenSSL::SSL::SSLSocket.new(io, @sslContext)
      ssl.sync_close = true
      ssl.connect
      while (lineIn = ssl.gets)
        lineIn = lineIn.chomp
        $stdout.puts "=> " + lineIn
        lineOut = "You said: " + lineIn
        $stdout.puts "<= " + lineOut
        ssl.puts lineOut
      end
    rescue
      $stderr.puts $!
    end
  end
end

server = Server.new(listeningPort)
server.start
server.join

客户端代码类似:

#!/usr/bin/ruby

require "socket"
require "thread"
require "openssl"

host = ARGV[0]
port = Integer(ARGV[1])

socket = TCPSocket.new(host, port)
sslContext = OpenSSL::SSL::SSLContext.new
sslContext.cert = OpenSSL::X509::Certificate.new(File.open("MyCert.pem"))
ssl = OpenSSL::SSL::SSLSocket.new(socket, sslContext)
ssl.sync_close = true
ssl.connect
puts ssl.peer_cert   # this is nil

Thread.new {
  begin
    while lineIn = ssl.gets
      lineIn = lineIn.chomp
      $stdout.puts lineIn
    end
  rescue
    $stderr.puts "Error in input loop: " + $!
  end
}

while (lineOut = $stdin.gets)
  lineOut = lineOut.chomp
  ssl.puts lineOut
end

当我连接时,我在服务器和客户端上都收到了这个错误:

in `connect': SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol (OpenSSL::SSL::SSLError)

问题可能是它不信任证书(自签名)。我不确定如何告诉客户信任该证书。上面,我已经将服务器的证书放在上下文中,但这只是在黑暗中拍摄。我什至不确定我的证书是可接受的格式(它是 base64,文件中有证书和私钥)。文档非常少,网络上似乎也没有太多这方面的内容。

有什么想法吗?

最佳答案

我想通了,多亏了一些不错的文档的链接。

一方面,SSLSocket.connect() 只能在客户端调用。

但主要问题是我正在尝试使用 GServer 套接字并将其升级到 SSL。相反,我应该使用 OpenSSL::SSL::SSLServer。

此外,我将我的证书和私钥分成两个文件。

这是工作服务器:

#!/usr/bin/ruby

require "socket"
require "openssl"
require "thread"

listeningPort = Integer(ARGV[0])

server = TCPServer.new(listeningPort)
sslContext = OpenSSL::SSL::SSLContext.new
sslContext.cert = OpenSSL::X509::Certificate.new(File.open("cert.pem"))
sslContext.key = OpenSSL::PKey::RSA.new(File.open("priv.pem"))
sslServer = OpenSSL::SSL::SSLServer.new(server, sslContext)

puts "Listening on port #{listeningPort}"

loop do
  connection = sslServer.accept
  Thread.new {
    begin
      while (lineIn = connection.gets)
        lineIn = lineIn.chomp
        $stdout.puts "=> " + lineIn
        lineOut = "You said: " + lineIn
        $stdout.puts "<= " + lineOut
        connection.puts lineOut
      end
    rescue
      $stderr.puts $!
    end
  }
end

和客户:

#!/usr/bin/ruby

require "socket"
require "thread"
require "openssl"

host = ARGV[0]
port = Integer(ARGV[1])

socket = TCPSocket.new(host, port)
expectedCert = OpenSSL::X509::Certificate.new(File.open("cert.pem"))
ssl = OpenSSL::SSL::SSLSocket.new(socket)
ssl.sync_close = true
ssl.connect
if ssl.peer_cert.to_s != expectedCert.to_s
  stderrr.puts "Unexpected certificate"
  exit(1)
end

Thread.new {
  begin
    while lineIn = ssl.gets
      lineIn = lineIn.chomp
      $stdout.puts lineIn
    end
  rescue
    $stderr.puts "Error in input loop: " + $!
  end
}

while (lineOut = $stdin.gets)
  lineOut = lineOut.chomp
  ssl.puts lineOut
end

关于ruby - 尝试通过 SSL 创建一个简单的 Ruby 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5872843/

相关文章:

ruby - 以 CSV 格式导出 SQLite3 表的内容

ruby-on-rails - 遇到 :dependent => :destroy and Instance variables 问题

ssl - TCP/IP 套接字无法与 TLSv1_2_client_method() 建立安全连接

c - 使用 Visual Studio 和 Openssl 进行 AES 256 CTR 加密/解密

node.js - 使用 Node.js 将 RESTful 服务与主要网站架构分离

linux - 如何在 PF_UNIX 套接字的服务器端打印客户端 sun_paths 名称?

ruby-on-rails - 如何在 Rails 3 的功能测试中使用 polymorphic_path

ruby - 在 Mechanize 中查找没有名称的字段

java - RSA_verify 中预期的数据类型是什么,无法验证从 Java 生成的签名

ios - 创建 iOS 客户端服务器应用程序。 ASIFormDataRequest 问题