如果需要先通过纯文本进行通信,如何在Ruby中使用SSL保护套接字?
我无法使用OpenSSL::SSL::SSLServer
,因为首先请求SSL连接是客户的责任
总而言之,我试图实现RFC3207,客户端发送关键字“STARTTLS”,然后创建SSL连接。
我的问题是“如何在服务器发送'220 OK'后创建SSL连接?”
我知道我可以在客户端使用OpenSSL::SSL::SSLSocket
,但我不知道在服务器端要做什么
如果您知道如何使用Ruby以外的其他语言进行此操作,只需发布代码并将其翻译,我已经在这方面工作了大约8个小时,我需要我能得到的一切
我已经在#ruby-lang中询问了,但是无济于事,我已经尝试在服务器和客户端的SSLSockets中同时包装Socket对象,但这不起作用
简而言之,我非常困难,我需要得到所有帮助
答案 0 :(得分:3)
您必须将SSLServer的start_immediately字段设置为false才能以纯文本模式启动SSL服务器。在任何时候(即,当您从客户端收到STARTTLS命令时),您可以调用SSLSocket的accept方法来启动SSL / TLS握手。客户当然必须同意协议:)
这是我编写的测试服务器的示例服务器:
#!/usr/bin/ruby
require 'socket';
require 'openssl';
certfile = 'mycert.pem';
port = 9002;
server = TCPServer.new( port );
# Establish an SSL context
sslContext = OpenSSL::SSL::SSLContext.new
sslContext.cert = OpenSSL::X509::Certificate.new( File.open( certfile ) );
sslContext.key = OpenSSL::PKey::RSA.new( File.open( certfile ) );
# Create SSL server
sslServer = OpenSSL::SSL::SSLServer.new( server, sslContext );
# Don't expect an immidate SSL handshake upon connection.
sslServer.start_immediately = false;
sslSocket = sslServer.accept;
sslSocket.puts( "Toast.." );
# Server loop
while line = sslSocket.gets
line.chomp!;
if "STARTTLS" == line
# Starting TLS
sslSocket.accept;
end
sslSocket.puts( "Got '#{line}'" );
end
sslSocket.close;
我确信原始海报知道如何测试STARTTLS,但我们其他人可能需要这个提醒。实际上我通常使用GNUTLS包中的utils(debian / ubuntu中的gnutls-bin)来测试starttls,因为它允许我随时启动握手:
$ gnutls-cli --starttls --port 9002 --insecure localhost
这以纯文本TCP套接字模式连接。键入一些行并让它们回显。此流量未加密。如果发送STARTTLS
,则调用sslSocket.accept
,服务器等待SSL握手。按ctrl-d(EOF)从gnutls客户端开始握手,并观察它建立加密的SSL连接。后续行也将被回显,但流量现在已加密。
答案 1 :(得分:3)
我创建了这个gist来说明如何设置最小的TLS服务器。您可能希望省略第62-67行,这是为了说明主干上的新功能。
但除此之外,它是一个完全正常工作的TLS服务器,您可以在其上构建以添加更多功能。
如果您想认真使用服务器证书的CN,可能还需要将服务器证书的CN从“localhost”更改为真实域:)
您可能会注意到,工作的最大部分实际上是正确设置PKI方面。核心服务器部分是:
ctx = OpenSSL::SSL::SSLContext.new
ctx.cert = ... # the server certificate
ctx.key = ... # the key associated with this certificate
ctx.ssl_version = :SSLv23
tcps = TCPServer.new('127.0.0.1', 8443)
ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
ssls.start_immediately = true
begin
loop do
ssl = ssls.accept
puts "Connected"
begin
while line = ssl.gets
puts "Client says: #{line}"
ssl.write(line) # simple echo, do something more useful here
end
ensure
ssl.close
end
end
ensure
tcps.close if tcps
end
答案 2 :(得分:0)
我已经取得了一些进展,保存以备将来使用:
随意编辑