亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

解決Python Requests TLSv1握手失敗與服務(wù)器拒絕連接問(wèn)題

DDD
發(fā)布: 2025-10-16 12:53:01
原創(chuàng)
574人瀏覽過(guò)

解決Python Requests TLSv1握手失敗與服務(wù)器拒絕連接問(wèn)題

當(dāng)python `requests`庫(kù)在進(jìn)行https連接時(shí),如果客戶端的tls版本過(guò)低(如tlsv1.0),可能導(dǎo)致服務(wù)器拒絕連接并拋出`connectionreseterror`。本文將深入探討此問(wèn)題的原因,并提供一套完整的解決方案,包括如何強(qiáng)制指定tls協(xié)議版本、配置加密套件(cipher suites)以及正確處理ssl證書(shū)驗(yàn)證,以確保python應(yīng)用程序能夠與現(xiàn)代安全標(biāo)準(zhǔn)的服務(wù)器建立穩(wěn)定且安全的連接。

TLS握手失敗:客戶端為何使用舊版TLS?

在進(jìn)行HTTPS通信時(shí),客戶端和服務(wù)器之間需要通過(guò)TLS(Transport Layer Security)協(xié)議進(jìn)行握手,協(xié)商加密算法和會(huì)話密鑰。如果客戶端在Client Hello消息中提議的TLS版本過(guò)舊,而服務(wù)器已禁用該版本(例如,為了滿足PCI DSS等安全標(biāo)準(zhǔn),許多服務(wù)器不再支持TLSv1.0和TLSv1.1),則服務(wù)器會(huì)直接拒絕連接,導(dǎo)致客戶端收到ConnectionResetError。

常見(jiàn)問(wèn)題現(xiàn)象如下:

  • Wireshark捕獲分析:在網(wǎng)絡(luò)流量中,可以看到客戶端發(fā)送的Client Hello消息明確指出使用的TLS版本為T(mén)LSv1.0,而不是預(yù)期的TLSv1.2或TLSv1.3。
  • Python異常:應(yīng)用程序拋出ConnectionResetError: [Errno 104] Connection reset by peer,表明連接在建立初期就被對(duì)端重置。

即使Python環(huán)境中的OpenSSL庫(kù)是最新版本(例如OpenSSL 1.1.1w),Python的ssl模塊或requests庫(kù)的默認(rèn)行為有時(shí)仍可能導(dǎo)致使用較舊的TLS版本。這通常需要我們顯式地配置SSLContext來(lái)強(qiáng)制使用更安全的TLS協(xié)議。

診斷服務(wù)器支持的TLS版本與加密套件

在嘗試修復(fù)客戶端配置之前,了解目標(biāo)服務(wù)器支持的TLS版本和加密套件至關(guān)重要??梢允褂胦penssl s_client命令進(jìn)行診斷:

立即學(xué)習(xí)Python免費(fèi)學(xué)習(xí)筆記(深入)”;

openssl s_client -connect www.handlingandfulfilment.co.uk:443
登錄后復(fù)制

或者,如果服務(wù)運(yùn)行在非標(biāo)準(zhǔn)端口

openssl s_client -connect www.handlingandfulfilment.co.uk:8079
登錄后復(fù)制

該命令的輸出會(huì)顯示成功建立連接時(shí)使用的TLS版本和加密套件,例如:

New, TLSv1.2, Cipher is AES256-GCM-SHA384
登錄后復(fù)制

這表明服務(wù)器支持TLSv1.2,并且AES256-GCM-SHA384是一個(gè)可用的加密套件。這些信息將指導(dǎo)我們配置Python客戶端。

強(qiáng)制TLS版本與指定加密套件

Python的ssl模塊允許我們創(chuàng)建自定義的SSLContext,從而精細(xì)控制TLS握手行為。

AI建筑知識(shí)問(wèn)答
AI建筑知識(shí)問(wèn)答

用人工智能ChatGPT幫你解答所有建筑問(wèn)題

AI建筑知識(shí)問(wèn)答22
查看詳情 AI建筑知識(shí)問(wèn)答

1. 禁用舊版TLS協(xié)議

