私は、RubyでSSL対応のサーバーを作成し、サーバーで使用する対応するRubyクライアントを作成しています。テストするために、私は自分のルートCA証明書を次のコマンドで作成しました。私は、私が作成したSSL証明書を使用するには、単純なSSL対応のサーバーを作成し、その後このRuby SSL対応のサーバー/クライアントテストはなぜ機能していますか?
$:~/devel/ssl-test/ssl/keys$ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
.+++
............................................+++
e is 65537 (0x10001)
$:~/devel/ssl-test/ssl/keys$ cd ../csrs/
$:~/devel/ssl-test/ssl/csrs$ openssl req -new -key ../keys/server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:my.secure.test
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
$:~/devel/ssl-test/ssl/csrs$ cd ../certs/
$:~/devel/ssl-test/ssl/certs$ openssl ca -in ../csrs/server.csr -cert ../CA/TestCA.crt -keyfile ../CA/TestCA.key -out server.crt
Using configuration from /usr/lib/ssl/openssl.cnf
I am unable to access the ./demoCA/newcerts directory
./demoCA/newcerts: No such file or directory
$:~/devel/ssl-test/ssl/certs$ mkdir -p demoCA/newcerts
$:~/devel/ssl-test/ssl/certs$ touch demoCA/index.txt
$:~/devel/ssl-test/ssl/certs$ echo "01" > demoCA/serial
$:~/devel/ssl-test/ssl/certs$ openssl ca -in ../csrs/server.csr -cert ../CA/TestCA.crt -keyfile ../CA/TestCA.key -out server.crt
Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Oct 25 16:25:05 2011 GMT
Not After : Oct 24 16:25:05 2012 GMT
Subject:
countryName = AU
stateOrProvinceName = Some-State
organizationName = Internet Widgits Pty Ltd
commonName = my.secure.test
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
48:50:B5:04:11:02:F1:40:97:58:BF:5F:8B:27:50:10:C0:3F:EE:D9
X509v3 Authority Key Identifier:
DirName:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
serial:81:44:16:06:5C:EB:5E:71
Certificate is to be certified until Oct 24 16:25:05 2012 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
:
$:~/devel/ssl-test/ssl/CA$ openssl genrsa -out TestCA.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
...........................+++
e is 65537 (0x10001)
$:~/devel/ssl-test/ssl/CA$ openssl req -new -key TestCA.key -out TestCA.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
$:~/devel/ssl-test/ssl/CA$ openssl x509 -req -days 365 -in TestCA.csr -out TestCA.crt -signkey TestCA.key
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
Getting Private key
私はその後、私のサーバーのSSL証明書を生成しました。
require 'socket'
require 'openssl'
require 'thread'
server = TCPServer.new(1337)
context = OpenSSL::SSL::SSLContext.new
context.cert = OpenSSL::X509::Certificate.new(File.open('ssl/certs/server.crt'))
context.key = OpenSSL::PKey::RSA.new(File.open('ssl/keys/server.key'))
secure = OpenSSL::SSL::SSLServer.new(server, context)
puts 'Listening securely on port 1337...'
loop do
Thread.new(secure.accept) do |conn|
begin
while request = conn.gets
$stdout.puts '=> ' + request
response = "You said: #{request}"
$stdout.puts '<= ' + response
conn.puts response
end
rescue
$stderr.puts $!
end
end
end
始めたとき、私はその後、ちょうどそれは接続を拒否されたことを確認するために、非SSL対応のクライアントを作成し
$:~/devel/ssl-test$ ruby server.rb
Listening securely on port 1337...
...正常に動作するようです。
require 'socket'
require 'thread'
client = TCPSocket.new('127.0.0.1', 1337)
Thread.new do
begin
while response = client.gets
$stdout.puts response
end
rescue
$stderr.puts "Error from client: #{$!}"
end
end
while request = $stdin.gets
request = request.chomp
client.puts request
end
私は次を経由して、これを実行すると:
$:~/devel/ssl-test$ ruby client.rb
hello
Error from client: Connection reset by peer
対応して、私は、サーバーから、次を得る:
$:~/devel/ssl-test$ ruby server.rb
Listening securely on port 1337...
/usr/local/rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/openssl/ssl-internal.rb:164:in `accept': SSL_accept returned=1 errno=0 state=SSLv2/v3 read client hello A: unknown protocol (OpenSSL::SSL::SSLError)
from /usr/local/rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/openssl/ssl-internal.rb:164:in `accept'
from server.rb:16:in `block in <main>'
from server.rb:15:in `loop'
from server.rb:15:in `<main>'
これは、すべての期待されました。次に、SSLコンテキストを使用するようにクライアントコードを変更しました。
require 'socket'
require 'openssl'
require 'thread'
client = TCPSocket.new('127.0.0.1', 1337)
context = OpenSSL::SSL::SSLContext.new
secure = OpenSSL::SSL::SSLSocket.new(client, context)
secure.sync_close = true
secure.connect
Thread.new do
begin
while response = secure.gets
$stdout.puts response
end
rescue
$stderr.puts "Error from client: #{$!}"
end
end
while request = $stdin.gets
request = request.chomp
secure.puts request
end
私は完全にこれはハンドシェイクプロセス中にも失敗すると予想、それは...私は、次の結果得ませんでした。この作品はなかった理由
$:~/devel/ssl-test$ ruby client.rb
hello
You Said: hello
を?クライアントがサーバーSSL証明書を作成して署名したルートCAについて考えていないと思ってサーバーの証明書を確認できないため、失敗すると想定していました。私は何が欠けていますか?サーバーの証明書を作成して署名し、それが「コミット」されたとき、これは何とかOpenSSLライブラリで利用できるようにしましたか?私は何らかの理由でクライアントのSSLコンテキストを伝えて、テスト目的のために作成したルートCAをどこで探すべきかを期待する必要がありました...
フォローアップテストとして、別のマシンにクライアントコードをコピーしましたこのテスト用に作成したルートCAについては何も分かっていないし、クライアントが接続しているIPアドレスを変更してテストを再実行した。このテストでも同じ結果が得られました。クライアントは、それができないと仮定したときにサーバーと通信できました。何か案は?
ああ、そのトリックでした。ありがとうイアン!今、サーバーの証明書を検証できるように自分のカスタムルートCAを探す場所についてクライアントのSSLコンテキストに通知するにはどうすればよいですか? – Bryan
奇妙なことに、http://rubydoc.info/stdlib/openssl/1.9.2/OpenSSL/SSL/SSLContext#DEFAULT_PARAMS-constant VERIFY_PEERはデフォルトのパラメータにする必要がありますが、デフォルトが正しく適用されていないようです。 –
@Bryan 'SSLContext'オブジェクトの' ca_file'または 'ca_path'のいずれかの設定を使いたいでしょう。 'ca_file'は、.pemファイルにポイントするか、何を持っているかのように、おそらく最も簡単です。 'ca_path'はopensslによって適切にハッシュされたディレクトリを必要とします。私はしばらくそれをしていないが、私はそれにリンクを掘ることができるかどうかがわかります。 –