javax.net.ssl.SSLException:收到致命警报:protocol_version

Posted

技术标签:

【中文标题】javax.net.ssl.SSLException:收到致命警报:protocol_version【英文标题】:javax.net.ssl.SSLException: Received fatal alert: protocol_version 【发布时间】:2013-05-08 15:25:06 【问题描述】:

以前有人遇到过这个错误吗?我是 SSL 的新手,我的 ClientHello 有什么明显的问题吗?该异常在没有 ServerHello 响应的情况下被抛出。任何建议表示赞赏。

*** ClientHello, TLSv1
RandomCookie:  GMT: 1351745496 bytes =  154, 151, 225, 128, 127, 137, 198, 245, 160, 35, 124, 13, 135, 120, 33, 240, 82, 223, 56, 25, 207, 231, 231, 124, 103, 205, 66, 218 
Session ID:  
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:   0 
***
[write] MD5 and SHA1 hashes:  len = 75
0000: 01 00 00 47 03 01 51 92   00 D8 9A 97 E1 80 7F 89  ...G..Q.........
0010: C6 F5 A0 23 7C 0D 87 78   21 F0 52 DF 38 19 CF E7  ...#...x!.R.8...
0020: E7 7C 67 CD 42 DA 00 00   20 00 04 00 05 00 2F 00  ..g.B... ...../.
0030: 33 00 32 00 0A 00 16 00   13 00 09 00 15 00 12 00  3.2.............
0040: 03 00 08 00 14 00 11 00   FF 01 00                 ...........
xxx, WRITE: TLSv1 Handshake, length = 75
[write] MD5 and SHA1 hashes:  len = 101
0000: 01 03 01 00 3C 00 00 00   20 00 00 04 01 00 80 00  ....<... .......
0010: 00 05 00 00 2F 00 00 33   00 00 32 00 00 0A 07 00  ..../..3..2.....
0020: C0 00 00 16 00 00 13 00   00 09 06 00 40 00 00 15  ............@...
0030: 00 00 12 00 00 03 02 00   80 00 00 08 00 00 14 00  ................
0040: 00 11 00 00 FF 51 92 00   D8 9A 97 E1 80 7F 89 C6  .....Q..........
0050: F5 A0 23 7C 0D 87 78 21   F0 52 DF 38 19 CF E7 E7  ..#...x!.R.8....
0060: 7C 67 CD 42 DA                                     .g.B.
xxx, WRITE: SSLv2 client hello message, length = 101
[Raw write]: length = 103
0000: 80 65 01 03 01 00 3C 00   00 00 20 00 00 04 01 00  .e....<... .....
0010: 80 00 00 05 00 00 2F 00   00 33 00 00 32 00 00 0A  ....../..3..2...
0020: 07 00 C0 00 00 16 00 00   13 00 00 09 06 00 40 00  ..............@.
0030: 00 15 00 00 12 00 00 03   02 00 80 00 00 08 00 00  ................
0040: 14 00 00 11 00 00 FF 51   92 00 D8 9A 97 E1 80 7F  .......Q........
0050: 89 C6 F5 A0 23 7C 0D 87   78 21 F0 52 DF 38 19 CF  ....#...x!.R.8..
0060: E7 E7 7C 67 CD 42 DA                               ...g.B.
[Raw read]: length = 5
0000: 15 03 01 00 02                                     .....
[Raw read]: length = 2
0000: 02 46                                              .F

http://xml.apache.org/axis/stackTrace:

javax.net.ssl.SSLException: Received fatal alert: protocol_version
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1806)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:986)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
at org.apache.axis.components.net.JSSESocketFactory.create(JSSESocketFactory.java:186)
at 

...

【问题讨论】:

你用的是什么服务器? 【参考方案1】:

这似乎是协议版本不匹配,此异常通常发生在客户端和服务器使用的 SSL 协议版本不匹配时。您的客户端应使用服务器支持的协议版本。

