6

最初にプレーンテキストで通信する必要がある場合、Ruby で SSL を使用してソケットを保護するにはどうすればよいですか?

OpenSSL::SSL::SSLServer最初に SSL 接続を要求するのはクライアントの責任であるため、使用できません

簡単に言うと、クライアントがキーワード「STARTTLS」を送信し、SSL 接続が作成される RFC3207 を実装しようとしています。

私の質問は、「サーバーが '220 OK' を送信した後、SSL 接続を作成するにはどうすればよいですか?」です。

OpenSSL::SSL::SSLSocketクライアント側で使えることはわかっているが、サーバー側で何をすればいいのかわからない

Ruby 以外の言語でこれを行う方法を知っている場合は、コードを投稿してください。翻訳します。私はこれに約 8 時間取り組んでおり、入手できるすべてのものが必要です。

#ruby-lang で質問しましたが、役に立たず、サーバーとクライアントで同時に Socket オブジェクトを SSLSockets にラップしようとしましたが、それも機能しません

要するに、私は非常に立ち往生しています。私が得ることができるすべての助けが必要です

4

3 に答える 3

3

この要点は、最小限の TLS サーバーをセットアップする方法を説明するために作成しました。トランクの新機能を説明するために、行 62 ~ 67 を省略してもかまいません。

しかし、それ以外は、完全に機能する TLS サーバーであり、さらに機能を追加するために構築することができます。

真剣に使用したい場合は、サーバー証明書の 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
于 2012-06-17T14:52:51.347 に答える
3

SSL サーバーをプレーン テキスト モードで起動するには、SSLServer の start_immediately フィールドを false に設定する必要があります。いつでも (つまり、クライアントから 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 パッケージ (debian/ubuntu の gnutls-bin) のユーティリティを使用して starttls をテストしています。これにより、いつでもハンドシェイクを開始できるからです。

$ gnutls-cli --starttls --port 9002 --insecure localhost

これは、プレーン テキストの TCP ソケット モードで接続します。いくつかの行を入力して、それらをエコーし​​ます。このトラフィックは暗号化されていません。を送信するSTARTTLSと、sslSocket.acceptが呼び出され、サーバーは SSL ハンドシェイクを待機します。ctrl-d (EOF) を押して gnutls クライアントからハンドシェイクを開始し、暗号化された SSL 接続が確立されるのを確認します。後続の行も同様にエコーされますが、トラフィックは暗号化されています。

于 2012-05-06T20:55:03.753 に答える
0

私はこれについていくらか前進し、将来の使用のために保存しました:

  • はい、両端で OpenSSL::SSL::SSLSocket を使用する必要があります
  • サーバー側では、OpenSSL::SSL::SSLContext オブジェクトを作成し、使用したいプロトコルと末尾に「_server」を追加したシンボルを渡します。OpenSSL::SSL::SSLContext::METHODS を参照してください。つまり、要するに、RFC3207 に「:TLSv1_server」を使用する必要さえありません。サーバー側では、証明書を使用してコンテキストを作成し、ソケットで #accept を呼び出して、クライアントの転送を待ちます。
  • SSL 証明書を ctx オブジェクトに渡します

自由に編集してください

于 2012-04-21T22:43:42.417 に答える