客户端和服务器的 SSL 握手失败

Posted

技术标签:

【中文标题】客户端和服务器的 SSL 握手失败【英文标题】:SSL Handshake failures with client and server 【发布时间】:2016-09-23 22:47:27 【问题描述】:

所以我在 Python 上构建了一个客户端,在 Java 上构建了一个服务器来通信和传输文件和字符串。我在想我要做的第一件事(除了连接服务器和客户端)是完成 SSL 握手。以下是我自己实现的Python客户端代码和Java服务端代码:

Python 客户端代码

import socket
import ssl
import struct
import io
import threading
import optparse
import os
import sys

HOST = "localhost"
PORT = 777
ADDR = (HOST,PORT)




def sock_connection():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    time.sleep(1)
    ssl_sock = ssl.wrap_socket(sock)
    try:
        time.sleep(1)
        ssl_sock.connect(ADDR)
        print('CONNECTED!')
    except socket.error as e:
        print('ERROR', e)
        exit(1)
    return ssl_sock

def main():
    sock_connection()

main()

Java 服务器代码:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;



  public 
  class Server 
    private static final int PORT = 777;

   public
            static
    void
            main(String[] arstring) 
        try 
            SSLServerSocketFactory sslserversocketfactory =
                    (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
            SSLServerSocket sslserversocket =
                    (SSLServerSocket) sslserversocketfactory.createServerSocket(PORT);
            SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

            InputStream inputstream = sslsocket.getInputStream();
            InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

            String string = null;
            while ((string = bufferedreader.readLine()) != null) 
                System.out.println(string);
                System.out.flush();
            
         catch (Exception exception) 
            exception.printStackTrace();
        
    

我通常先运行服务器,它运行良好,然后我运行客户端,我在服务器终端收到以下错误:

javax.net.ssl.SSLHandshakeException:没有共同的密码套装

在python中还有以下内容:

错误 [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 警报握手失败 (_ssl.c:645)

我们将不胜感激。

谢谢

【问题讨论】:

【参考方案1】:

javax.net.ssl.SSLHandshakeException:没有共同的密码套装

这意味着服务器只支持客户端不支持的密码,即没有重叠,因此没有可用于身份验证和加密的通用密码。

鉴于您服务器的源代码,我猜您错过了设置服务器应使用的证书。在这种情况下,只能进行匿名身份验证,并且通常不会在 SSL 客户端中启用此密码(也不会在浏览器中启用)。

【讨论】:

感谢您的帮助!啊,我明白了。好的,所以我需要设置服务器应该使用的证书,然后客户端如何确认证书有效? @D.Crusaf:是的,你应该设置一个证书。客户端是否接受取决于证书的颁发者以及客户端是否信任此颁发者。解释 TLS 如何工作以及如何更详细地完成证书验证确实超出了这个问题的范围。我建议阅读How does SSL/TLS work?。 非常感谢!我将尝试为服务器制作证书。谢谢你的链接,非常感谢。【参考方案2】:

由于安全漏洞,SSLV3 已被弃用。您的客户端正在尝试使用 SSLV3 协议,而服务器甚至无法识别它。

你可以:

设置服务器以允许 SSLV3(不是我推荐的) 在您的 python 客户端中配置您的套接字,以明确不使用任何基于 SSLV3 的协议。您可以改用 TLS。您通常希望通过覆盖使用的 SocketFactory 来做到这一点。

在 Java 世界中,我们在 java 1.6 中使用客户端时会遇到这个问题。 Java 1.7 移除了 SSLV3Hello 的默认使用。

【讨论】:

我有最新的 Java 版本,我的客户端是 Python。我真的不知道 Tomcat 是什么,但我只是将我的 cmd 与我编写的一些脚本一起使用。我将尝试覆盖使用的 SocketFactory!谢谢! 您对 Tomcat 的看法绝对正确。我太老套了,忘记了。我会编辑我的答案。无论如何,问题仍然存在:客户端使用 SSLV3 握手,服务器拒绝它。您应该将客户端配置为使用 TLS。 好的,谢谢您的意见。我不确定如何使用 TLS,但我会尽力弄清楚。再次感谢! 不是 python 用户,但这个页面似乎提供了非常有用的信息:docs.python.org/2/library/ssl.htmlSSLContext.set_alpn_protocols(protocols) : Specify which protocols the socket should advertise during the SSL/TLS handshake. It should be a list of ASCII strings, like ['http/1.1', 'spdy/2'], ordered by preference. The selection of a protocol will happen during the handshake, and will play out according to RFC 7301. After a successful handshake, the SSLSocket.selected_alpn_protocol() method will return the agreed-upon protocol.

以上是关于客户端和服务器的 SSL 握手失败的主要内容,如果未能解决你的问题,请参考以下文章

Qt SSL:从 QML 发出的请求握手失败

调用 fork 后 gRPC 服务器中的 SSL 握手失败

ClientHello 后 SSL 握手失败

HTTPS|SSL笔记-SSL双向认证失败(客户端证书信任库不含服务端证书)握手过程(含wireshark分析)

当 curl 成功时,Java HTTPS 客户端失败 SSL 握手

无效session ticket导致的SSL握手协商失败