2013-08-12 5 views
0

Я пишу прокси-сервер, http-часть готова, но возникают проблемы с https. Я создал сертификат и закрытый ключ (как я понял, без него не будет работать) таким образом:Прокси-сервер QSslSocket (https) и сертификаты. Ошибка установления связи

OpenSSL> req-x509-newkey rsa: 2048-keyout server.key-nodes-days 365-out server.csr 

Я сделал простой QTcpServer, который передается в socketDescriptor на созданный объект на newIncomingConnection(). В конструкторе моего объекта я сделал:

sock = new QSslSocket(); 
    connect (sock,SIGNAL(readyRead()),this,SLOT(onQuery())); 
    connect(sock,SIGNAL(disconnected()),this,SLOT(deleteLater())); 
    connect(sock,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onError(QAbstractSocket::SocketError))); 
    connect(sock,SIGNAL(sslErrors(QList<QSslError>)),this,SLOT(sltSslErrors(QList<QSslError>))); 

... 
Load key and cert 
... 
    sock->setProtocol(QSsl::AnyProtocol); 
    QSslKey sslKey(key, QSsl::Rsa); 
    QSslCertificate sslCert(cert); 
    sock->setPrivateKey(sslKey); 
    sock->setLocalCertificate(sslCert); 
    sock->setSocketDescriptor(socketDesc); 
    sock->startServerEncryption(); 
    if(!sock->waitForEncrypted(30000)) { 
     qDebug()<<"wait for encrypted failed"; 
    } 

На подключения в консоли я вижу «ждать зашифрованного неудавшегося» и розеткой emited сигнала ошибки() с QAbstractSocket :: SslHandshakeFailedError. Не могли бы вы дать советы о том, что еще нужно сделать, чтобы установить соединение ssl без ошибок?

ответ

1

Мне кажется, вам нужно позвонить setSocketDescriptor перед вызовом методов setPrivateKey и setLocalCertificate.

Ниже приведен код, который я использовал для создания HTTPS Server Socket, охватывающий QTcpServer.

void SslServer::incomingConnection(qintptr socketDescriptor) 
{ 
    QSslSocket *serverSocket = new QSslSocket; 
    if (serverSocket->setSocketDescriptor(socketDescriptor)) { 
     QFile keyFile(<sslKeyFileName>); 
     if (!keyFile.open(QIODevice::ReadOnly)) { 
      delete serverSocket; 
      return; 
     } 
     QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); 
     if (key.isNull()) { 
      delete serverSocket; 
      return; 
     } 
     keyFile.close(); 
     serverSocket->setPrivateKey(key); 
     // to prevent asking for client certificate. 
     serverSocket->setPeerVerifyMode(QSslSocket::VerifyNone); 
     serverSocket->setLocalCertificate(<certificateFileName>); 
     serverSocket->startServerEncryption(); 
     if (serverSocket->waitForEncrypted(3000)) { 
      // this will emit a newConnection() signal 
      addPendingConnection(serverSocket); 
     } else { 
      qDebug() << "Encryption Failed."; 
      delete serverSocket; 
     } 
    } else { 
     delete serverSocket; 
    } 
} 
0

См. Исходный код примера sslechoserver. Он использует QWebSocket, но то же самое работает и с QSslSocket.

// Enable SSL 
QSslConfiguration sslConfiguration; 
QFile certFile(QStringLiteral("/home/stefan/cert/my.cert")); 
QFile keyFile(QStringLiteral("/home/stefan/cert/my.key")); 
certFile.open(QIODevice::ReadOnly); 
keyFile.open(QIODevice::ReadOnly); 
QSslCertificate certificate(&certFile, QSsl::Pem); 
QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem); 
certFile.close(); 
keyFile.close(); 
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone); 
sslConfiguration.setLocalCertificate(certificate); 
sslConfiguration.setPrivateKey(sslKey); 
sslConfiguration.setProtocol(QSsl::TlsV1SslV3); 
socket.setSslConfiguration(sslConfiguration); 
socket.startServerEncryption(); 

И не вызывайте socket.waitForEncrypted(), потому что это снова приведет к непредвиденной ошибке.

Смежные вопросы