【讨论】:

感谢您的解释。如果我的问题得到解决,我会告诉你的:)【参考方案2】:

这是因为您发送了 TLSv1 握手,但随后您使用 SSLv2 协议发送了消息;

xxx, WRITE: TLSv1 Handshake, length = 75
xxx, WRITE: SSLv2 client hello message, length = 101

这意味着服务器期望使用 TLSv1 协议并且不会接受连接。尝试指定要使用的协议,或发布一些相关代码以便我们查看

【讨论】:

不过根据docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/…这似乎是正常的 你的服务器支持什么协议?【参考方案3】:

在 Java 1.8 上,默认 TLS 协议是 v1.2。在 Java 1.6 和 1.7 上,默认 TLS1.0 已过时。我在 Java 1.8 上收到此错误,因为 url 使用旧的 TLS1.0(例如 Your - You see ClientHello, TLSv1)。要解决此错误,您需要使用 Java 1.8 的覆盖默认值。

System.setProperty("https.protocols", "TLSv1");

有关Oracle blog:Diagnosing TLS, SSL, and HTTPS的更多信息。

【讨论】:

您可以将其指定为命令行参数。我用-Dhttps.protocols=TLSv1.2【参考方案4】:

marioosh 的答案似乎在正确的轨道上。它对我不起作用。 于是我发现:

Problems connecting via HTTPS/SSL through own Java client

使用:

java.lang.System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");

这对于 Java 7 和 TLSv1.2 站点似乎是必需的。

我检查了网站:

openssl s_client -connect www.st.nmfs.noaa.gov:443

使用

openssl version
OpenSSL 1.0.2l  25 May 2017

得到了结果:

...
SSL-Session:
   Protocol  : TLSv1.2
   Cipher    : ECDHE-RSA-AES256-GCM-SHA384
...

请注意,我的 mac 上的旧版 openssl 无法正常工作,我必须使用 macports 版本。

【讨论】:

【参考方案5】:

@marioosh 添加了一些关于密码套件加密的额外信息。


cipher suite 是一组对称和非对称加密算法,主机用于在传输层安全 (TLS)/安全套接字层 (SSL) 网络协议中建立安全通信。 密码是算法,更具体地说,它们是一组用于执行加密和相应解密的步骤。

密码套件为以下每个任务指定一种算法:

密钥交换 批量加密 消息认证

SocketFactory « 默认握手协议 « 为了避免 SSLException,请使用 https.protocols 系统属性。 这包含以逗号分隔的协议套件名称列表,指定要在此 HttpsURLConnection 上启用哪些协议套件。请参阅SSLSocket.setEnabledProtocols(String[]) method

System.setProperty("https.protocols", "SSLv3");
// (OR)
System.setProperty("https.protocols", "TLSv1");

JAVA8 « TLS 1.1 和 TLS 1.2 默认启用:SunJSSE 提供程序默认启用客户端上的协议 TLS 1.1 和 TLS 1.2。

System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");

Java8 网络文件示例:

public class SecureSocket 
    static 
        // System.setProperty("javax.net.debug", "all");
        System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
    
    public static void main(String[] args) 
        String GhitHubSSLFile = "https://raw.githubusercontent.com/Yash-777/SeleniumWebDrivers/master/pom.xml";
        try 
            String str = readCloudFileAsString(GhitHubSSLFile);
                    // new String(Files.readAllBytes(Paths.get( "D:/Sample.file" )));
                    
            System.out.println("Cloud File Data : "+ str);
         catch (IOException e) 
            e.printStackTrace();
        
    
    public static String readCloudFileAsString( String urlStr ) throws java.io.IOException 
        if( urlStr != null && urlStr != "" ) 
            java.io.InputStream s = null;
            String content = null;
            try 
                URL url = new URL( urlStr );
                s = (java.io.InputStream) url.getContent();
                content = IOUtils.toString(s, "UTF-8");
             finally 
                if (s != null) s.close(); 
            
            return content.toString();
        
        return null;
    

