Python3でTLSv1.3を使えるようにする

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 TL...

ほほぅ、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のみ対応のホストにもきちんと接続できるようになりました。お手軽ぅ!

コメント

タイトルとURLをコピーしました