通過(guò)設(shè)置SSLContext的options屬性,可以禁用TLSv1.0和TLSv1.1:

import ssl

context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# 禁用TLS 1.0 和 TLS 1.1
context.options |= ssl.OP_NO_TLSv1
context.options |= ssl.OP_NO_TLSv1_1
# 對(duì)于更現(xiàn)代的應(yīng)用,也可以禁用TLS 1.2,強(qiáng)制TLS 1.3
# context.options |= ssl.OP_NO_TLSv1_2
登錄后復(fù)制

使用ssl.PROTOCOL_TLS_CLIENT是創(chuàng)建客戶端SSLContext的推薦方式,它會(huì)自動(dòng)設(shè)置一些合理的默認(rèn)值。

2. 指定加密套件

根據(jù)openssl s_client的診斷結(jié)果,我們可以使用set_ciphers方法來(lái)指定允許的加密套件。例如,如果服務(wù)器使用AES256-GCM-SHA384:

CIPHERS = 'ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384:!aNULL:!MD5'
context.set_ciphers(CIPHERS)
登錄后復(fù)制

這里的!aNULL:!MD5是常見(jiàn)的做法,用于排除不安全的匿名加密套件和使用MD5哈希的套件。

證書(shū)驗(yàn)證與certifi

在配置TLS版本和加密套件后,可能會(huì)遇到證書(shū)驗(yàn)證失敗的問(wèn)題。這是因?yàn)榭蛻舳诵枰粋€(gè)信任的根證書(shū)頒發(fā)機(jī)構(gòu)(CA)列表來(lái)驗(yàn)證服務(wù)器提供的證書(shū)。certifi庫(kù)提供了一個(gè)最新的、經(jīng)過(guò)Mozilla維護(hù)的CA證書(shū)包,可以很方便地集成到SSLContext中:

import certifi
context.load_verify_locations(certifi.where())
登錄后復(fù)制

將配置應(yīng)用于requests和zeep

對(duì)于使用requests庫(kù)(或其上層庫(kù)如zeep)的應(yīng)用程序,最優(yōu)雅的解決方案是創(chuàng)建一個(gè)自定義的HTTPAdapter。

import certifi
import requests
from requests.adapters import HTTPAdapter, Retry
from urllib3 import PoolManager
from urllib3.util.ssl_ import create_urllib3_context
from zeep import Client
from zeep.transports import Transport
from dataclasses import dataclass, field

# 定義所需的加密套件
CIPHERS = 'ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384:!aNULL:!MD5'

class TLSAdapter(HTTPAdapter):
    """
    自定義HTTPAdapter,用于強(qiáng)制TLS版本、指定加密套件和加載certifi證書(shū)。
    """
    def init_poolmanager(self, *args, **kwargs):
        # 創(chuàng)建一個(gè)帶有指定加密套件的SSL上下文
        context = create_urllib3_context(ciphers=CIPHERS)

        # 加載certifi提供的CA證書(shū)
        context.load_verify_locations(certifi.where())

        # 再次設(shè)置加密套件,確保生效
        context.set_ciphers(CIPHERS)

        # 禁用TLS 1.0 和 TLS 1.1
        # SSL_OP_NO_TLSv1 (0x80000) 和 SSL_OP_NO_TLSv1_1 (0x1000000) 是OpenSSL的選項(xiàng)標(biāo)志
        context.options |= 0x80000  # ssl.OP_NO_TLSv1
        context.options |= 0x1000000 # ssl.OP_NO_TLSv1_1

        # 將自定義的SSL上下文傳遞給urllib3的PoolManager
        self.poolmanager = PoolManager(*args, ssl_context=context, **kwargs)

def requests_retry_session(
    retries=8,
    backoff_factor=0.3,
    status_forcelist=(500, 502, 503, 504),
    session=None,
) -> requests.Session:
    """
    創(chuàng)建一個(gè)帶有重試機(jī)制和自定義TLS配置的requests會(huì)話。
    """
    session = session or requests.Session()
    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
    )
    # 使用自定義的TLSAdapter掛載到http和https協(xié)議上
    adapter = TLSAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session