JDK 8 Security 您可以通过设置系统属性来自定义 JSSE 的某些方面,通过指定以下属性,您可以检查文件中的加密数据。
System.setProperty("javax.net.debug", "all");

例外

javax.net.ssl.SSLException: Received fatal alert: protocol_version

如果由于某种原因握手失败,SSLSocket 将关闭,并且无法进行进一步的通信。

上述示例的观察者日志示例:

*** ClientHello, TLSv1.2
RandomCookie:  GMT: 1505482843 bytes =  12, 11, 111, 99, 8, 177, 101, 27, 84, 176, 147, 215, 116, 208, 31, 178, 141, 170, 29, 118, 29, 192, 61, 191, 53, 201, 127, 100 
Session ID:  
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:   0 
Extension elliptic_curves, curve names: secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Extension server_name, server_name: [host_name: raw.githubusercontent.com]
***
[write] MD5 and SHA1 hashes:  len = 213
0000: 01 00 00 D1 03 03 5A BC   D8 5B 0C 0B 6F 63 08 B1  ......Z..[..oc..
0010: 65 1B 54 B0 93 D7 74 D0   1F B2 8D AA 1D 76 1D C0  e.T...t......v..
0020: 3D BF 35 C9 7F 64 00 00   2A C0 09 C0 13 00 2F C0  =.5..d..*...../.
0030: 04 C0 0E 00 33 00 32 C0   08 C0 12 00 0A C0 03 C0  ....3.2.........
0040: 0D 00 16 00 13 C0 07 C0   11 00 05 C0 02 C0 0C 00  ................
0050: 04 00 FF 01 00 00 7E 00   0A 00 34 00 32 00 17 00  ..........4.2...
0060: 01 00 03 00 13 00 15 00   06 00 07 00 09 00 0A 00  ................
0070: 18 00 0B 00 0C 00 19 00   0D 00 0E 00 0F 00 10 00  ................
0080: 11 00 02 00 12 00 04 00   05 00 14 00 08 00 16 00  ................
0090: 0B 00 02 01 00 00 0D 00   1A 00 18 06 03 06 01 05  ................
00A0: 03 05 01 04 03 04 01 03   03 03 01 02 03 02 01 02  ................
00B0: 02 01 01 00 00 00 1E 00   1C 00 00 19 72 61 77 2E  ............raw.
00C0: 67 69 74 68 75 62 75 73   65 72 63 6F 6E 74 65 6E  githubuserconten
00D0: 74 2E 63 6F 6D                                     t.com
main, WRITE: TLSv1.2 Handshake, length = 213
[Raw write]: length = 218
0000: 16 03 03 00 D5 01 00 00   D1 03 03 5A BC D8 5B 0C  ...........Z..[.
0010: 0B 6F 63 08 B1 65 1B 54   B0 93 D7 74 D0 1F B2 8D  .oc..e.T...t....
0020: AA 1D 76 1D C0 3D BF 35   C9 7F 64 00 00 2A C0 09  ..v..=.5..d..*..
0030: C0 13 00 2F C0 04 C0 0E   00 33 00 32 C0 08 C0 12  .../.....3.2....
0040: 00 0A C0 03 C0 0D 00 16   00 13 C0 07 C0 11 00 05  ................
0050: C0 02 C0 0C 00 04 00 FF   01 00 00 7E 00 0A 00 34  ...............4
0060: 00 32 00 17 00 01 00 03   00 13 00 15 00 06 00 07  .2..............
0070: 00 09 00 0A 00 18 00 0B   00 0C 00 19 00 0D 00 0E  ................
0080: 00 0F 00 10 00 11 00 02   00 12 00 04 00 05 00 14  ................
0090: 00 08 00 16 00 0B 00 02   01 00 00 0D 00 1A 00 18  ................
00A0: 06 03 06 01 05 03 05 01   04 03 04 01 03 03 03 01  ................
00B0: 02 03 02 01 02 02 01 01   00 00 00 1E 00 1C 00 00  ................
00C0: 19 72 61 77 2E 67 69 74   68 75 62 75 73 65 72 63  .raw.githubuserc
00D0: 6F 6E 74 65 6E 74 2E 63   6F 6D                    ontent.com
[Raw read]: length = 5
0000: 16 03 03 00 5D                                     ....]

使用 whatsapp 进行加密和安全通信Image from businesstoday.in

@见

AZURE TLS/SSL cipher suites javax.net.ssl.SSLHandshakeException: No appropriate protocol Whatsapp End To End Encryption

【讨论】:

【参考方案6】:

我遇到了同样的错误。 对于 Java 版本 7,以下对我有用。

java.lang.System.setProperty("https.protocols", "TLSv1.2");

【讨论】:

【参考方案7】:

我在尝试安装 PySpark 包时遇到了这个问题。我通过使用环境变量更改 TLS 版本解决了这个问题:

echo 'export JAVA_TOOL_OPTIONS="-Dhttps.protocols=TLSv1.2"' >> ~/.bashrc
source ~/.bashrc

【讨论】:

在使用 java 7 运行 gradlew 时,这对我有用。谢谢【参考方案8】:

您可以尝试在最后一次输入 JAVA_OPTS 后在 catalina.bat 中添加以下行

设置JAVA_OPTS=%JAVA_OPTS% -Dhttps.protocols=TLSv1.2 -Djdk.tls.client.protocols=TLSv1.2

【讨论】:

【参考方案9】:

不确定您是否找到答案,但我遇到了这个问题,需要将 TLS 版本升级到 1.2

private HttpsURLConnection getSSlConnection(String url, String username, String password)
    SSLContext sc = SSLContext.getInstance("TLSv1.2")
    // Create a trust manager that accepts all SSL sites
    TrustManager[] trustAllCerts = new TrustManager[1]
    def tm = new X509TrustManager()
        @Override
        public void checkClientTrusted(X509Certificate[] certs, String authType) 
        

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException 
        

        @Override
        X509Certificate[] getAcceptedIssuers() 
            return new X509Certificate[0]
        
    
    trustAllCerts[0] = tm

    sc.init(null, trustAllCerts, new SecureRandom())
    HttpsURLConnection connection = (HttpsURLConnection) getConnection(url, username, password)
    connection.setSSLSocketFactory(sc.getSocketFactory())
    return connection

【讨论】:

【参考方案10】:

我在更新到 JDK 1.8 后遇到了这个错误。但是JAVA_HOME 变量被硬编码到JDK 1.7。修改后解决了问题:

set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_241

【讨论】:

【参考方案11】:

我将 apache-tomcat-7.0.70jdk1.7.0_45 一起使用,*** 上和其他地方的解决方案均不适合我。只是分享这个解决方案,因为它希望可以帮助某人,因为这在谷歌的搜索中非常高

这两个步骤都行得通:

    通过将“export JAVA_OPTS="$JAVA_OPTS -Dhttps.protocols=TLSv1.2" 添加到 tomcat/bin/setenv.sh 来启动我的 tomcat(Windows 上的语法略有不同)

    使用 TLS1.2 协议手动构建/强制 HttpClient 或您需要的任何其他内容:

    Context ctx = SSLContexts.custom().useProtocol("TLSv1.2").build();
    HttpClient httpClient = HttpClientBuilder.create().setSslcontext(ctx).build();
    HttpPost httppost = new HttpPost(scsTokenVerificationUrl);
    
    List<NameValuePair> paramsAccessToken = new ArrayList<NameValuePair>(2);
    paramsAccessToken.add(new BasicNameValuePair("token", token));
    paramsAccessToken.add(new BasicNameValuePair("client_id", scsClientId));
    paramsAccessToken.add(new BasicNameValuePair("secret", scsClientSecret));
    httppost.setEntity(new UrlEncodedFormEntity(paramsAccessToken, "utf-8"));
    
    //Execute and get the response.
    HttpResponse httpResponseAccessToken = httpClientAccessToken.execute(httppost);
    
    String responseJsonAccessToken = EntityUtils.toString(httpResponseAccessToken.getEntity());
    

【讨论】:

【参考方案12】:

对于使用 IBM JDK 的用户,您需要将此参数提供给 JVM。 -Dcom.ibm.jsse2.overrideDefaultTLS=true

我使用的是 Liberty,所​​以我在 jvm.options 文件中进行了设置。

Reference Documentation

More information on protocols used with IBM Here

【讨论】:

谢谢!除非我在 IBM JDK 上使用此设置,否则其他设置将生效【参考方案13】:
public class SecureSocket 
static 
    // System.setProperty("javax.net.debug", "all");
    System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");

public static void main(String[] args) 
    String GhitHubSSLFile = "https://raw.githubusercontent.com/Yash-777/SeleniumWebDrivers/master/pom.xml";
    try 
        String str = readCloudFileAsString(GhitHubSSLFile);
                // new String(Files.readAllBytes(Paths.get( "D:/Sample.file" )));

        System.out.println("Cloud File Data : "+ str);
     catch (IOException e) 
        e.printStackTrace();
    

public static String readCloudFileAsString( String urlStr ) throws java.io.IOException 
    if( urlStr != null && urlStr != "" ) 
        java.io.InputStream s = null;
        String content = null;
        try 
            URL url = new URL( urlStr );
            s = (java.io.InputStream) url.getContent();
            content = IOUtils.toString(s, "UTF-8");
          
        
        return content.toString();
    
    return null;

Factory Reset Helplowearnings.com

【讨论】:

嗨威廉,欢迎来到 ***。为了使您的答案更有效,您可能需要详细说明您的解决方案,而不仅仅是粘贴一些代码。这将有助于 OP 和其他读者理解问题和解决方案。【参考方案14】:

就我而言,只有以下解决方案有效


private static CloseableHttpClient buildHttpClient() 
        System.setProperty("https.protocols", "TLSv1.2");
        SSLContext ctx = null;
        try 
            ctx = SSLContexts.custom().useProtocol("TLSv1.2").build();
         catch (KeyManagementException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         catch (NoSuchAlgorithmException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
        CloseableHttpClient httpClient = 
            HttpClientBuilder.create().setSslcontext(ctx).build();
        return httpClient;
    

【讨论】:

【参考方案15】:

[使用 JBoss]

打开配置路径:

JBOSS_HOME/standalone/configuration/standalone.xml

JBOSS_HOME/standalone/configuration/standalone-full.xml

在“&lt;system-properties&gt;”标签内,添加以下行:

<property name="https.protocols" value="TLSv1,TLSv1.1,TLSv1.2"/>

它为我解决了问题。

【讨论】:

jboss-fuse-6.3.0.redhat-187/etc/system.properties for JBOSS 6.3 添加新行 https.protocols=TLSv1,TLSv1.1,TLSv1.2 虽然这并没有解决我的问题。但是现在出现差异错误【参考方案16】:

当我尝试在 Java 7 上使用 TLS1.2 时,我遇到了同样的错误。 我用SSLContext 解决了这个问题。这是我的代码。我已经在 J​​ava 7 上测试过这段代码。

 String url = "--add-url-here--"
 URL url = new URL("https://" + url);
 //sslcontext
 SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
 sslContext.init(null, null, new SecureRandom());
 HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
 connection.setRequestMethod("POST");
 connection.setSSLSocketFactory(sslContext.getSocketFactory());
 System.out.println(connection.getResponseCode());

【讨论】:

以上是关于javax.net.ssl.SSLException:收到致命警报:protocol_version的主要内容,如果未能解决你的问题,请参考以下文章