問題在年底制訂的問題,我已經測試答案瀏覽器請求與IO ::插座:: SSL
我正在寫一些代碼來展示一些基本的原則,以先詳細說明其他。代碼將永遠不會有生產力,並且打算簡化。
我的目標(從別人開始)是編寫一個簡單的應用程序,使用Web-Certificat加密其網絡流量。
的出發點是一個應用程序,它不不加密:
#!/usr/bin/env perl
use strict;
use warnings;
use IO::Socket::INET;
# auto-flush on socket
$| = 1;
# creating a listening socket
my $socket = new IO::Socket::INET (
LocalAddr => '0.0.0.0', # local server address
LocalPort => '7777', # local server port
Listen => 5, # queue size for connections
Proto => 'tcp', # protocol used
);
die "cannot create socket $!\n" unless $socket;
print "server waiting for client connection on port 7777\n";
while(1)
{
# waiting for a new client connection
my $client_socket = $socket->accept() or die "socket accept failed $!";
# get information about a newly connected client
my $client_address = $client_socket->peerhost();
my $client_port = $client_socket->peerport();
print "connection from $client_address:$client_port\n";
# read up to 1024 characters from the connected client
my $client_data = '';
sysread($client_socket, $client_data, 1024);
print "received data: $client_data\n";
# write response data to the connected client
print $client_socket "Hey $client_data!";
# notify client that response has been sent
shutdown($client_socket, 1);
}
END {
$socket->close();
}
此服務器的應用程序可以使用此客戶端調用:
#!/usr/bin/env perl
use IO::Socket::INET;
# auto-flush on socket
$| = 1;
# create a connecting socket
my $socket = new IO::Socket::INET (
PeerHost => '127.0.0.1',
PeerPort => '7777',
Proto => 'tcp',
);
die "cannot connect to the server $!\n" unless $socket;
print "connected to the server\n";
# data to send to a server
my $req = $ARGV[0] . '';
print $socket $req;
# notify server that request has been sent
shutdown($socket, 1);
# receive a response of up to 1024 characters from server
my $response = '';
sysread($socket, $response,1024);
print "received response: $response\n";
$socket->close();
客戶端和服務器之間的相互作用可以看看像這樣:
inet$ perl server.pl server waiting for client connection on port 7777
connection from 127.0.0.1:40028
received data: Herbert
inet$ perl client.pl "Herbert"
connected to the server
received response: Hey Herbert!
很酷的事情是:服務器還可以從瀏覽器調用:
所以第一個結論:代碼工作,並是很好的展示一個簡單的客戶端 - 服務器交互的基本功能。
現在的程序應該使用SSL通信
服務器和客戶端都這麼寫的,是SSL的能力可以通過只在代碼中添加幾行來實現:
$ diff inet/server.pl ssl/server.pl
7c7
< use IO::Socket::INET;
---
> use IO::Socket::SSL 'inet4';
13c13
< my $socket = new IO::Socket::INET (
---
> my $socket = IO::Socket::SSL->new (
17a18,19
> SSL_cert_file => 'cert.pem', # SSL certificate
> SSL_key_file => 'key.pem', # SSL certificate key
$ diff inet/client.pl ssl/client.pl
5c5
< use IO::Socket::INET;
---
> use IO::Socket::SSL 'inet4';
11c11
< my $socket = new IO::Socket::INET (
---
> my $socket = new IO::Socket::SSL (
14a15
> SSL_ca_file => 'cert.pem',
因此,新的啓用了SSL代碼:
#!/usr/bin/env perl
use strict;
use warnings;
use IO::Socket::SSL 'inet4';
# auto-flush on socket
$| = 1;
# creating a listening socket
my $socket = IO::Socket::SSL->new (
LocalAddr => '0.0.0.0', # local server address
LocalPort => '7777', # local server port
Listen => 5, # queue size for connections
Proto => 'tcp', # protocol used
SSL_cert_file => 'cert.pem', # SSL certificate
SSL_key_file => 'key.pem', # SSL certificate key
);
die "cannot create socket $!\n" unless $socket;
print "server waiting for client connection on port 7777\n";
while(1)
{
# waiting for a new client connection
my $client_socket = $socket->accept() or die "socket accept failed $!";
# get information about a newly connected client
my $client_address = $client_socket->peerhost();
my $client_port = $client_socket->peerport();
print "connection from $client_address:$client_port\n";
# read up to 1024 characters from the connected client
my $client_data = '';
sysread($client_socket, $client_data, 1024);
print "received data: $client_data\n";
# write response data to the connected client
print $client_socket "Hey $client_data!";
# notify client that response has been sent
shutdown($client_socket, 1);
}
END {
$socket->close();
}
和
#!/usr/bin/env perl
use IO::Socket::SSL 'inet4';
# auto-flush on socket
$| = 1;
# create a connecting socket
my $socket = new IO::Socket::SSL (
PeerHost => '127.0.0.1',
PeerPort => '7777',
Proto => 'tcp',
SSL_ca_file => 'cert.pem',
);
die "cannot connect to the server $!\n" unless $socket;
print "connected to the server\n";
# data to send to a server
my $req = $ARGV[0] . '';
print $socket $req;
# notify server that request has been sent
shutdown($socket, 1);
# receive a response of up to 1024 characters from server
my $response = '';
sysread($socket, $response,1024);
print "received response: $response\n";
$socket->close();
運行代碼,證書必須首先創建:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
現在服務器和客戶端可以啓動,並很好地互動:
ssl$ perl server.pl
Enter PEM pass phrase:
server waiting for client connection on port 7777
connection from 127.0.0.1:40041
received data: Sabine
ssl$ perl client.pl "Sabine"
connected to the server
received response: Hey Sabine!
但是,什麼行不通的來自類似Firefox或Chrome的瀏覽器的連接,即使我使用以下格式轉換證書:
openssl pkcs12 -export -in cert.pem -inkey key.pem -out webcert.p12
我還通過導入菜單將新創建的證書導入瀏覽器。
連接剛被拒絕。瀏覽器無法連接,服務器在$socket->accept()
失敗,沒有任何有用的消息。
UPDATE:有在導出的變量$SSL_ERROR
消息:
SSL accept attempt failed error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request
我做了一些測試用工具analyze ssl
p5-ssl-tools-master$ perl analyze-ssl.pl --show-chain --all-ciphers -v3 127.0.0.1:7777
+ checking host=127.0.0.1(127.0.0.1) port=7777
* version SSLv23 no verification, ciphers= -> TLSv1_2,ECDHE-RSA-AES128-GCM-SHA256
* version SSLv23 no verification, ciphers=HIGH:ALL -> TLSv1_2,ECDHE-RSA-AES128-GCM-SHA256
* version TLSv1_2 no verification, ciphers= -> TLSv1_2,ECDHE-RSA-AES128-GCM-SHA256
* version TLSv1_2 no verification, ciphers=HIGH:ALL -> TLSv1_2,ECDHE-RSA-AES128-GCM-SHA256
* version TLSv1_1 no verification, ciphers= -> TLSv1_1,ECDHE-RSA-AES256-SHA
* version TLSv1_1 no verification, ciphers=HIGH:ALL -> TLSv1_1,ECDHE-RSA-AES256-SHA
* version TLSv1 no verification, ciphers= -> TLSv1,ECDHE-RSA-AES256-SHA
* version TLSv1 no verification, ciphers=HIGH:ALL -> TLSv1,ECDHE-RSA-AES256-SHA
* version SSLv3, no verification, ciphers= -> FAIL! SSL connect attempt failed because of handshake problems error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
+ 127.0.0.1 failed permanently 'tcp connect: Verbindungsaufbau abgelehnt', no more IP to try
tcp connect: Verbindungsaufbau abgelehnt
服務器似乎接受了一定的要求,未能在最後,也許與瀏覽器一樣?
ssl$ perl server.pl
Enter PEM pass phrase:
server waiting for client connection on port 7777
connection from 127.0.0.1:40042
received data:
connection from 127.0.0.1:40043
received data:
connection from 127.0.0.1:40044
received data:
connection from 127.0.0.1:40045
received data:
connection from 127.0.0.1:40046
received data:
connection from 127.0.0.1:40047
received data:
connection from 127.0.0.1:40048
received data:
connection from 127.0.0.1:40049
received data:
socket accept failed at server.pl line 27.
我的問題
爲什麼用瀏覽器的請求不能正常工作? 代碼應該支持瀏覽器請求,因爲它不使用SSL。 由於SSL-Perl-Client沒有問題,它似乎是瀏覽器特定的SSL設置。 或者是證書導入瀏覽器不按預期工作? 任何人都可以給我提示或解決這個問題?
更新:當我看看$SSL_ERROR
錯誤消息「SSL23
」,並在客戶端測試錯誤消息「SSL3
」似乎有兼容性問題SSL版本?我需要明確指定我想要的版本嗎? (另一方面,「SSL23
」的客戶端測試似乎成功運行...)
非常感謝。
UPDATE:輸出與$IO::Socket::SSL::DEBUG = 3;
ssl$ perl server.pl
Enter PEM pass phrase:
DEBUG: .../IO/Socket/SSL.pm:2554: new ctx 42708208
server waiting for client connection on port 7777
DEBUG: .../IO/Socket/SSL.pm:799: no socket yet
DEBUG: .../IO/Socket/SSL.pm:801: accept created normal socket IO::Socket::SSL=GLOB(0x28ac158)
DEBUG: .../IO/Socket/SSL.pm:829: starting sslifying
DEBUG: .../IO/Socket/SSL.pm:873: Net::SSLeay::accept -> -1
DEBUG: .../IO/Socket/SSL.pm:1779: SSL accept attempt failed
DEBUG: .../IO/Socket/SSL.pm:1784: SSL accept attempt failed error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request
socket accept failed: SSL accept attempt failed error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request at server.pl line 28.
DEBUG: .../IO/Socket/SSL.pm:2587: free ctx 42708208 open=42708208
DEBUG: .../IO/Socket/SSL.pm:2599: OK free ctx 42708208
Ullrich你真棒!雖然對我來說有點尷尬......在我身邊的一個簡單的錯誤。非常感謝您的時間。 (我可能沒有看到森林,因爲所有的樹木,就像我們在德語中所說的那樣) –