Transport adapters not honored with proxy

オープン
#6,205 コメント 0 件 リアクション 2 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
42/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python
領域
networking

調査の方向性

まず、報告に示されているカスタム HTTPAdapter、SOCKS プロキシ、TLS 1.2 の設定で問題を再現します。直接リクエストとプロキシ経由のリクエストの経路を比較し、その後、既存のリクエスト動作を維持したまま、設定した TLS バージョンがプロキシ経由でも適用されることを確認します。

索引モデルが issue の本文から書いたものです。

説明

hi,

making a poor socks server at localhost on port 8001 with ssh/sshd running at localhost :

@term1$ ssh -N -D localhost:8001 localhost

making a self-signed certificate for testing and debuging negociations on server side with s_server@openssl :

@term2$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes 
        while :
        do
            echo -e "HTTP/1.0 200 OK\nContent-Length: 0\n\n" |
            openssl s_server -4 -cert cert.pem -key key.pem -accept 4433 -msg
        done

getting requests informations :

@term3$ python -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "charset_normalizer": {
    "version": "2.1.0"
  },
  "cryptography": {
    "version": "2.8"
  },
  "idna": {
    "version": "2.8"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.8.10"
  },
  "platform": {
    "release": "5.10.0-1057-oem",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "1010106f",
    "version": "19.0.0"
  },
  "requests": {
    "version": "2.28.1"
  },
  "system_ssl": {
    "version": "1010106f"
  },
  "urllib3": {
    "version": "1.25.8"
  },
  "using_charset_normalizer": false,
  "using_pyopenssl": true
}

running requests simply :

@term3$ python <<~~~
import requests
url = "https://localhost:4433/"
session = requests.Session()
response = session.head(url=url, verify=False)
~~~

TLS1.3 by default :

@term2$ ...
        <<< TLS 1.3, Handshake [length 0034], Finished
        ...
        >>> TLS 1.3, Handshake [length 00e9], NewSessionTicket
        ...

running requests with transport adapter only :

@term3$ python <<~~~
import ssl
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
class TestHTTPAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            ssl_version=ssl.PROTOCOL_TLSv1_2
        )
url = "https://localhost:4433/"
session = requests.Session()
session.mount(url, TestHTTPAdapter())
response = session.head(url=url, verify=False)
~~~

TLS1.2 is OK 🙂 :

@term2$ ...
        >>> TLS 1.2, Handshake [length 0010], Finished
        ...

running requests with transport adapter and socks proxy :

@term3$ python <<~~~
import ssl
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
class TestHTTPAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            ssl_version=ssl.PROTOCOL_TLSv1_2
        )
url = "https://localhost:4433/"
session = requests.Session()
session.mount(url, TestHTTPAdapter())
proxies={"https":"socks5://localhost:8001"}
response = session.head(url=url, proxies=proxies, verify=False)
~~~

TLS1.2 is KO 🙁 :

@term2$ ...
        <<< TLS 1.3, Handshake [length 0034], Finished
        ...
        >>> TLS 1.3, Handshake [length 00e9], NewSessionTicket
        ...

requests has the same behavior whether pyopenssl is present/used or not.
HTTP/HTTPS proxies not tested : sorry.

regards, lacsaP.


note that httpie works as expected :

@term4$ https --verify no https://localhost:4433
HTTP/1.0 200 OK
Content-Length: 0
@term2$ ...
        <<< TLS 1.3, Handshake [length 0034], Finished
        ...
        >>> TLS 1.3, Handshake [length 00e9], NewSessionTicket
        ...
@term4$ https --ssl tls1.2 --verify no https://localhost:4433
HTTP/1.0 200 OK
Content-Length: 0
@term2$ ...
        >>> TLS 1.2, Handshake [length 0010], Finished
        ...
@term4$ https --ssl tls1.2 --verify no --proxy https:socks5://localhost:8001 https://localhost:4433
HTTP/1.0 200 OK
Content-Length: 0
@term2$ ...
        >>> TLS 1.2, Handshake [length 0010], Finished
        ...

as well as urllib3 :

@term5$ python <<~~~
import urllib3
https = urllib3.PoolManager(cert_reqs='CERT_NONE')
r = https.request('GET', 'https://localhost:4433')
~~~
@term2$ ...
        <<< TLS 1.3, Handshake [length 0034], Finished
        ...
        >>> TLS 1.3, Handshake [length 00e9], NewSessionTicket
        ...
@term5$ python <<~~~
import ssl, urllib3
https = urllib3.PoolManager(cert_reqs='CERT_NONE', ssl_version=ssl.PROTOCOL_TLSv1_2)
r = https.request('GET', 'https://localhost:4433')
~~~
@term2$ ...
        >>> TLS 1.2, Handshake [length 0010], Finished
        ...
@term5$ python <<~~~
import ssl
from urllib3.contrib.socks import SOCKSProxyManager
socks = SOCKSProxyManager('socks5h://localhost:8001/', cert_reqs='CERT_NONE', ssl_version=ssl.PROTOCOL_TLSv1_2)
r = socks.request('GET', 'https://localhost:4433')
~~~
@term2$ ...
        >>> TLS 1.2, Handshake [length 0010], Finished
        ...
主要言語
Python
スター
54.7k
フォーク
10.8k
平均マージ
18分
マージ済み PR(30日)
1

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

psf/requests のほかの issue

psf/requests の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。