https.protocols在Java中的使用

Contents

Caused by: java.io.EOFException: SSL peer shut down incorrectly

在服务器上,发现一个微博爬虫系统偶尔会报这种异常。Google 了下,在 Stackoverflow 上看到相关的回答。所以决定详细了解下这原理。

上面说,明确指定HTTPS的协议版本即可。即:System.setProperty("https.protocols", "TLSv1.1")

HTTPS 的 protocols

查看维基百科,关于 HTTPS 的介绍可知:

严格地讲,HTTPS并不是一个单独的协议,而是对工作在一加密连接(TLS或SSL)上的常规HTTP协议的称呼。

TLS 与 SSL

SSLTLS 的前身。SSLNetscape 公司推出的 HTTPS 协议,以 SSL 进行加密。

IETFSSL 进行标准化,公布了第一版的 TLS 标准文件。

发展历史

SSL

  • 1.0 没有公开过
  • 2.0 1995年2月发布
  • 3.0 1996年发布。2014年10月,Google 发现 SSL 3.0 设计缺陷,建议禁用此一协议。

TLS

IETF 将SSL标准化,并称为 TLS. TLS1.0SSL 3.0 的差异非常小。

  • 1.0
  • 1.1 2006
  • 1.2 2008
  • 1.3 2016

JDK中对 HTTPS 版本的支持情况

JDK 6

  • SSL v3
  • TLS v1(默认)
  • TLS v1.1(JDK6 update 111 及以上)

JDK 7

  • SSLv3
  • TLS v1(默认)
  • TLS v1.1
  • TLS v1.2

JDK 8

  • SSL v3
  • TLS v1
  • TLS v1.1
  • TLS v1.2(默认)

JSSE

JSSE(Java Security Socket Extension),它实现了SSL和TSL(传输层安全)协议。

JSSE 参数调节

  • javax.net.debug :打印连接的详细信息。例如 -Djavax.net.debug=all 或者 -Djavax.net.debug=ssl🤝verbose
  • https.protocols :控制使用 Java 客户端通过 HttpsURLConnectionURL.openStream() 操作的协议版本。例如 -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2. 对于非HTTP协议,可以通过 SocketFactory's SSLContext 来控制 。
  • jdk.tls.client.protocols :控制底层平台的TLS实现。例如 -Djdk.tls.client.protocols=TLSv1.1,TLSv1.2
  • http.agent :当初始化连接时,Java会使用这个作为 user-agent 的字符串。例如: -Dhttp.agent="known agent"
  • java.net.useSystemProxies :使用系统本身的代理: -Djava.net.useSystemProxies=true
  • http.proxyHosthttp.proxyPort : 使用HTTP协议时的代理。例如: -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080
  • https.proxyHosthttps.proxyPort : 和上面一样,区别只是 HTTP 和 HTTPS
  • http.proxyUser,http.proxyPassword, https.proxyUser,https.proxyPassword : 认证用户名和密码。

查看服务器支持的 HTTPS 协议版本

1
nmap --script ssl-enum-ciphers -p 443 api.weibo.com

返回的结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

Starting Nmap 7.40 ( https://nmap.org ) at 2017-03-02 14:18 CST
Nmap scan report for api.weibo.com (180.149.135.176)
Host is up (0.039s latency).
Other addresses for api.weibo.com (not scanned): 180.149.135.230
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| SSLv3:
| ciphers:
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 1024) - D
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| 64-bit block cipher DES vulnerable to SWEET32 attack
| 64-bit block cipher IDEA vulnerable to SWEET32 attack
| Broken cipher RC4 is deprecated by RFC 7465
| CBC-mode cipher in SSLv3 (CVE-2014-3566)
| Key exchange (dh 1024) of lower strength than certificate key
| TLSv1.0:
| ciphers:
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 1024) - D
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| 64-bit block cipher DES vulnerable to SWEET32 attack
| 64-bit block cipher IDEA vulnerable to SWEET32 attack
| Broken cipher RC4 is deprecated by RFC 7465
| Key exchange (dh 1024) of lower strength than certificate key
| TLSv1.1:
| ciphers:
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 1024) - D
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| 64-bit block cipher DES vulnerable to SWEET32 attack
| 64-bit block cipher IDEA vulnerable to SWEET32 attack
| Broken cipher RC4 is deprecated by RFC 7465
| Key exchange (dh 1024) of lower strength than certificate key
| TLSv1.2:
| ciphers:
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 1024) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 1024) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 1024) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (dh 1024) - D
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| 64-bit block cipher DES vulnerable to SWEET32 attack
| 64-bit block cipher IDEA vulnerable to SWEET32 attack
| Broken cipher RC4 is deprecated by RFC 7465
| Key exchange (dh 1024) of lower strength than certificate key
|_ least strength: D
Nmap done: 1 IP address (1 host up) scanned in 10.99 seconds

可知,它支持的协议有:

  • SSLv3
  • TLSv1.0
  • TLSv1.1
  • TLSv1.2

解决办法

服务器为Linux + JDK7 + 64位。添加

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

在爬虫爬取数据时,就没有报这类似的异常了。

参考资料