Python3でクロールしてるスクリプトがあるのですが、最近特定のサイトがなぜかエラーになるのに気づきまして。
なんとかしようとは思ったものの、この環境はopenssl 1.0.2kまでしか入っていない上に簡単に環境をいじれないので、ソースからのビルドなどでPython自体のバージョンを上げるのも難しいです。
さーて困ったなぁと思ってたところ、使ってる Requests の GitHub Issue にこんなコメントが。
Requests now forcing TLS 1.2 on Python 3.6.10 · Issue #5555 · psf/requests
Due to the changes in this PR that made it into release 2.24.0 our stack went from using TLS 1.3 through pyopenssl to TLS 1.2 through the new requests/ssl path ...
ほほぅ、Requests が使う ssl ではなく、TLSv1.3に対応している pyopenssl を優先的に使うようにすると。これが使えるなら手軽でいいなぁ…ということで、実際にそうなるのか試してみます。まず環境を整えて。
# python3 -V
Python 3.6.8
# python3 -m venv tlsv1.3test
# cd tlsv1.3test
# . bin/activate
(tlsv1.3test)# pip install -U pip
(tlsv1.3test)# pip install requests pyopenssl
(tlsv1.3test)# pip freeze
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.7
cryptography==35.0.0
idna==3.3
pycparser==2.20
pyOpenSSL==21.0.0
requests==2.26.0
six==1.16.0
urllib3==1.26.7
で、普通に Requests 使って SSL 接続の最高レベルを確認してみます。
(tlsv1.3test)# python
Python 3.6.8 (default, Nov 16 2020, 16:55:22)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get('https://www.howsmyssl.com/a/check').json()['tls_version']
'TLS 1.2'
TLS 1.2が最高の対応バージョンだと返ってきました。では先程の Issue コメントの通りに pyopenssl を inject してみます。
>>> from urllib3.contrib import pyopenssl
>>> pyopenssl.inject_into_urllib3()
>>> requests.get('https://www.howsmyssl.com/a/check').json()['tls_version']
'TLS 1.3'
おお、ほんとにTLS 1.3対応になった。
ということで、既存のコードを大きく変えることもなく、TLS 1.3のみ対応のホストにもきちんと接続できるようになりました。お手軽ぅ!
コメント