无脑的解决方案
经测试,Python 3.9 是最合适的一个版本了,直接静态编译一个 Python,搞定 TLS 的难题
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
|
mkdir -p /local/root/opt/{lib,source}
export LIBDIR=/local/root/opt/lib
export WORKDIR=/local/root/opt/source
cd $WORKDIR && \
wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.0l.tar.gz && \
tar -xzvf openssl-1.1.0l.tar.gz && \
cd openssl-1.1.0l && \
./config shared \
--openssldir=$LIBDIR/openssl \
--prefix=$LIBDIR/openssl \
-DOPENSSL_TLS_SECURITY_LEVEL=0 && \
make -j16 && \
make install
# complie python 3.9.0
cd $WORKDIR && \
wget --no-check-certificate http://npm.taobao.org/mirrors/python/3.9.0/Python-3.9.0.tar.xz && \
tar -Jxvf Python-3.9.0.tar.xz && \
cd Python-3.9.0 && \
sed -i "s|OPENSSL_LIBS=\"-lssl -lcrypto\"|OPENSSL_LIBS=\"\$ssldir/lib/libssl.a \$ssldir/lib/libcrypto.a\"|g" ./configure && \
sed -i "s|libraries=openssl_libs|extra_objects=openssl_libs|g" ./setup.py && \
sed -i "s|split_var('OPENSSL_LIBS', '-l')|split_var('OPENSSL_LIBS', '')|g" ./setup.py && \
./configure --prefix=$(pyenv root)/versions/openssl \
--with-openssl=$LIBDIR/openssl && \
make -j16 && \
make install
|
繁琐的解决方案
UNSAFE_LEGACY_RENEGOTIATION_DISABLED
新建一个 openssl.cnf
文件,内容如下
1
2
3
4
5
6
7
8
9
10
|
openssl_conf = openssl_init
[openssl_init]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
Options = UnsafeLegacyRenegotiation
|
之后更换 OPENSSL_CONF
环境变量运行 Python 脚本
1
|
OPENSSL_CONF=openssl.cnf python3 demo.py
|
CERTIFICATE_VERIFY_FAILED
将 Python 脚本中所有的 requests 库的请求函数加上 verify=False
参数
1
|
print(requests.get(url=url, verify=False).content)
|
UNSUPPORTED_PROTOCOL
本机的 openssl 编译时未曾添加所需 TLS 支持
若是碰到低版本的 TLS 建议用 Ubuntu 16.04 这些老版本的系统进行命令操作
不然很可能得自己编译一个低版本的 openssl 来添加系统对低版本 TLS 的支持
首先要查看本地的 openssl 库对该网站的协议是否支持,命令及结果如下所示
1
2
3
4
5
|
# openssl s_client -help 2>&1 | awk '/-ssl[0-9]|-tls[0-9]/{print $1}'
-tls1
-tls1_1
-tls1_2
-tls1_3
|
接着要查看本地的 openssl 是否支持对应的加密方式
1
2
3
4
5
|
# openssl ciphers -s -v
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
...
|
但是如上两行命令也可能不能帮你获晓 openssl 对所需 TLS 提供支持的具体情况
可以选择用浏览器查看网站,再点击证书,或用 curl 命令来访问网址
这两种方式是都可以看到网站所用 TLS 版本信息及加密方式的
本机的 openssl 支持该 TLS 版本
可用 curl 先证明一下能否支持,如下是能够支持 TLS 的样例
1
2
3
4
5
6
7
8
|
# curl --insecure -vi https://example.com
* Rebuilt URL to: https://example.com/
* Trying xxx.xxx.xxx.xxx...
* Connected to example.com (xxx.xxx.xxx.xxx) port 443 (#0)
* found 129 certificates in /etc/ssl/certs/ca-certificates.crt
* found 516 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.0 / RSA_AES_256_CBC_SHA1
|
如下是不能支持该 TLS 的样例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# curl --insecure -vi https://example.com
* Rebuilt URL to: https://example.com/
* Trying xxx.xxx.xxx.xxx...
* Connected to example.com (xxx.xxx.xxx.xxx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (OUT), TLS header, Unknown (21):
* TLSv1.3 (OUT), TLS alert, protocol version (582):
* error:0A000102:SSL routines::unsupported protocol
* Closing connection 0
curl: (35) error:0A000102:SSL routines::unsupported protocol
|
新建一个 openssl.cnf
文件,内容如下
1
2
3
4
5
6
7
8
9
10
11
|
openssl_conf = openssl_init
[openssl_init]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1.0
CipherString = DEFAULT@SECLEVEL=1
|
之后更换 OPENSSL_CONF
环境变量运行 Python 脚本
1
|
OPENSSL_CONF=openssl.cnf python3 demo.py
|