# 示例:如何將此會(huì)話用于zeep客戶端
@dataclass(order=True)
class ArkH:
    wsdl_url: str
    consumerName: str
    passCode: str
    helixClientName: str
    helixUsername: str
    userPassword: str
    client: Client = field(init=False)
    dummyCustomer: str
    dummy_customer_mapping: dict = field(default_factory=lambda: {'CTS':'CTS'})
    dear_warehouse: str
    dear_ship_after_3PL_shipment_date: bool

    def __post_init__(self):
        # 創(chuàng)建一個(gè)帶有自定義TLS配置和重試機(jī)制的requests會(huì)話
        session = requests_retry_session()
        # 將此會(huì)話傳遞給Zeep的Transport
        transport = Transport(session=session, timeout=40, operation_timeout=40)
        self.client = Client(self.wsdl_url, transport=transport)

# 實(shí)際使用示例 (假設(shè)你有一個(gè)WSDL URL)
# ark_client = ArkH(
#     wsdl_url='https://www.handlingandfulfilment.co.uk:8079/YourService?wsdl',
#     consumerName='your_consumer',
#     passCode='your_passcode',
#     helixClientName='your_helix_client',
#     helixUsername='your_helix_username',
#     userPassword='your_user_password',
#     dummyCustomer='CTS',
#     dear_warehouse='main',
#     dear_ship_after_3PL_shipment_date=True
# )
# print("Zeep client initialized with custom TLS settings.")
登錄后復(fù)制

注意事項(xiàng)與最佳實(shí)踐

  1. OpenSSL版本:確保你的Python環(huán)境使用的OpenSSL庫(kù)是最新且安全的版本。Python的ssl模塊通常會(huì)綁定到系統(tǒng)安裝的OpenSSL庫(kù)。
  2. Cipher Suites選擇:選擇加密套件時(shí),應(yīng)優(yōu)先考慮安全性和兼容性。openssl s_client是一個(gè)很好的起點(diǎn),但應(yīng)避免過(guò)度限制,除非有明確的安全要求。
  3. 證書(shū)更新:certifi庫(kù)應(yīng)定期更新,以確保包含最新的可信CA證書(shū)。
  4. 錯(cuò)誤處理:即使配置了正確的TLS版本和加密套件,網(wǎng)絡(luò)問(wèn)題、服務(wù)器端配置變更等仍可能導(dǎo)致連接失敗。在應(yīng)用程序中實(shí)現(xiàn)健壯的錯(cuò)誤處理和重試機(jī)制(如requests_retry_session所示)是必不可少的。
  5. 調(diào)試:當(dāng)遇到TLS問(wèn)題時(shí),啟用requests和urllib3的調(diào)試日志可以提供詳細(xì)的握手信息,幫助診斷問(wèn)題:
    import logging
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True
    登錄后復(fù)制

總結(jié)

解決Python requests或zeep連接中因TLS版本過(guò)舊導(dǎo)致的ConnectionResetError,關(guān)鍵在于顯式地配置SSLContext。這包括禁用不安全的TLS協(xié)議版本(如TLSv1.0和TLSv1.1)、指定服務(wù)器支持的加密套件,以及利用certifi庫(kù)確保正確的證書(shū)驗(yàn)證。通過(guò)創(chuàng)建自定義的HTTPAdapter并將其掛載到requests.Session上,可以優(yōu)雅且一致地將這些安全配置應(yīng)用到整個(gè)應(yīng)用程序的HTTP/HTTPS請(qǐng)求中,從而提高連接的穩(wěn)定性和安全性。

以上就是解決Python Requests TLSv1握手失敗與服務(wù)器拒絕連接問(wèn)題的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!

最佳 Windows 性能的頂級(jí)免費(fèi)優(yōu)化軟件
最佳 Windows 性能的頂級(jí)免費(fèi)優(yōu)化軟件

每個(gè)人都需要一臺(tái)速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊(cè)表數(shù)據(jù)和不必要的后臺(tái)進(jìn)程會(huì)占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。

下載
來(lái)源:php中文網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn
最新問(wèn)題
開(kāi)源免費(fèi)商場(chǎng)系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見(jiàn)反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)